1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef COMPILER_OPTIMIZER_IR_GRAPH_CHECKER_H
17 #define COMPILER_OPTIMIZER_IR_GRAPH_CHECKER_H
18
19 #include <iostream>
20 #include "compiler_options.h"
21 #include "graph.h"
22 #include "graph_visitor.h"
23 #include "optimizer/analysis/dominators_tree.h"
24 #include "optimizer/analysis/rpo.h"
25 #include "optimizer/analysis/loop_analyzer.h"
26 #include "optimizer/optimizations/cleanup.h"
27
28 namespace panda::compiler {
operator <<(std::ostream &os, const std::initializer_list<Opcode> &opcs)29 inline std::ostream &operator<<(std::ostream &os, const std::initializer_list<Opcode> &opcs)
30 {
31 os << "[ ";
32 for (auto opc : opcs) {
33 os << GetOpcodeString(opc) << " ";
34 }
35 os << "]";
36 return os;
37 }
38
39 class GraphChecker : public GraphVisitor {
40 public:
41 explicit GraphChecker(Graph *graph);
42 ~GraphChecker() override
43 {
44 GetGraph()->GetPassManager()->SetCheckMode(false);
45 }
46
47 NO_COPY_SEMANTIC(GraphChecker);
48 NO_MOVE_SEMANTIC(GraphChecker);
49
50 void Check();
51
52 private:
53 void PreCloneChecks(Graph *graph);
54 void UserInputCheck(Graph *graph);
55 void CheckBlock(BasicBlock *block);
56 void CheckDomTree();
57 void CheckLoopAnalysis();
58 void CheckStartBlock();
59 void CheckEndBlock();
60 void CheckControlFlow(BasicBlock *block);
61 void CheckDataFlow(BasicBlock *block);
62 void CheckPhiInputs(Inst *phi_inst);
63 void CheckInstsRegisters(BasicBlock *block);
64 void CheckPhisRegisters(BasicBlock *block);
65 void CheckNoLowLevel(BasicBlock *block);
66 void CheckLoops();
67 void CheckGraph();
68 bool HasOuterInfiniteLoop();
69 bool CheckInstHasInput(Inst *inst, Inst *input);
70 bool CheckInstHasUser(Inst *inst, Inst *user);
71 void CheckCallReturnInlined();
72 void CheckSpillFillHolder(Inst *inst);
73 bool CheckInstRegUsageSaved(const Inst *inst, Register reg) const;
74 void MarkBlocksInLoop(Loop *loop, Marker mrk);
75 bool CheckBlockHasPredecessor(BasicBlock *block, BasicBlock *predecessor);
76 bool CheckBlockHasSuccessor(BasicBlock *block, BasicBlock *successor);
77 void CheckLoopHasSafePoint(Loop *loop);
78 void CheckBlockEdges(const BasicBlock &block);
79 void CheckTryBeginBlock(const BasicBlock &block);
80 void CheckJump(const BasicBlock &block);
81 bool IsTryCatchDomination(const BasicBlock *input_block, const BasicBlock *user_block) const;
82 #ifndef NDEBUG
83 bool NeedCheckSaveState();
84 #endif // !NDEBUG
85 void CheckSaveStateInputs();
86 void CheckObjectRec(const Inst *object, const Inst *user, const BasicBlock *block, Inst *start_from,
87 Marker visited) const;
88 void FindObjectInSaveState(const Inst *object, Inst *ss) const;
89 void CheckSaveStatesWithRuntimeCallUsers();
90 void CheckSaveStateOsrRec(const Inst *inst, const Inst *user, BasicBlock *block, Marker visited);
91
GetGraph() const92 Graph *GetGraph() const
93 {
94 return graph_;
95 }
96
GetAllocator()97 ArenaAllocator *GetAllocator()
98 {
99 return &allocator_;
100 }
101
GetLocalAllocator()102 ArenaAllocator *GetLocalAllocator()
103 {
104 return &local_allocator_;
105 }
106
107 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override
108 {
109 return GetGraph()->GetBlocksRPO();
110 }
111
112 /*
113 * Visitors to check instructions types
114 */
115 static void VisitReturn([[maybe_unused]] GraphVisitor *v, Inst *inst);
116 static void VisitIf([[maybe_unused]] GraphVisitor *v, Inst *inst);
117 static void VisitIfImm([[maybe_unused]] GraphVisitor *v, Inst *inst);
118 #include "visitor.inc"
119
CheckCommonTypes(Inst *inst1, Inst *inst2)120 static bool CheckCommonTypes(Inst *inst1, Inst *inst2)
121 {
122 if (inst1->GetBasicBlock()->GetGraph()->IsDynamicMethod() &&
123 (inst1->GetType() == DataType::ANY || inst2->GetType() == DataType::ANY)) {
124 return true;
125 }
126 DataType::Type type1 = inst1->GetType();
127 DataType::Type type2 = inst2->GetType();
128 return DataType::GetCommonType(type1) == DataType::GetCommonType(type2);
129 }
130 private:
131 Graph *graph_;
132 ArenaAllocator allocator_ {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
133 ArenaAllocator local_allocator_ {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
134 int null_ptr_inst_counter_ = 0;
135 };
136 } // namespace panda::compiler
137
138 #endif // COMPILER_OPTIMIZER_IR_GRAPH_CHECKER_H
139