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_OPTIMIZATIONS_INLINING_H_ 17 #define COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINING_H_ 18 19 #include <string> 20 #include "optimizer/pass.h" 21 #include "optimizer/ir/inst.h" 22 #include "optimizer/ir/runtime_interface.h" 23 #include "compiler_options.h" 24 #include "utils/arena_containers.h" 25 26 namespace panda::compiler { 27 struct InlineContext { 28 RuntimeInterface::MethodPtr method {}; 29 bool cha_devirtualize {false}; 30 bool replace_to_static {false}; 31 }; 32 33 struct InlinedGraph { 34 Graph *graph {nullptr}; 35 bool has_runtime_calls {false}; 36 }; 37 38 class Inlining : public Optimization { 39 static constexpr size_t SMALL_METHOD_MAX_SIZE = 5; 40 41 public: Inlining(Graph * graph)42 explicit Inlining(Graph *graph) : Inlining(graph, 0, 0, 0) {} 43 44 Inlining(Graph *graph, uint32_t instructions_count, uint32_t inline_depth, uint32_t methods_inlined); 45 46 NO_MOVE_SEMANTIC(Inlining); 47 NO_COPY_SEMANTIC(Inlining); 48 ~Inlining() override = default; 49 50 bool RunImpl() override; 51 IsEnable()52 bool IsEnable() const override 53 { 54 return options.IsCompilerInlining(); 55 } 56 GetPassName()57 const char *GetPassName() const override 58 { 59 return "Inline"; 60 } 61 62 void InvalidateAnalyses() override; 63 64 private: 65 bool TryInline(CallInst *call_inst); 66 bool TryInlineWithInlineCaches(CallInst *call_inst); 67 bool TryInlineExternal(CallInst *call_inst, InlineContext *ctx); 68 bool TryInlineExternalAot(CallInst *call_inst, InlineContext *ctx); 69 70 Inst *GetNewDefAndCorrectDF(Inst *call_inst, Inst *old_def); 71 72 bool DoInline(CallInst *call_inst, InlineContext *ctx); 73 bool DoInlineMonomorphic(CallInst *call_inst, RuntimeInterface::ClassPtr receiver); 74 bool DoInlinePolymorphic(CallInst *call_inst); 75 void CreateCompareClass(CallInst *call_inst, Inst *get_cls_inst, RuntimeInterface::ClassPtr receiver, 76 BasicBlock *call_bb); 77 void InsertDeoptimizeInst(CallInst *call_inst, BasicBlock *call_bb); 78 void InsertPolymorphicGraph(InlinedGraph inl_graph, BasicBlock *call_bb, PhiInst *phi_inst, CallInst *call_inst, 79 CallInst *new_call_inst); 80 81 void UpdateDataflow(Graph *graph_inl, Inst *call_inst, std::variant<BasicBlock *, PhiInst *> use, 82 Inst *new_def = nullptr); 83 void UpdateControlflow(Graph *graph_inl, BasicBlock *call_bb, BasicBlock *call_cont_bb); 84 void MoveConstants(Graph *graph_inl); 85 86 template <bool check_external> 87 bool CheckMethodCanBeInlined(const CallInst *call_inst, InlineContext *ctx); 88 bool ResolveTarget(CallInst *call_inst, InlineContext *ctx); 89 void InsertChaGuard(CallInst *call_inst); 90 91 InlinedGraph BuildGraph(InlineContext *ctx, CallInst *call_inst, CallInst *poly_call_inst = nullptr); 92 bool CheckBytecode(const InlineContext &ctx, bool *callee_call_runtime, CallInst *call_inst); 93 bool CheckInsrtuctionLimitAndCallInline(InlineContext *ctx, Graph *graph_inl, CallInst *call_inst); 94 bool TryBuildGraph(const InlineContext &ctx, Graph *graph_inl, CallInst *call_inst, CallInst *poly_call_inst); 95 bool CheckLoops(bool *callee_call_runtime, Graph *graph_inl); 96 static void PropagateObjectInfo(Graph *graph_inl, CallInst *call_inst); 97 98 void ProcessCallReturnInstructions(CallInst *call_inst, BasicBlock *call_cont_bb, bool has_runtime_calls, 99 bool need_barriers = false); 100 GetCha()101 IClassHierarchyAnalysis *GetCha() 102 { 103 return cha_; 104 } 105 106 bool IsInlineCachesEnabled() const; 107 GetLogIndent()108 std::string GetLogIndent() const 109 { 110 return std::string(depth_ * 2, ' '); 111 } 112 113 bool SkipBlock(const BasicBlock *block) const; 114 115 private: 116 IClassHierarchyAnalysis *cha_ {nullptr}; 117 ArenaUnorderedSet<std::string> blacklist_; 118 ArenaVector<BasicBlock *> return_blocks_; 119 ArenaVector<RuntimeInterface::ClassPtr> recievers_; 120 uint32_t instructions_count_ {0}; 121 uint32_t depth_ {0}; 122 uint32_t methods_inlined_ {0}; 123 uint32_t vregs_count_ {0}; 124 }; 125 } // namespace panda::compiler 126 127 #endif // COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINING_H_ 128