• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage,-warnings-as-errors)
27 #define LOG_INLINING(level) COMPILER_LOG(level, INLINING) << GetLogIndent()
28 
29 namespace panda::compiler {
30 struct InlineContext {
31     RuntimeInterface::MethodPtr method {};
32     bool chaDevirtualize {false};
33     bool replaceToStatic {false};
34     RuntimeInterface::IntrinsicId intrinsicId {RuntimeInterface::IntrinsicId::INVALID};
35 };
36 
37 struct InlinedGraph {
38     Graph *graph {nullptr};
39     bool hasRuntimeCalls {false};
40 };
41 
42 class Inlining : public Optimization {
43     static constexpr size_t SMALL_METHOD_MAX_SIZE = 5;
44 
45 public:
Inlining(Graph * graph)46     explicit Inlining(Graph *graph) : Inlining(graph, 0, 0, 0) {}
Inlining(Graph * graph,bool resolveWoInline)47     Inlining(Graph *graph, bool resolveWoInline) : Inlining(graph)
48     {
49         resolveWoInline_ = resolveWoInline;
50     }
51 
52     Inlining(Graph *graph, uint32_t instructionsCount, uint32_t inlineDepth, uint32_t methodsInlined);
53 
54     NO_MOVE_SEMANTIC(Inlining);
55     NO_COPY_SEMANTIC(Inlining);
56     ~Inlining() override = default;
57 
58     bool RunImpl() override;
59 
IsEnable()60     bool IsEnable() const override
61     {
62         return g_options.IsCompilerInlining();
63     }
64 
GetPassName()65     const char *GetPassName() const override
66     {
67         return "Inline";
68     }
69 
70     void InvalidateAnalyses() override;
71 
72 protected:
73     virtual void RunOptimizations() const;
74     virtual bool IsInstSuitableForInline(Inst *inst) const;
75     virtual bool TryInline(CallInst *callInst);
76     bool TryInlineWithInlineCaches(CallInst *callInst);
77     bool TryInlineExternal(CallInst *callInst, InlineContext *ctx);
78     bool TryInlineExternalAot(CallInst *callInst, InlineContext *ctx);
79 
80     Inst *GetNewDefAndCorrectDF(Inst *callInst, Inst *oldDef);
81 
82     bool Do();
83     bool DoInline(CallInst *callInst, InlineContext *ctx);
84     bool DoInlineMethod(CallInst *callInst, InlineContext *ctx);
85     bool DoInlineIntrinsic(CallInst *callInst, InlineContext *ctx);
86     bool DoInlineMonomorphic(CallInst *callInst, RuntimeInterface::ClassPtr receiver);
87     bool DoInlinePolymorphic(CallInst *callInst, ArenaVector<RuntimeInterface::ClassPtr> *receivers);
88     void CreateCompareClass(CallInst *callInst, Inst *getClsInst, RuntimeInterface::ClassPtr receiver,
89                             BasicBlock *callBb);
90     void InsertDeoptimizeInst(CallInst *callInst, BasicBlock *callBb,
91                               DeoptimizeType deoptType = DeoptimizeType::INLINE_IC);
92     void InsertCallInst(CallInst *callInst, BasicBlock *callBb, BasicBlock *retBb, Inst *phiInst);
93 
94     void UpdateDataflow(Graph *graphInl, Inst *callInst, std::variant<BasicBlock *, PhiInst *> use,
95                         Inst *newDef = nullptr);
96     void UpdateDataflowForEmptyGraph(Inst *callInst, std::variant<BasicBlock *, PhiInst *> use, BasicBlock *endBlock);
97     void UpdateParameterDataflow(Graph *graphInl, Inst *callInst);
98     void UpdateControlflow(Graph *graphInl, BasicBlock *callBb, BasicBlock *callContBb);
99     void MoveConstants(Graph *graphInl);
100 
101     template <bool CHECK_EXTERNAL, bool CHECK_INTRINSICS = false>
102     bool CheckMethodCanBeInlined(const CallInst *callInst, InlineContext *ctx);
103     template <bool CHECK_EXTERNAL>
104     bool CheckTooBigMethodCanBeInlined(const CallInst *callInst, InlineContext *ctx, bool methodIsTooBig);
105     bool ResolveTarget(CallInst *callInst, InlineContext *ctx);
106     bool CanUseTypeInfo(ObjectTypeInfo typeInfo, RuntimeInterface::MethodPtr method);
107     void InsertChaGuard(CallInst *callInst);
108 
109     InlinedGraph BuildGraph(InlineContext *ctx, CallInst *callInst, CallInst *polyCallInst = nullptr);
110     bool CheckBytecode(CallInst *callInst, const InlineContext &ctx, bool *calleeCallRuntime);
111     bool CheckInstructionLimit(CallInst *callInst, InlineContext *ctx, size_t inlinedInstsCount);
112     bool TryBuildGraph(const InlineContext &ctx, Graph *graphInl, CallInst *callInst, CallInst *polyCallInst);
113     bool CheckLoops(bool *calleeCallRuntime, Graph *graphInl);
114     static void PropagateObjectInfo(Graph *graphInl, CallInst *callInst);
115 
116     void ProcessCallReturnInstructions(CallInst *callInst, BasicBlock *callContBb, bool hasRuntimeCalls,
117                                        bool needBarriers = false);
118     size_t CalculateInstructionsCount(Graph *graph);
119 
GetCha()120     IClassHierarchyAnalysis *GetCha()
121     {
122         return cha_;
123     }
124 
125     bool IsInlineCachesEnabled() const;
126 
GetLogIndent()127     std::string GetLogIndent() const
128     {
129         return std::string(depth_ * 2U, ' ');
130     }
131 
IsIntrinsic(const InlineContext * ctx)132     bool IsIntrinsic(const InlineContext *ctx) const
133     {
134         return ctx->intrinsicId != RuntimeInterface::IntrinsicId::INVALID;
135     }
136 
137     virtual bool SkipBlock(const BasicBlock *block) const;
138 
139 protected:
140     // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
141     uint32_t depth_ {0};
142     uint32_t methodsInlined_ {0};
143     uint32_t instructionsCount_ {0};
144     uint32_t instructionsLimit_ {0};
145     ArenaVector<BasicBlock *> returnBlocks_;
146     ArenaUnorderedSet<std::string> blacklist_;
147     // NOLINTEND(misc-non-private-member-variables-in-classes)
148 
149 private:
150     uint32_t vregsCount_ {0};
151     bool resolveWoInline_ {false};
152     IClassHierarchyAnalysis *cha_ {nullptr};
153 };
154 }  // namespace panda::compiler
155 
156 #endif  // COMPILER_OPTIMIZER_OPTIMIZATIONS_INLINING_H
157