1 /* 2 * Copyright (c) 2021-2023 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_OPTIMIZATIONS_DEOPTIMIZEELIMINATION_H 17 #define COMPILER_OPTIMIZER_OPTIMIZATIONS_DEOPTIMIZEELIMINATION_H 18 19 #include "compiler_logger.h" 20 #include "optimizer/ir/graph.h" 21 #include "optimizer/pass.h" 22 #include "optimizer/analysis/bounds_analysis.h" 23 #include "optimizer/analysis/loop_analyzer.h" 24 #include "optimizer/ir/graph_visitor.h" 25 26 namespace panda::compiler { 27 // NOLINTNEXTLINE(fuchsia-multiple-inheritance) 28 class DeoptimizeElimination : public Optimization, public GraphVisitor { 29 using Optimization::Optimization; 30 31 public: DeoptimizeElimination(Graph * graph)32 explicit DeoptimizeElimination(Graph *graph) 33 : Optimization(graph), 34 blocksType_(graph->GetLocalAllocator()->Adapter()), 35 deoptimizeMustThrow_(graph->GetLocalAllocator()->Adapter()) 36 { 37 } 38 39 NO_MOVE_SEMANTIC(DeoptimizeElimination); 40 NO_COPY_SEMANTIC(DeoptimizeElimination); 41 ~DeoptimizeElimination() override = default; 42 43 bool RunImpl() override; 44 GetPassName()45 const char *GetPassName() const override 46 { 47 return "DeoptimizeElimination"; 48 } 49 50 void InvalidateAnalyses() override; 51 IsEnable()52 bool IsEnable() const override 53 { 54 return g_options.IsCompilerDeoptimizeElimination(); 55 } 56 57 void ReplaceDeoptimizeIfByUnconditionalDeoptimize(); 58 59 void RemoveSafePoints(); 60 61 /* 62 * By default all blocks have INVALID_TYPE. 63 * GUARD - If block have IsMustDeootimize before runtime call inst(in reverse order) 64 * RUNTIME_CALL - If block have runtime call inst before IsMustDeoptimize(in reverse order) 65 * NOTHING - If block is preccessed, but it doesn't contain GUARD and RUNTIME_CALL 66 */ 67 enum BlockType { INVALID, GUARD, RUNTIME_CALL, NOTHING }; 68 GetBlocksToVisit()69 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override 70 { 71 return GetGraph()->GetBlocksRPO(); 72 } 73 SetApplied()74 void SetApplied() 75 { 76 isApplied_ = true; 77 } 78 IsApplied()79 bool IsApplied() const 80 { 81 return isApplied_; 82 } 83 SetLoopDeleted()84 void SetLoopDeleted() 85 { 86 isLoopDeleted_ = true; 87 } 88 IsLoopDeleted()89 bool IsLoopDeleted() const 90 { 91 return isLoopDeleted_; 92 } 93 HaveCalls()94 bool HaveCalls() 95 { 96 return haveCalls_; 97 } 98 99 #include <deoptimize_elimination_call_visitors.inl> 100 static void VisitSaveState(GraphVisitor *v, Inst *inst); 101 static void VisitSaveStateDeoptimize(GraphVisitor *v, Inst *inst); 102 static void VisitDeoptimizeIf(GraphVisitor *v, Inst *inst); 103 void VisitDefault(Inst *inst) override; 104 105 #include "optimizer/ir/visitor.inc" 106 107 private: SetHaveCalls()108 void SetHaveCalls() 109 { 110 haveCalls_ = true; 111 } 112 PushNewDeoptimizeIf(Inst * inst)113 void PushNewDeoptimizeIf(Inst *inst) 114 { 115 deoptimizeMustThrow_.push_back(inst); 116 } 117 PushNewBlockType(BasicBlock * block,BlockType type)118 void PushNewBlockType(BasicBlock *block, BlockType type) 119 { 120 ASSERT(blocksType_.find(block) == blocksType_.end()); 121 blocksType_.emplace(block, type); 122 } 123 GetBlockType(BasicBlock * block)124 BlockType GetBlockType(BasicBlock *block) 125 { 126 if (blocksType_.find(block) != blocksType_.end()) { 127 return blocksType_.at(block); 128 } 129 return BlockType::INVALID; 130 } 131 132 bool TryToRemoveRedundantSaveState(Inst *inst); 133 bool CanRemoveGuard(Inst *guard); 134 bool CanRemoveGuardRec(BasicBlock *block, Inst *guard, const Marker &mrk, const Marker &removeMrk); 135 void RemoveGuard(Inst *guard); 136 void RemoveDeoptimizeIf(Inst *inst); 137 bool RequireRegMap(Inst *inst); 138 139 private: 140 bool haveCalls_ {false}; 141 bool isApplied_ {false}; 142 bool isLoopDeleted_ {false}; 143 ArenaUnorderedMap<BasicBlock *, BlockType> blocksType_; 144 InstVector deoptimizeMustThrow_; 145 }; 146 } // namespace panda::compiler 147 148 #endif // COMPILER_OPTIMIZER_OPTIMIZATIONS_DEOPTIMIZEELIMINATION_H 149