xref: /aosp_15_r20/art/compiler/optimizing/inliner.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_OPTIMIZING_INLINER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_INLINER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
22*795d594fSAndroid Build Coastguard Worker #include "dex/invoke_type.h"
23*795d594fSAndroid Build Coastguard Worker #include "jit/profiling_info.h"
24*795d594fSAndroid Build Coastguard Worker #include "optimization.h"
25*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker class CodeGenerator;
30*795d594fSAndroid Build Coastguard Worker class DexCompilationUnit;
31*795d594fSAndroid Build Coastguard Worker class HGraph;
32*795d594fSAndroid Build Coastguard Worker class HInvoke;
33*795d594fSAndroid Build Coastguard Worker class OptimizingCompilerStats;
34*795d594fSAndroid Build Coastguard Worker 
35*795d594fSAndroid Build Coastguard Worker class HInliner : public HOptimization {
36*795d594fSAndroid Build Coastguard Worker  public:
37*795d594fSAndroid Build Coastguard Worker   HInliner(HGraph* outer_graph,
38*795d594fSAndroid Build Coastguard Worker            HGraph* outermost_graph,
39*795d594fSAndroid Build Coastguard Worker            CodeGenerator* codegen,
40*795d594fSAndroid Build Coastguard Worker            const DexCompilationUnit& outer_compilation_unit,
41*795d594fSAndroid Build Coastguard Worker            const DexCompilationUnit& caller_compilation_unit,
42*795d594fSAndroid Build Coastguard Worker            OptimizingCompilerStats* stats,
43*795d594fSAndroid Build Coastguard Worker            size_t total_number_of_dex_registers,
44*795d594fSAndroid Build Coastguard Worker            size_t total_number_of_instructions,
45*795d594fSAndroid Build Coastguard Worker            HInliner* parent,
46*795d594fSAndroid Build Coastguard Worker            HEnvironment* caller_environment,
47*795d594fSAndroid Build Coastguard Worker            size_t depth,
48*795d594fSAndroid Build Coastguard Worker            bool try_catch_inlining_allowed,
49*795d594fSAndroid Build Coastguard Worker            const char* name = kInlinerPassName)
HOptimization(outer_graph,name,stats)50*795d594fSAndroid Build Coastguard Worker       : HOptimization(outer_graph, name, stats),
51*795d594fSAndroid Build Coastguard Worker         outermost_graph_(outermost_graph),
52*795d594fSAndroid Build Coastguard Worker         outer_compilation_unit_(outer_compilation_unit),
53*795d594fSAndroid Build Coastguard Worker         caller_compilation_unit_(caller_compilation_unit),
54*795d594fSAndroid Build Coastguard Worker         codegen_(codegen),
55*795d594fSAndroid Build Coastguard Worker         total_number_of_dex_registers_(total_number_of_dex_registers),
56*795d594fSAndroid Build Coastguard Worker         total_number_of_instructions_(total_number_of_instructions),
57*795d594fSAndroid Build Coastguard Worker         parent_(parent),
58*795d594fSAndroid Build Coastguard Worker         caller_environment_(caller_environment),
59*795d594fSAndroid Build Coastguard Worker         depth_(depth),
60*795d594fSAndroid Build Coastguard Worker         inlining_budget_(0),
61*795d594fSAndroid Build Coastguard Worker         try_catch_inlining_allowed_(try_catch_inlining_allowed),
62*795d594fSAndroid Build Coastguard Worker         run_extra_type_propagation_(false),
63*795d594fSAndroid Build Coastguard Worker         inline_stats_(nullptr) {}
64*795d594fSAndroid Build Coastguard Worker 
65*795d594fSAndroid Build Coastguard Worker   bool Run() override;
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kInlinerPassName = "inliner";
68*795d594fSAndroid Build Coastguard Worker 
GetParent()69*795d594fSAndroid Build Coastguard Worker   const HInliner* GetParent() const { return parent_; }
GetCallerEnvironment()70*795d594fSAndroid Build Coastguard Worker   const HEnvironment* GetCallerEnvironment() const { return caller_environment_; }
71*795d594fSAndroid Build Coastguard Worker 
GetOutermostGraph()72*795d594fSAndroid Build Coastguard Worker   const HGraph* GetOutermostGraph() const { return outermost_graph_; }
GetGraph()73*795d594fSAndroid Build Coastguard Worker   const HGraph* GetGraph() const { return graph_; }
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker  private:
76*795d594fSAndroid Build Coastguard Worker   enum InlineCacheType {
77*795d594fSAndroid Build Coastguard Worker     kInlineCacheNoData = 0,
78*795d594fSAndroid Build Coastguard Worker     kInlineCacheUninitialized = 1,
79*795d594fSAndroid Build Coastguard Worker     kInlineCacheMonomorphic = 2,
80*795d594fSAndroid Build Coastguard Worker     kInlineCachePolymorphic = 3,
81*795d594fSAndroid Build Coastguard Worker     kInlineCacheMegamorphic = 4,
82*795d594fSAndroid Build Coastguard Worker     kInlineCacheMissingTypes = 5
83*795d594fSAndroid Build Coastguard Worker   };
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker   bool TryInline(HInvoke* invoke_instruction);
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker   // Try to inline `resolved_method` in place of `invoke_instruction`. `do_rtp` is whether
88*795d594fSAndroid Build Coastguard Worker   // reference type propagation can run after the inlining. If the inlining is successful, this
89*795d594fSAndroid Build Coastguard Worker   // method will replace and remove the `invoke_instruction`.
90*795d594fSAndroid Build Coastguard Worker   bool TryInlineAndReplace(HInvoke* invoke_instruction,
91*795d594fSAndroid Build Coastguard Worker                            ArtMethod* resolved_method,
92*795d594fSAndroid Build Coastguard Worker                            ReferenceTypeInfo receiver_type,
93*795d594fSAndroid Build Coastguard Worker                            bool do_rtp,
94*795d594fSAndroid Build Coastguard Worker                            bool is_speculative)
95*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker   bool TryBuildAndInline(HInvoke* invoke_instruction,
98*795d594fSAndroid Build Coastguard Worker                          ArtMethod* resolved_method,
99*795d594fSAndroid Build Coastguard Worker                          ReferenceTypeInfo receiver_type,
100*795d594fSAndroid Build Coastguard Worker                          HInstruction** return_replacement,
101*795d594fSAndroid Build Coastguard Worker                          bool is_speculative)
102*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker   bool TryBuildAndInlineHelper(HInvoke* invoke_instruction,
105*795d594fSAndroid Build Coastguard Worker                                ArtMethod* resolved_method,
106*795d594fSAndroid Build Coastguard Worker                                ReferenceTypeInfo receiver_type,
107*795d594fSAndroid Build Coastguard Worker                                HInstruction** return_replacement,
108*795d594fSAndroid Build Coastguard Worker                                bool is_speculative)
109*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
110*795d594fSAndroid Build Coastguard Worker 
111*795d594fSAndroid Build Coastguard Worker   // Substitutes parameters in the callee graph with their values from the caller.
112*795d594fSAndroid Build Coastguard Worker   void SubstituteArguments(HGraph* callee_graph,
113*795d594fSAndroid Build Coastguard Worker                            HInvoke* invoke_instruction,
114*795d594fSAndroid Build Coastguard Worker                            ReferenceTypeInfo receiver_type,
115*795d594fSAndroid Build Coastguard Worker                            const DexCompilationUnit& dex_compilation_unit)
116*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker   // Run simple optimizations on `callee_graph`.
119*795d594fSAndroid Build Coastguard Worker   void RunOptimizations(HGraph* callee_graph,
120*795d594fSAndroid Build Coastguard Worker                         HEnvironment* caller_environment,
121*795d594fSAndroid Build Coastguard Worker                         const dex::CodeItem* code_item,
122*795d594fSAndroid Build Coastguard Worker                         const DexCompilationUnit& dex_compilation_unit,
123*795d594fSAndroid Build Coastguard Worker                         bool try_catch_inlining_allowed_for_recursive_inline)
124*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   // Try to recognize known simple patterns and replace invoke call with appropriate instructions.
127*795d594fSAndroid Build Coastguard Worker   bool TryPatternSubstitution(HInvoke* invoke_instruction,
128*795d594fSAndroid Build Coastguard Worker                               ArtMethod* method,
129*795d594fSAndroid Build Coastguard Worker                               const CodeItemDataAccessor& accessor,
130*795d594fSAndroid Build Coastguard Worker                               HInstruction** return_replacement)
131*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker   // Returns whether inlining is allowed based on ART semantics.
134*795d594fSAndroid Build Coastguard Worker   bool IsInliningAllowed(art::ArtMethod* method, const CodeItemDataAccessor& accessor) const
135*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   // Returns whether ART supports inlining this method.
139*795d594fSAndroid Build Coastguard Worker   //
140*795d594fSAndroid Build Coastguard Worker   // Some methods are not supported because they have features for which inlining
141*795d594fSAndroid Build Coastguard Worker   // is not implemented. For example, we do not currently support inlining throw
142*795d594fSAndroid Build Coastguard Worker   // instructions into a try block.
143*795d594fSAndroid Build Coastguard Worker   bool IsInliningSupported(const HInvoke* invoke_instruction,
144*795d594fSAndroid Build Coastguard Worker                            art::ArtMethod* method,
145*795d594fSAndroid Build Coastguard Worker                            const CodeItemDataAccessor& accessor) const
146*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker   // Returns whether inlining is encouraged.
149*795d594fSAndroid Build Coastguard Worker   //
150*795d594fSAndroid Build Coastguard Worker   // For example, this checks whether the function has grown too large and
151*795d594fSAndroid Build Coastguard Worker   // inlining should be prevented.
152*795d594fSAndroid Build Coastguard Worker   bool IsInliningEncouraged(const HInvoke* invoke_instruction,
153*795d594fSAndroid Build Coastguard Worker                             art::ArtMethod* method,
154*795d594fSAndroid Build Coastguard Worker                             const CodeItemDataAccessor& accessor) const
155*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   // Inspects the body of a method (callee_graph) and returns whether it can be
158*795d594fSAndroid Build Coastguard Worker   // inlined.
159*795d594fSAndroid Build Coastguard Worker   //
160*795d594fSAndroid Build Coastguard Worker   // This checks for instructions and constructs that we do not support
161*795d594fSAndroid Build Coastguard Worker   // inlining, such as inlining a throw instruction into a try block.
162*795d594fSAndroid Build Coastguard Worker   bool CanInlineBody(const HGraph* callee_graph,
163*795d594fSAndroid Build Coastguard Worker                      HInvoke* invoke,
164*795d594fSAndroid Build Coastguard Worker                      size_t* out_number_of_instructions,
165*795d594fSAndroid Build Coastguard Worker                      bool is_speculative) const
166*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker   // Create a new HInstanceFieldGet.
169*795d594fSAndroid Build Coastguard Worker   HInstanceFieldGet* CreateInstanceFieldGet(uint32_t field_index,
170*795d594fSAndroid Build Coastguard Worker                                             ArtMethod* referrer,
171*795d594fSAndroid Build Coastguard Worker                                             HInstruction* obj);
172*795d594fSAndroid Build Coastguard Worker   // Create a new HInstanceFieldSet.
173*795d594fSAndroid Build Coastguard Worker   HInstanceFieldSet* CreateInstanceFieldSet(uint32_t field_index,
174*795d594fSAndroid Build Coastguard Worker                                             ArtMethod* referrer,
175*795d594fSAndroid Build Coastguard Worker                                             HInstruction* obj,
176*795d594fSAndroid Build Coastguard Worker                                             HInstruction* value,
177*795d594fSAndroid Build Coastguard Worker                                             bool* is_final = nullptr);
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker   // Try inlining the invoke instruction using inline caches.
180*795d594fSAndroid Build Coastguard Worker   bool TryInlineFromInlineCache(HInvoke* invoke_instruction)
181*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
182*795d594fSAndroid Build Coastguard Worker 
183*795d594fSAndroid Build Coastguard Worker   // Try inlining the invoke instruction using CHA.
184*795d594fSAndroid Build Coastguard Worker   bool TryInlineFromCHA(HInvoke* invoke_instruction)
185*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker   // When we fail inlining `invoke_instruction`, we will try to devirtualize the
188*795d594fSAndroid Build Coastguard Worker   // call.
189*795d594fSAndroid Build Coastguard Worker   bool TryDevirtualize(HInvoke* invoke_instruction,
190*795d594fSAndroid Build Coastguard Worker                        ArtMethod* method,
191*795d594fSAndroid Build Coastguard Worker                        HInvoke** replacement)
192*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker   // Try getting the inline cache from JIT code cache.
195*795d594fSAndroid Build Coastguard Worker   // Return true if the inline cache was successfully allocated and the
196*795d594fSAndroid Build Coastguard Worker   // invoke info was found in the profile info.
197*795d594fSAndroid Build Coastguard Worker   InlineCacheType GetInlineCacheJIT(
198*795d594fSAndroid Build Coastguard Worker       HInvoke* invoke_instruction,
199*795d594fSAndroid Build Coastguard Worker       /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes)
200*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   // Try getting the inline cache from AOT offline profile.
203*795d594fSAndroid Build Coastguard Worker   // Return true if the inline cache was successfully allocated and the
204*795d594fSAndroid Build Coastguard Worker   // invoke info was found in the profile info.
205*795d594fSAndroid Build Coastguard Worker   InlineCacheType GetInlineCacheAOT(
206*795d594fSAndroid Build Coastguard Worker       HInvoke* invoke_instruction,
207*795d594fSAndroid Build Coastguard Worker       /*out*/StackHandleScope<InlineCache::kIndividualCacheSize>* classes)
208*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   // Compute the inline cache type.
211*795d594fSAndroid Build Coastguard Worker   static InlineCacheType GetInlineCacheType(
212*795d594fSAndroid Build Coastguard Worker       const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
213*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   // Try to inline the target of a monomorphic call. If successful, the code
216*795d594fSAndroid Build Coastguard Worker   // in the graph will look like:
217*795d594fSAndroid Build Coastguard Worker   // if (receiver.getClass() != ic.GetMonomorphicType()) deopt
218*795d594fSAndroid Build Coastguard Worker   // ... // inlined code
219*795d594fSAndroid Build Coastguard Worker   bool TryInlineMonomorphicCall(HInvoke* invoke_instruction,
220*795d594fSAndroid Build Coastguard Worker                                 const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
221*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
222*795d594fSAndroid Build Coastguard Worker 
223*795d594fSAndroid Build Coastguard Worker   // Try to inline targets of a polymorphic call.
224*795d594fSAndroid Build Coastguard Worker   bool TryInlinePolymorphicCall(HInvoke* invoke_instruction,
225*795d594fSAndroid Build Coastguard Worker                                 const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
226*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
227*795d594fSAndroid Build Coastguard Worker 
228*795d594fSAndroid Build Coastguard Worker   bool TryInlinePolymorphicCallToSameTarget(
229*795d594fSAndroid Build Coastguard Worker       HInvoke* invoke_instruction,
230*795d594fSAndroid Build Coastguard Worker       const StackHandleScope<InlineCache::kIndividualCacheSize>& classes)
231*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker   // Returns whether or not we should use only polymorphic inlining with no deoptimizations.
234*795d594fSAndroid Build Coastguard Worker   bool UseOnlyPolymorphicInliningWithNoDeopt();
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker   // Try CHA-based devirtualization to change virtual method calls into
237*795d594fSAndroid Build Coastguard Worker   // direct calls.
238*795d594fSAndroid Build Coastguard Worker   // Returns the actual method that resolved_method can be devirtualized to.
239*795d594fSAndroid Build Coastguard Worker   ArtMethod* FindMethodFromCHA(ArtMethod* resolved_method)
240*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
241*795d594fSAndroid Build Coastguard Worker 
242*795d594fSAndroid Build Coastguard Worker   // Add a CHA guard for a CHA-based devirtualized call. A CHA guard checks a
243*795d594fSAndroid Build Coastguard Worker   // should_deoptimize flag and if it's true, does deoptimization.
244*795d594fSAndroid Build Coastguard Worker   void AddCHAGuard(HInstruction* invoke_instruction,
245*795d594fSAndroid Build Coastguard Worker                    uint32_t dex_pc,
246*795d594fSAndroid Build Coastguard Worker                    HInstruction* cursor,
247*795d594fSAndroid Build Coastguard Worker                    HBasicBlock* bb_cursor);
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker   HInstanceFieldGet* BuildGetReceiverClass(ClassLinker* class_linker,
250*795d594fSAndroid Build Coastguard Worker                                            HInstruction* receiver,
251*795d594fSAndroid Build Coastguard Worker                                            uint32_t dex_pc) const
252*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
253*795d594fSAndroid Build Coastguard Worker 
254*795d594fSAndroid Build Coastguard Worker   void MaybeRunReferenceTypePropagation(HInstruction* replacement,
255*795d594fSAndroid Build Coastguard Worker                                         HInvoke* invoke_instruction)
256*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker   void FixUpReturnReferenceType(ArtMethod* resolved_method, HInstruction* return_replacement)
259*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker   bool ArgumentTypesMoreSpecific(HInvoke* invoke_instruction, ArtMethod* resolved_method)
262*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
263*795d594fSAndroid Build Coastguard Worker 
264*795d594fSAndroid Build Coastguard Worker   bool ReturnTypeMoreSpecific(HInstruction* return_replacement, HInvoke* invoke_instruction)
265*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   // Add a type guard on the given `receiver`. This will add to the graph:
268*795d594fSAndroid Build Coastguard Worker   // i0 = HFieldGet(receiver, klass)
269*795d594fSAndroid Build Coastguard Worker   // i1 = HLoadClass(class_index, is_referrer)
270*795d594fSAndroid Build Coastguard Worker   // i2 = HNotEqual(i0, i1)
271*795d594fSAndroid Build Coastguard Worker   //
272*795d594fSAndroid Build Coastguard Worker   // And if `with_deoptimization` is true:
273*795d594fSAndroid Build Coastguard Worker   // HDeoptimize(i2)
274*795d594fSAndroid Build Coastguard Worker   //
275*795d594fSAndroid Build Coastguard Worker   // The method returns the `HNotEqual`, that will be used for polymorphic inlining.
276*795d594fSAndroid Build Coastguard Worker   HInstruction* AddTypeGuard(HInstruction* receiver,
277*795d594fSAndroid Build Coastguard Worker                              HInstruction* cursor,
278*795d594fSAndroid Build Coastguard Worker                              HBasicBlock* bb_cursor,
279*795d594fSAndroid Build Coastguard Worker                              dex::TypeIndex class_index,
280*795d594fSAndroid Build Coastguard Worker                              Handle<mirror::Class> klass,
281*795d594fSAndroid Build Coastguard Worker                              HInstruction* invoke_instruction,
282*795d594fSAndroid Build Coastguard Worker                              bool with_deoptimization)
283*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_);
284*795d594fSAndroid Build Coastguard Worker 
285*795d594fSAndroid Build Coastguard Worker   /*
286*795d594fSAndroid Build Coastguard Worker    * Ad-hoc implementation for implementing a diamond pattern in the graph for
287*795d594fSAndroid Build Coastguard Worker    * polymorphic inlining:
288*795d594fSAndroid Build Coastguard Worker    * 1) `compare` becomes the input of the new `HIf`.
289*795d594fSAndroid Build Coastguard Worker    * 2) Everything up until `invoke_instruction` is in the then branch (could
290*795d594fSAndroid Build Coastguard Worker    *    contain multiple blocks).
291*795d594fSAndroid Build Coastguard Worker    * 3) `invoke_instruction` is moved to the otherwise block.
292*795d594fSAndroid Build Coastguard Worker    * 4) If `return_replacement` is not null, the merge block will have
293*795d594fSAndroid Build Coastguard Worker    *    a phi whose inputs are `return_replacement` and `invoke_instruction`.
294*795d594fSAndroid Build Coastguard Worker    *
295*795d594fSAndroid Build Coastguard Worker    * Before:
296*795d594fSAndroid Build Coastguard Worker    *             Block1
297*795d594fSAndroid Build Coastguard Worker    *             compare
298*795d594fSAndroid Build Coastguard Worker    *              ...
299*795d594fSAndroid Build Coastguard Worker    *         invoke_instruction
300*795d594fSAndroid Build Coastguard Worker    *
301*795d594fSAndroid Build Coastguard Worker    * After:
302*795d594fSAndroid Build Coastguard Worker    *            Block1
303*795d594fSAndroid Build Coastguard Worker    *            compare
304*795d594fSAndroid Build Coastguard Worker    *              if
305*795d594fSAndroid Build Coastguard Worker    *          /        \
306*795d594fSAndroid Build Coastguard Worker    *         /          \
307*795d594fSAndroid Build Coastguard Worker    *   Then block    Otherwise block
308*795d594fSAndroid Build Coastguard Worker    *      ...       invoke_instruction
309*795d594fSAndroid Build Coastguard Worker    *       \              /
310*795d594fSAndroid Build Coastguard Worker    *        \            /
311*795d594fSAndroid Build Coastguard Worker    *          Merge block
312*795d594fSAndroid Build Coastguard Worker    *  phi(return_replacement, invoke_instruction)
313*795d594fSAndroid Build Coastguard Worker    */
314*795d594fSAndroid Build Coastguard Worker   void CreateDiamondPatternForPolymorphicInline(HInstruction* compare,
315*795d594fSAndroid Build Coastguard Worker                                                 HInstruction* return_replacement,
316*795d594fSAndroid Build Coastguard Worker                                                 HInstruction* invoke_instruction);
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker   // Update the inlining budget based on `total_number_of_instructions_`.
319*795d594fSAndroid Build Coastguard Worker   void UpdateInliningBudget();
320*795d594fSAndroid Build Coastguard Worker 
321*795d594fSAndroid Build Coastguard Worker   // Count the number of calls of `method` being inlined recursively.
322*795d594fSAndroid Build Coastguard Worker   size_t CountRecursiveCallsOf(ArtMethod* method) const;
323*795d594fSAndroid Build Coastguard Worker 
324*795d594fSAndroid Build Coastguard Worker   // Pretty-print for spaces during logging.
325*795d594fSAndroid Build Coastguard Worker   std::string DepthString(int line) const;
326*795d594fSAndroid Build Coastguard Worker 
327*795d594fSAndroid Build Coastguard Worker   HGraph* const outermost_graph_;
328*795d594fSAndroid Build Coastguard Worker   const DexCompilationUnit& outer_compilation_unit_;
329*795d594fSAndroid Build Coastguard Worker   const DexCompilationUnit& caller_compilation_unit_;
330*795d594fSAndroid Build Coastguard Worker   CodeGenerator* const codegen_;
331*795d594fSAndroid Build Coastguard Worker   const size_t total_number_of_dex_registers_;
332*795d594fSAndroid Build Coastguard Worker   size_t total_number_of_instructions_;
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker   // The 'parent' inliner, that means the inlining optimization that requested
335*795d594fSAndroid Build Coastguard Worker   // `graph_` to be inlined.
336*795d594fSAndroid Build Coastguard Worker   const HInliner* const parent_;
337*795d594fSAndroid Build Coastguard Worker   const HEnvironment* const caller_environment_;
338*795d594fSAndroid Build Coastguard Worker   const size_t depth_;
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker   // The budget left for inlining, in number of instructions.
341*795d594fSAndroid Build Coastguard Worker   size_t inlining_budget_;
342*795d594fSAndroid Build Coastguard Worker 
343*795d594fSAndroid Build Coastguard Worker   // States if we are allowing try catch inlining to occur at this particular instance of inlining.
344*795d594fSAndroid Build Coastguard Worker   bool try_catch_inlining_allowed_;
345*795d594fSAndroid Build Coastguard Worker 
346*795d594fSAndroid Build Coastguard Worker   // True if we need to run type propagation to type guards we inserted.
347*795d594fSAndroid Build Coastguard Worker   bool run_extra_type_propagation_;
348*795d594fSAndroid Build Coastguard Worker 
349*795d594fSAndroid Build Coastguard Worker   // Used to record stats about optimizations on the inlined graph.
350*795d594fSAndroid Build Coastguard Worker   // If the inlining is successful, these stats are merged to the caller graph's stats.
351*795d594fSAndroid Build Coastguard Worker   OptimizingCompilerStats* inline_stats_;
352*795d594fSAndroid Build Coastguard Worker 
353*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HInliner);
354*795d594fSAndroid Build Coastguard Worker };
355*795d594fSAndroid Build Coastguard Worker 
356*795d594fSAndroid Build Coastguard Worker }  // namespace art
357*795d594fSAndroid Build Coastguard Worker 
358*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_INLINER_H_
359