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 { 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); ~GraphChecker()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()92 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 GetBlocksToVisit()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