xref: /aosp_15_r20/art/compiler/optimizing/nodes.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_NODES_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_OPTIMIZING_NODES_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <algorithm>
21*795d594fSAndroid Build Coastguard Worker #include <array>
22*795d594fSAndroid Build Coastguard Worker #include <type_traits>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/arena_bit_vector.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/arena_object.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/intrusive_forward_list.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/iteration_range.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/quasi_atomic.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
36*795d594fSAndroid Build Coastguard Worker #include "base/transform_array_ref.h"
37*795d594fSAndroid Build Coastguard Worker #include "block_namer.h"
38*795d594fSAndroid Build Coastguard Worker #include "class_root.h"
39*795d594fSAndroid Build Coastguard Worker #include "compilation_kind.h"
40*795d594fSAndroid Build Coastguard Worker #include "data_type.h"
41*795d594fSAndroid Build Coastguard Worker #include "deoptimization_kind.h"
42*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
43*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
44*795d594fSAndroid Build Coastguard Worker #include "dex/invoke_type.h"
45*795d594fSAndroid Build Coastguard Worker #include "dex/method_reference.h"
46*795d594fSAndroid Build Coastguard Worker #include "entrypoints/quick/quick_entrypoints_enum.h"
47*795d594fSAndroid Build Coastguard Worker #include "handle.h"
48*795d594fSAndroid Build Coastguard Worker #include "handle_cache.h"
49*795d594fSAndroid Build Coastguard Worker #include "intrinsics_enum.h"
50*795d594fSAndroid Build Coastguard Worker #include "locations.h"
51*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
52*795d594fSAndroid Build Coastguard Worker #include "mirror/method_type.h"
53*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
54*795d594fSAndroid Build Coastguard Worker #include "reference_type_info.h"
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
57*795d594fSAndroid Build Coastguard Worker 
58*795d594fSAndroid Build Coastguard Worker class ArenaStack;
59*795d594fSAndroid Build Coastguard Worker class CodeGenerator;
60*795d594fSAndroid Build Coastguard Worker class GraphChecker;
61*795d594fSAndroid Build Coastguard Worker class HBasicBlock;
62*795d594fSAndroid Build Coastguard Worker class HCondition;
63*795d594fSAndroid Build Coastguard Worker class HConstructorFence;
64*795d594fSAndroid Build Coastguard Worker class HCurrentMethod;
65*795d594fSAndroid Build Coastguard Worker class HDoubleConstant;
66*795d594fSAndroid Build Coastguard Worker class HEnvironment;
67*795d594fSAndroid Build Coastguard Worker class HFloatConstant;
68*795d594fSAndroid Build Coastguard Worker class HGraphBuilder;
69*795d594fSAndroid Build Coastguard Worker class HGraphVisitor;
70*795d594fSAndroid Build Coastguard Worker class HInstruction;
71*795d594fSAndroid Build Coastguard Worker class HIntConstant;
72*795d594fSAndroid Build Coastguard Worker class HInvoke;
73*795d594fSAndroid Build Coastguard Worker class HLongConstant;
74*795d594fSAndroid Build Coastguard Worker class HNullConstant;
75*795d594fSAndroid Build Coastguard Worker class HParameterValue;
76*795d594fSAndroid Build Coastguard Worker class HPhi;
77*795d594fSAndroid Build Coastguard Worker class HSuspendCheck;
78*795d594fSAndroid Build Coastguard Worker class HTryBoundary;
79*795d594fSAndroid Build Coastguard Worker class HVecCondition;
80*795d594fSAndroid Build Coastguard Worker class FieldInfo;
81*795d594fSAndroid Build Coastguard Worker class LiveInterval;
82*795d594fSAndroid Build Coastguard Worker class LocationSummary;
83*795d594fSAndroid Build Coastguard Worker class ProfilingInfo;
84*795d594fSAndroid Build Coastguard Worker class SlowPathCode;
85*795d594fSAndroid Build Coastguard Worker class SsaBuilder;
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker namespace mirror {
88*795d594fSAndroid Build Coastguard Worker class DexCache;
89*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfBlocks = 8;
92*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfSuccessors = 2;
93*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfPredecessors = 2;
94*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfExceptionalPredecessors = 0;
95*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfDominatedBlocks = 1;
96*795d594fSAndroid Build Coastguard Worker static const int kDefaultNumberOfBackEdges = 1;
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker // The maximum (meaningful) distance (31) that can be used in an integer shift/rotate operation.
99*795d594fSAndroid Build Coastguard Worker static constexpr int32_t kMaxIntShiftDistance = 0x1f;
100*795d594fSAndroid Build Coastguard Worker // The maximum (meaningful) distance (63) that can be used in a long shift/rotate operation.
101*795d594fSAndroid Build Coastguard Worker static constexpr int32_t kMaxLongShiftDistance = 0x3f;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
104*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kUnknownClassDefIndex = static_cast<uint16_t>(-1);
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
107*795d594fSAndroid Build Coastguard Worker 
108*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kNoDexPc = -1;
109*795d594fSAndroid Build Coastguard Worker 
IsSameDexFile(const DexFile & lhs,const DexFile & rhs)110*795d594fSAndroid Build Coastguard Worker inline bool IsSameDexFile(const DexFile& lhs, const DexFile& rhs) {
111*795d594fSAndroid Build Coastguard Worker   // For the purposes of the compiler, the dex files must actually be the same object
112*795d594fSAndroid Build Coastguard Worker   // if we want to safely treat them as the same. This is especially important for JIT
113*795d594fSAndroid Build Coastguard Worker   // as custom class loaders can open the same underlying file (or memory) multiple
114*795d594fSAndroid Build Coastguard Worker   // times and provide different class resolution but no two class loaders should ever
115*795d594fSAndroid Build Coastguard Worker   // use the same DexFile object - doing so is an unsupported hack that can lead to
116*795d594fSAndroid Build Coastguard Worker   // all sorts of weird failures.
117*795d594fSAndroid Build Coastguard Worker   return &lhs == &rhs;
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker enum IfCondition {
121*795d594fSAndroid Build Coastguard Worker   // All types.
122*795d594fSAndroid Build Coastguard Worker   kCondEQ,  // ==
123*795d594fSAndroid Build Coastguard Worker   kCondNE,  // !=
124*795d594fSAndroid Build Coastguard Worker   // Signed integers and floating-point numbers.
125*795d594fSAndroid Build Coastguard Worker   kCondLT,  // <
126*795d594fSAndroid Build Coastguard Worker   kCondLE,  // <=
127*795d594fSAndroid Build Coastguard Worker   kCondGT,  // >
128*795d594fSAndroid Build Coastguard Worker   kCondGE,  // >=
129*795d594fSAndroid Build Coastguard Worker   // Unsigned integers.
130*795d594fSAndroid Build Coastguard Worker   kCondB,   // <
131*795d594fSAndroid Build Coastguard Worker   kCondBE,  // <=
132*795d594fSAndroid Build Coastguard Worker   kCondA,   // >
133*795d594fSAndroid Build Coastguard Worker   kCondAE,  // >=
134*795d594fSAndroid Build Coastguard Worker   // First and last aliases.
135*795d594fSAndroid Build Coastguard Worker   kCondFirst = kCondEQ,
136*795d594fSAndroid Build Coastguard Worker   kCondLast = kCondAE,
137*795d594fSAndroid Build Coastguard Worker };
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker enum GraphAnalysisResult {
140*795d594fSAndroid Build Coastguard Worker   kAnalysisSkipped,
141*795d594fSAndroid Build Coastguard Worker   kAnalysisInvalidBytecode,
142*795d594fSAndroid Build Coastguard Worker   kAnalysisFailThrowCatchLoop,
143*795d594fSAndroid Build Coastguard Worker   kAnalysisFailAmbiguousArrayOp,
144*795d594fSAndroid Build Coastguard Worker   kAnalysisFailIrreducibleLoopAndStringInit,
145*795d594fSAndroid Build Coastguard Worker   kAnalysisFailPhiEquivalentInOsr,
146*795d594fSAndroid Build Coastguard Worker   kAnalysisSuccess,
147*795d594fSAndroid Build Coastguard Worker };
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, GraphAnalysisResult ga);
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker template <typename T>
MakeUnsigned(T x)152*795d594fSAndroid Build Coastguard Worker static inline typename std::make_unsigned<T>::type MakeUnsigned(T x) {
153*795d594fSAndroid Build Coastguard Worker   return static_cast<typename std::make_unsigned<T>::type>(x);
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker class HInstructionList : public ValueObject {
157*795d594fSAndroid Build Coastguard Worker  public:
HInstructionList()158*795d594fSAndroid Build Coastguard Worker   HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker   void AddInstruction(HInstruction* instruction);
161*795d594fSAndroid Build Coastguard Worker   void RemoveInstruction(HInstruction* instruction);
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker   // Insert `instruction` before/after an existing instruction `cursor`.
164*795d594fSAndroid Build Coastguard Worker   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
165*795d594fSAndroid Build Coastguard Worker   void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   // Return true if this list contains `instruction`.
168*795d594fSAndroid Build Coastguard Worker   bool Contains(HInstruction* instruction) const;
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker   // Return true if `instruction1` is found before `instruction2` in
171*795d594fSAndroid Build Coastguard Worker   // this instruction list and false otherwise.  Abort if none
172*795d594fSAndroid Build Coastguard Worker   // of these instructions is found.
173*795d594fSAndroid Build Coastguard Worker   bool FoundBefore(const HInstruction* instruction1,
174*795d594fSAndroid Build Coastguard Worker                    const HInstruction* instruction2) const;
175*795d594fSAndroid Build Coastguard Worker 
IsEmpty()176*795d594fSAndroid Build Coastguard Worker   bool IsEmpty() const { return first_instruction_ == nullptr; }
Clear()177*795d594fSAndroid Build Coastguard Worker   void Clear() { first_instruction_ = last_instruction_ = nullptr; }
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker   // Update the block of all instructions to be `block`.
180*795d594fSAndroid Build Coastguard Worker   void SetBlockOfInstructions(HBasicBlock* block) const;
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker   void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
183*795d594fSAndroid Build Coastguard Worker   void AddBefore(HInstruction* cursor, const HInstructionList& instruction_list);
184*795d594fSAndroid Build Coastguard Worker   void Add(const HInstructionList& instruction_list);
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker   // Return the number of instructions in the list. This is an expensive operation.
187*795d594fSAndroid Build Coastguard Worker   size_t CountSize() const;
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker  private:
190*795d594fSAndroid Build Coastguard Worker   HInstruction* first_instruction_;
191*795d594fSAndroid Build Coastguard Worker   HInstruction* last_instruction_;
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   friend class HBasicBlock;
194*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
195*795d594fSAndroid Build Coastguard Worker   friend class HInstruction;
196*795d594fSAndroid Build Coastguard Worker   friend class HInstructionIterator;
197*795d594fSAndroid Build Coastguard Worker   friend class HInstructionIteratorHandleChanges;
198*795d594fSAndroid Build Coastguard Worker   friend class HBackwardInstructionIterator;
199*795d594fSAndroid Build Coastguard Worker 
200*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HInstructionList);
201*795d594fSAndroid Build Coastguard Worker };
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker // Control-flow graph of a method. Contains a list of basic blocks.
204*795d594fSAndroid Build Coastguard Worker class HGraph : public ArenaObject<kArenaAllocGraph> {
205*795d594fSAndroid Build Coastguard Worker  public:
206*795d594fSAndroid Build Coastguard Worker   HGraph(ArenaAllocator* allocator,
207*795d594fSAndroid Build Coastguard Worker          ArenaStack* arena_stack,
208*795d594fSAndroid Build Coastguard Worker          VariableSizedHandleScope* handles,
209*795d594fSAndroid Build Coastguard Worker          const DexFile& dex_file,
210*795d594fSAndroid Build Coastguard Worker          uint32_t method_idx,
211*795d594fSAndroid Build Coastguard Worker          InstructionSet instruction_set,
212*795d594fSAndroid Build Coastguard Worker          InvokeType invoke_type = kInvalidInvokeType,
213*795d594fSAndroid Build Coastguard Worker          bool dead_reference_safe = false,
214*795d594fSAndroid Build Coastguard Worker          bool debuggable = false,
215*795d594fSAndroid Build Coastguard Worker          CompilationKind compilation_kind = CompilationKind::kOptimized,
216*795d594fSAndroid Build Coastguard Worker          int start_instruction_id = 0)
allocator_(allocator)217*795d594fSAndroid Build Coastguard Worker       : allocator_(allocator),
218*795d594fSAndroid Build Coastguard Worker         arena_stack_(arena_stack),
219*795d594fSAndroid Build Coastguard Worker         handle_cache_(handles),
220*795d594fSAndroid Build Coastguard Worker         blocks_(allocator->Adapter(kArenaAllocBlockList)),
221*795d594fSAndroid Build Coastguard Worker         reverse_post_order_(allocator->Adapter(kArenaAllocReversePostOrder)),
222*795d594fSAndroid Build Coastguard Worker         linear_order_(allocator->Adapter(kArenaAllocLinearOrder)),
223*795d594fSAndroid Build Coastguard Worker         entry_block_(nullptr),
224*795d594fSAndroid Build Coastguard Worker         exit_block_(nullptr),
225*795d594fSAndroid Build Coastguard Worker         number_of_vregs_(0),
226*795d594fSAndroid Build Coastguard Worker         number_of_in_vregs_(0),
227*795d594fSAndroid Build Coastguard Worker         temporaries_vreg_slots_(0),
228*795d594fSAndroid Build Coastguard Worker         has_bounds_checks_(false),
229*795d594fSAndroid Build Coastguard Worker         has_try_catch_(false),
230*795d594fSAndroid Build Coastguard Worker         has_monitor_operations_(false),
231*795d594fSAndroid Build Coastguard Worker         has_traditional_simd_(false),
232*795d594fSAndroid Build Coastguard Worker         has_predicated_simd_(false),
233*795d594fSAndroid Build Coastguard Worker         has_loops_(false),
234*795d594fSAndroid Build Coastguard Worker         has_irreducible_loops_(false),
235*795d594fSAndroid Build Coastguard Worker         has_direct_critical_native_call_(false),
236*795d594fSAndroid Build Coastguard Worker         has_always_throwing_invokes_(false),
237*795d594fSAndroid Build Coastguard Worker         dead_reference_safe_(dead_reference_safe),
238*795d594fSAndroid Build Coastguard Worker         debuggable_(debuggable),
239*795d594fSAndroid Build Coastguard Worker         current_instruction_id_(start_instruction_id),
240*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file),
241*795d594fSAndroid Build Coastguard Worker         method_idx_(method_idx),
242*795d594fSAndroid Build Coastguard Worker         invoke_type_(invoke_type),
243*795d594fSAndroid Build Coastguard Worker         in_ssa_form_(false),
244*795d594fSAndroid Build Coastguard Worker         number_of_cha_guards_(0),
245*795d594fSAndroid Build Coastguard Worker         instruction_set_(instruction_set),
246*795d594fSAndroid Build Coastguard Worker         cached_null_constant_(nullptr),
247*795d594fSAndroid Build Coastguard Worker         cached_int_constants_(std::less<int32_t>(), allocator->Adapter(kArenaAllocConstantsMap)),
248*795d594fSAndroid Build Coastguard Worker         cached_float_constants_(std::less<int32_t>(), allocator->Adapter(kArenaAllocConstantsMap)),
249*795d594fSAndroid Build Coastguard Worker         cached_long_constants_(std::less<int64_t>(), allocator->Adapter(kArenaAllocConstantsMap)),
250*795d594fSAndroid Build Coastguard Worker         cached_double_constants_(std::less<int64_t>(), allocator->Adapter(kArenaAllocConstantsMap)),
251*795d594fSAndroid Build Coastguard Worker         cached_current_method_(nullptr),
252*795d594fSAndroid Build Coastguard Worker         art_method_(nullptr),
253*795d594fSAndroid Build Coastguard Worker         compilation_kind_(compilation_kind),
254*795d594fSAndroid Build Coastguard Worker         useful_optimizing_(false),
255*795d594fSAndroid Build Coastguard Worker         cha_single_implementation_list_(allocator->Adapter(kArenaAllocCHA)) {
256*795d594fSAndroid Build Coastguard Worker     blocks_.reserve(kDefaultNumberOfBlocks);
257*795d594fSAndroid Build Coastguard Worker   }
258*795d594fSAndroid Build Coastguard Worker 
259*795d594fSAndroid Build Coastguard Worker   std::ostream& Dump(std::ostream& os,
260*795d594fSAndroid Build Coastguard Worker                      CodeGenerator* codegen,
261*795d594fSAndroid Build Coastguard Worker                      std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);
262*795d594fSAndroid Build Coastguard Worker 
GetAllocator()263*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* GetAllocator() const { return allocator_; }
GetArenaStack()264*795d594fSAndroid Build Coastguard Worker   ArenaStack* GetArenaStack() const { return arena_stack_; }
265*795d594fSAndroid Build Coastguard Worker 
GetHandleCache()266*795d594fSAndroid Build Coastguard Worker   HandleCache* GetHandleCache() { return &handle_cache_; }
267*795d594fSAndroid Build Coastguard Worker 
GetBlocks()268*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetBlocks() const { return blocks_; }
269*795d594fSAndroid Build Coastguard Worker 
270*795d594fSAndroid Build Coastguard Worker   // An iterator to only blocks that are still actually in the graph (when
271*795d594fSAndroid Build Coastguard Worker   // blocks are removed they are replaced with 'nullptr' in GetBlocks to
272*795d594fSAndroid Build Coastguard Worker   // simplify block-id assignment and avoid memmoves in the block-list).
GetActiveBlocks()273*795d594fSAndroid Build Coastguard Worker   IterationRange<FilterNull<ArenaVector<HBasicBlock*>::const_iterator>> GetActiveBlocks() const {
274*795d594fSAndroid Build Coastguard Worker     return FilterOutNull(MakeIterationRange(GetBlocks()));
275*795d594fSAndroid Build Coastguard Worker   }
276*795d594fSAndroid Build Coastguard Worker 
IsInSsaForm()277*795d594fSAndroid Build Coastguard Worker   bool IsInSsaForm() const { return in_ssa_form_; }
SetInSsaForm()278*795d594fSAndroid Build Coastguard Worker   void SetInSsaForm() { in_ssa_form_ = true; }
279*795d594fSAndroid Build Coastguard Worker 
GetEntryBlock()280*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetEntryBlock() const { return entry_block_; }
GetExitBlock()281*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetExitBlock() const { return exit_block_; }
HasExitBlock()282*795d594fSAndroid Build Coastguard Worker   bool HasExitBlock() const { return exit_block_ != nullptr; }
283*795d594fSAndroid Build Coastguard Worker 
SetEntryBlock(HBasicBlock * block)284*795d594fSAndroid Build Coastguard Worker   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
SetExitBlock(HBasicBlock * block)285*795d594fSAndroid Build Coastguard Worker   void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
286*795d594fSAndroid Build Coastguard Worker 
287*795d594fSAndroid Build Coastguard Worker   void AddBlock(HBasicBlock* block);
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker   void ComputeDominanceInformation();
290*795d594fSAndroid Build Coastguard Worker   void ClearDominanceInformation();
291*795d594fSAndroid Build Coastguard Worker   void ClearLoopInformation();
292*795d594fSAndroid Build Coastguard Worker   void FindBackEdges(ArenaBitVector* visited);
293*795d594fSAndroid Build Coastguard Worker   GraphAnalysisResult BuildDominatorTree();
294*795d594fSAndroid Build Coastguard Worker   GraphAnalysisResult RecomputeDominatorTree();
295*795d594fSAndroid Build Coastguard Worker   void SimplifyCFG();
296*795d594fSAndroid Build Coastguard Worker   void SimplifyCatchBlocks();
297*795d594fSAndroid Build Coastguard Worker 
298*795d594fSAndroid Build Coastguard Worker   // Analyze all natural loops in this graph. Returns a code specifying that it
299*795d594fSAndroid Build Coastguard Worker   // was successful or the reason for failure. The method will fail if a loop
300*795d594fSAndroid Build Coastguard Worker   // is a throw-catch loop, i.e. the header is a catch block.
301*795d594fSAndroid Build Coastguard Worker   GraphAnalysisResult AnalyzeLoops() const;
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker   // Iterate over blocks to compute try block membership. Needs reverse post
304*795d594fSAndroid Build Coastguard Worker   // order and loop information.
305*795d594fSAndroid Build Coastguard Worker   void ComputeTryBlockInformation();
306*795d594fSAndroid Build Coastguard Worker 
307*795d594fSAndroid Build Coastguard Worker   // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
308*795d594fSAndroid Build Coastguard Worker   // Returns the instruction to replace the invoke expression or null if the
309*795d594fSAndroid Build Coastguard Worker   // invoke is for a void method. Note that the caller is responsible for replacing
310*795d594fSAndroid Build Coastguard Worker   // and removing the invoke instruction.
311*795d594fSAndroid Build Coastguard Worker   HInstruction* InlineInto(HGraph* outer_graph, HInvoke* invoke);
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker   // Update the loop and try membership of `block`, which was spawned from `reference`.
314*795d594fSAndroid Build Coastguard Worker   // In case `reference` is a back edge, `replace_if_back_edge` notifies whether `block`
315*795d594fSAndroid Build Coastguard Worker   // should be the new back edge.
316*795d594fSAndroid Build Coastguard Worker   // `has_more_specific_try_catch_info` will be set to true when inlining a try catch.
317*795d594fSAndroid Build Coastguard Worker   void UpdateLoopAndTryInformationOfNewBlock(HBasicBlock* block,
318*795d594fSAndroid Build Coastguard Worker                                              HBasicBlock* reference,
319*795d594fSAndroid Build Coastguard Worker                                              bool replace_if_back_edge,
320*795d594fSAndroid Build Coastguard Worker                                              bool has_more_specific_try_catch_info = false);
321*795d594fSAndroid Build Coastguard Worker 
322*795d594fSAndroid Build Coastguard Worker   // Need to add a couple of blocks to test if the loop body is entered and
323*795d594fSAndroid Build Coastguard Worker   // put deoptimization instructions, etc.
324*795d594fSAndroid Build Coastguard Worker   void TransformLoopHeaderForBCE(HBasicBlock* header);
325*795d594fSAndroid Build Coastguard Worker 
326*795d594fSAndroid Build Coastguard Worker   // Adds a new loop directly after the loop with the given header and exit.
327*795d594fSAndroid Build Coastguard Worker   // Returns the new preheader.
328*795d594fSAndroid Build Coastguard Worker   HBasicBlock* TransformLoopForVectorization(HBasicBlock* header,
329*795d594fSAndroid Build Coastguard Worker                                              HBasicBlock* body,
330*795d594fSAndroid Build Coastguard Worker                                              HBasicBlock* exit);
331*795d594fSAndroid Build Coastguard Worker 
332*795d594fSAndroid Build Coastguard Worker   // Removes `block` from the graph. Assumes `block` has been disconnected from
333*795d594fSAndroid Build Coastguard Worker   // other blocks and has no instructions or phis.
334*795d594fSAndroid Build Coastguard Worker   void DeleteDeadEmptyBlock(HBasicBlock* block);
335*795d594fSAndroid Build Coastguard Worker 
336*795d594fSAndroid Build Coastguard Worker   // Splits the edge between `block` and `successor` while preserving the
337*795d594fSAndroid Build Coastguard Worker   // indices in the predecessor/successor lists. If there are multiple edges
338*795d594fSAndroid Build Coastguard Worker   // between the blocks, the lowest indices are used.
339*795d594fSAndroid Build Coastguard Worker   // Returns the new block which is empty and has the same dex pc as `successor`.
340*795d594fSAndroid Build Coastguard Worker   HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor);
341*795d594fSAndroid Build Coastguard Worker 
342*795d594fSAndroid Build Coastguard Worker   void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker   // Splits the edge between `block` and `successor` and then updates the graph's RPO to keep
345*795d594fSAndroid Build Coastguard Worker   // consistency without recomputing the whole graph.
346*795d594fSAndroid Build Coastguard Worker   HBasicBlock* SplitEdgeAndUpdateRPO(HBasicBlock* block, HBasicBlock* successor);
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker   void OrderLoopHeaderPredecessors(HBasicBlock* header);
349*795d594fSAndroid Build Coastguard Worker 
350*795d594fSAndroid Build Coastguard Worker   // Transform a loop into a format with a single preheader.
351*795d594fSAndroid Build Coastguard Worker   //
352*795d594fSAndroid Build Coastguard Worker   // Each phi in the header should be split: original one in the header should only hold
353*795d594fSAndroid Build Coastguard Worker   // inputs reachable from the back edges and a single input from the preheader. The newly created
354*795d594fSAndroid Build Coastguard Worker   // phi in the preheader should collate the inputs from the original multiple incoming blocks.
355*795d594fSAndroid Build Coastguard Worker   //
356*795d594fSAndroid Build Coastguard Worker   // Loops in the graph typically have a single preheader, so this method is used to "repair" loops
357*795d594fSAndroid Build Coastguard Worker   // that no longer have this property.
358*795d594fSAndroid Build Coastguard Worker   void TransformLoopToSinglePreheaderFormat(HBasicBlock* header);
359*795d594fSAndroid Build Coastguard Worker 
360*795d594fSAndroid Build Coastguard Worker   void SimplifyLoop(HBasicBlock* header);
361*795d594fSAndroid Build Coastguard Worker 
GetNextInstructionId()362*795d594fSAndroid Build Coastguard Worker   int32_t GetNextInstructionId() {
363*795d594fSAndroid Build Coastguard Worker     CHECK_NE(current_instruction_id_, INT32_MAX);
364*795d594fSAndroid Build Coastguard Worker     return current_instruction_id_++;
365*795d594fSAndroid Build Coastguard Worker   }
366*795d594fSAndroid Build Coastguard Worker 
GetCurrentInstructionId()367*795d594fSAndroid Build Coastguard Worker   int32_t GetCurrentInstructionId() const {
368*795d594fSAndroid Build Coastguard Worker     return current_instruction_id_;
369*795d594fSAndroid Build Coastguard Worker   }
370*795d594fSAndroid Build Coastguard Worker 
SetCurrentInstructionId(int32_t id)371*795d594fSAndroid Build Coastguard Worker   void SetCurrentInstructionId(int32_t id) {
372*795d594fSAndroid Build Coastguard Worker     CHECK_GE(id, current_instruction_id_);
373*795d594fSAndroid Build Coastguard Worker     current_instruction_id_ = id;
374*795d594fSAndroid Build Coastguard Worker   }
375*795d594fSAndroid Build Coastguard Worker 
UpdateTemporariesVRegSlots(size_t slots)376*795d594fSAndroid Build Coastguard Worker   void UpdateTemporariesVRegSlots(size_t slots) {
377*795d594fSAndroid Build Coastguard Worker     temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
378*795d594fSAndroid Build Coastguard Worker   }
379*795d594fSAndroid Build Coastguard Worker 
GetTemporariesVRegSlots()380*795d594fSAndroid Build Coastguard Worker   size_t GetTemporariesVRegSlots() const {
381*795d594fSAndroid Build Coastguard Worker     DCHECK(!in_ssa_form_);
382*795d594fSAndroid Build Coastguard Worker     return temporaries_vreg_slots_;
383*795d594fSAndroid Build Coastguard Worker   }
384*795d594fSAndroid Build Coastguard Worker 
SetNumberOfVRegs(uint16_t number_of_vregs)385*795d594fSAndroid Build Coastguard Worker   void SetNumberOfVRegs(uint16_t number_of_vregs) {
386*795d594fSAndroid Build Coastguard Worker     number_of_vregs_ = number_of_vregs;
387*795d594fSAndroid Build Coastguard Worker   }
388*795d594fSAndroid Build Coastguard Worker 
GetNumberOfVRegs()389*795d594fSAndroid Build Coastguard Worker   uint16_t GetNumberOfVRegs() const {
390*795d594fSAndroid Build Coastguard Worker     return number_of_vregs_;
391*795d594fSAndroid Build Coastguard Worker   }
392*795d594fSAndroid Build Coastguard Worker 
SetNumberOfInVRegs(uint16_t value)393*795d594fSAndroid Build Coastguard Worker   void SetNumberOfInVRegs(uint16_t value) {
394*795d594fSAndroid Build Coastguard Worker     number_of_in_vregs_ = value;
395*795d594fSAndroid Build Coastguard Worker   }
396*795d594fSAndroid Build Coastguard Worker 
GetNumberOfInVRegs()397*795d594fSAndroid Build Coastguard Worker   uint16_t GetNumberOfInVRegs() const {
398*795d594fSAndroid Build Coastguard Worker     return number_of_in_vregs_;
399*795d594fSAndroid Build Coastguard Worker   }
400*795d594fSAndroid Build Coastguard Worker 
GetNumberOfLocalVRegs()401*795d594fSAndroid Build Coastguard Worker   uint16_t GetNumberOfLocalVRegs() const {
402*795d594fSAndroid Build Coastguard Worker     DCHECK(!in_ssa_form_);
403*795d594fSAndroid Build Coastguard Worker     return number_of_vregs_ - number_of_in_vregs_;
404*795d594fSAndroid Build Coastguard Worker   }
405*795d594fSAndroid Build Coastguard Worker 
GetReversePostOrder()406*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetReversePostOrder() const {
407*795d594fSAndroid Build Coastguard Worker     return reverse_post_order_;
408*795d594fSAndroid Build Coastguard Worker   }
409*795d594fSAndroid Build Coastguard Worker 
GetReversePostOrderSkipEntryBlock()410*795d594fSAndroid Build Coastguard Worker   ArrayRef<HBasicBlock* const> GetReversePostOrderSkipEntryBlock() const {
411*795d594fSAndroid Build Coastguard Worker     DCHECK(GetReversePostOrder()[0] == entry_block_);
412*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HBasicBlock* const>(GetReversePostOrder()).SubArray(1);
413*795d594fSAndroid Build Coastguard Worker   }
414*795d594fSAndroid Build Coastguard Worker 
GetPostOrder()415*795d594fSAndroid Build Coastguard Worker   IterationRange<ArenaVector<HBasicBlock*>::const_reverse_iterator> GetPostOrder() const {
416*795d594fSAndroid Build Coastguard Worker     return ReverseRange(GetReversePostOrder());
417*795d594fSAndroid Build Coastguard Worker   }
418*795d594fSAndroid Build Coastguard Worker 
GetLinearOrder()419*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetLinearOrder() const {
420*795d594fSAndroid Build Coastguard Worker     return linear_order_;
421*795d594fSAndroid Build Coastguard Worker   }
422*795d594fSAndroid Build Coastguard Worker 
GetLinearPostOrder()423*795d594fSAndroid Build Coastguard Worker   IterationRange<ArenaVector<HBasicBlock*>::const_reverse_iterator> GetLinearPostOrder() const {
424*795d594fSAndroid Build Coastguard Worker     return ReverseRange(GetLinearOrder());
425*795d594fSAndroid Build Coastguard Worker   }
426*795d594fSAndroid Build Coastguard Worker 
HasBoundsChecks()427*795d594fSAndroid Build Coastguard Worker   bool HasBoundsChecks() const {
428*795d594fSAndroid Build Coastguard Worker     return has_bounds_checks_;
429*795d594fSAndroid Build Coastguard Worker   }
430*795d594fSAndroid Build Coastguard Worker 
SetHasBoundsChecks(bool value)431*795d594fSAndroid Build Coastguard Worker   void SetHasBoundsChecks(bool value) {
432*795d594fSAndroid Build Coastguard Worker     has_bounds_checks_ = value;
433*795d594fSAndroid Build Coastguard Worker   }
434*795d594fSAndroid Build Coastguard Worker 
435*795d594fSAndroid Build Coastguard Worker   // Is the code known to be robust against eliminating dead references
436*795d594fSAndroid Build Coastguard Worker   // and the effects of early finalization?
IsDeadReferenceSafe()437*795d594fSAndroid Build Coastguard Worker   bool IsDeadReferenceSafe() const { return dead_reference_safe_; }
438*795d594fSAndroid Build Coastguard Worker 
MarkDeadReferenceUnsafe()439*795d594fSAndroid Build Coastguard Worker   void MarkDeadReferenceUnsafe() { dead_reference_safe_ = false; }
440*795d594fSAndroid Build Coastguard Worker 
IsDebuggable()441*795d594fSAndroid Build Coastguard Worker   bool IsDebuggable() const { return debuggable_; }
442*795d594fSAndroid Build Coastguard Worker 
443*795d594fSAndroid Build Coastguard Worker   // Returns a constant of the given type and value. If it does not exist
444*795d594fSAndroid Build Coastguard Worker   // already, it is created and inserted into the graph. This method is only for
445*795d594fSAndroid Build Coastguard Worker   // integral types.
446*795d594fSAndroid Build Coastguard Worker   HConstant* GetConstant(DataType::Type type, int64_t value);
447*795d594fSAndroid Build Coastguard Worker 
448*795d594fSAndroid Build Coastguard Worker   // TODO: This is problematic for the consistency of reference type propagation
449*795d594fSAndroid Build Coastguard Worker   // because it can be created anytime after the pass and thus it will be left
450*795d594fSAndroid Build Coastguard Worker   // with an invalid type.
451*795d594fSAndroid Build Coastguard Worker   HNullConstant* GetNullConstant();
452*795d594fSAndroid Build Coastguard Worker 
453*795d594fSAndroid Build Coastguard Worker   HIntConstant* GetIntConstant(int32_t value);
454*795d594fSAndroid Build Coastguard Worker   HLongConstant* GetLongConstant(int64_t value);
455*795d594fSAndroid Build Coastguard Worker   HFloatConstant* GetFloatConstant(float value);
456*795d594fSAndroid Build Coastguard Worker   HDoubleConstant* GetDoubleConstant(double value);
457*795d594fSAndroid Build Coastguard Worker 
458*795d594fSAndroid Build Coastguard Worker   HCurrentMethod* GetCurrentMethod();
459*795d594fSAndroid Build Coastguard Worker 
GetDexFile()460*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const {
461*795d594fSAndroid Build Coastguard Worker     return dex_file_;
462*795d594fSAndroid Build Coastguard Worker   }
463*795d594fSAndroid Build Coastguard Worker 
GetMethodIdx()464*795d594fSAndroid Build Coastguard Worker   uint32_t GetMethodIdx() const {
465*795d594fSAndroid Build Coastguard Worker     return method_idx_;
466*795d594fSAndroid Build Coastguard Worker   }
467*795d594fSAndroid Build Coastguard Worker 
468*795d594fSAndroid Build Coastguard Worker   // Get the method name (without the signature), e.g. "<init>"
469*795d594fSAndroid Build Coastguard Worker   const char* GetMethodName() const;
470*795d594fSAndroid Build Coastguard Worker 
471*795d594fSAndroid Build Coastguard Worker   // Get the pretty method name (class + name + optionally signature).
472*795d594fSAndroid Build Coastguard Worker   std::string PrettyMethod(bool with_signature = true) const;
473*795d594fSAndroid Build Coastguard Worker 
GetInvokeType()474*795d594fSAndroid Build Coastguard Worker   InvokeType GetInvokeType() const {
475*795d594fSAndroid Build Coastguard Worker     return invoke_type_;
476*795d594fSAndroid Build Coastguard Worker   }
477*795d594fSAndroid Build Coastguard Worker 
GetInstructionSet()478*795d594fSAndroid Build Coastguard Worker   InstructionSet GetInstructionSet() const {
479*795d594fSAndroid Build Coastguard Worker     return instruction_set_;
480*795d594fSAndroid Build Coastguard Worker   }
481*795d594fSAndroid Build Coastguard Worker 
IsCompilingOsr()482*795d594fSAndroid Build Coastguard Worker   bool IsCompilingOsr() const { return compilation_kind_ == CompilationKind::kOsr; }
483*795d594fSAndroid Build Coastguard Worker 
IsCompilingBaseline()484*795d594fSAndroid Build Coastguard Worker   bool IsCompilingBaseline() const { return compilation_kind_ == CompilationKind::kBaseline; }
485*795d594fSAndroid Build Coastguard Worker 
GetCompilationKind()486*795d594fSAndroid Build Coastguard Worker   CompilationKind GetCompilationKind() const { return compilation_kind_; }
487*795d594fSAndroid Build Coastguard Worker 
GetCHASingleImplementationList()488*795d594fSAndroid Build Coastguard Worker   ArenaSet<ArtMethod*>& GetCHASingleImplementationList() {
489*795d594fSAndroid Build Coastguard Worker     return cha_single_implementation_list_;
490*795d594fSAndroid Build Coastguard Worker   }
491*795d594fSAndroid Build Coastguard Worker 
492*795d594fSAndroid Build Coastguard Worker   // In case of OSR we intend to use SuspendChecks as an entry point to the
493*795d594fSAndroid Build Coastguard Worker   // function; for debuggable graphs we might deoptimize to interpreter from
494*795d594fSAndroid Build Coastguard Worker   // SuspendChecks. In these cases we should always generate code for them.
SuspendChecksAreAllowedToNoOp()495*795d594fSAndroid Build Coastguard Worker   bool SuspendChecksAreAllowedToNoOp() const {
496*795d594fSAndroid Build Coastguard Worker     return !IsDebuggable() && !IsCompilingOsr();
497*795d594fSAndroid Build Coastguard Worker   }
498*795d594fSAndroid Build Coastguard Worker 
AddCHASingleImplementationDependency(ArtMethod * method)499*795d594fSAndroid Build Coastguard Worker   void AddCHASingleImplementationDependency(ArtMethod* method) {
500*795d594fSAndroid Build Coastguard Worker     cha_single_implementation_list_.insert(method);
501*795d594fSAndroid Build Coastguard Worker   }
502*795d594fSAndroid Build Coastguard Worker 
HasShouldDeoptimizeFlag()503*795d594fSAndroid Build Coastguard Worker   bool HasShouldDeoptimizeFlag() const {
504*795d594fSAndroid Build Coastguard Worker     return number_of_cha_guards_ != 0 || debuggable_;
505*795d594fSAndroid Build Coastguard Worker   }
506*795d594fSAndroid Build Coastguard Worker 
HasTryCatch()507*795d594fSAndroid Build Coastguard Worker   bool HasTryCatch() const { return has_try_catch_; }
SetHasTryCatch(bool value)508*795d594fSAndroid Build Coastguard Worker   void SetHasTryCatch(bool value) { has_try_catch_ = value; }
509*795d594fSAndroid Build Coastguard Worker 
HasMonitorOperations()510*795d594fSAndroid Build Coastguard Worker   bool HasMonitorOperations() const { return has_monitor_operations_; }
SetHasMonitorOperations(bool value)511*795d594fSAndroid Build Coastguard Worker   void SetHasMonitorOperations(bool value) { has_monitor_operations_ = value; }
512*795d594fSAndroid Build Coastguard Worker 
HasTraditionalSIMD()513*795d594fSAndroid Build Coastguard Worker   bool HasTraditionalSIMD() { return has_traditional_simd_; }
SetHasTraditionalSIMD(bool value)514*795d594fSAndroid Build Coastguard Worker   void SetHasTraditionalSIMD(bool value) { has_traditional_simd_ = value; }
515*795d594fSAndroid Build Coastguard Worker 
HasPredicatedSIMD()516*795d594fSAndroid Build Coastguard Worker   bool HasPredicatedSIMD() { return has_predicated_simd_; }
SetHasPredicatedSIMD(bool value)517*795d594fSAndroid Build Coastguard Worker   void SetHasPredicatedSIMD(bool value) { has_predicated_simd_ = value; }
518*795d594fSAndroid Build Coastguard Worker 
HasSIMD()519*795d594fSAndroid Build Coastguard Worker   bool HasSIMD() const { return has_traditional_simd_ || has_predicated_simd_; }
520*795d594fSAndroid Build Coastguard Worker 
HasLoops()521*795d594fSAndroid Build Coastguard Worker   bool HasLoops() const { return has_loops_; }
SetHasLoops(bool value)522*795d594fSAndroid Build Coastguard Worker   void SetHasLoops(bool value) { has_loops_ = value; }
523*795d594fSAndroid Build Coastguard Worker 
HasIrreducibleLoops()524*795d594fSAndroid Build Coastguard Worker   bool HasIrreducibleLoops() const { return has_irreducible_loops_; }
SetHasIrreducibleLoops(bool value)525*795d594fSAndroid Build Coastguard Worker   void SetHasIrreducibleLoops(bool value) { has_irreducible_loops_ = value; }
526*795d594fSAndroid Build Coastguard Worker 
HasDirectCriticalNativeCall()527*795d594fSAndroid Build Coastguard Worker   bool HasDirectCriticalNativeCall() const { return has_direct_critical_native_call_; }
SetHasDirectCriticalNativeCall(bool value)528*795d594fSAndroid Build Coastguard Worker   void SetHasDirectCriticalNativeCall(bool value) { has_direct_critical_native_call_ = value; }
529*795d594fSAndroid Build Coastguard Worker 
HasAlwaysThrowingInvokes()530*795d594fSAndroid Build Coastguard Worker   bool HasAlwaysThrowingInvokes() const { return has_always_throwing_invokes_; }
SetHasAlwaysThrowingInvokes(bool value)531*795d594fSAndroid Build Coastguard Worker   void SetHasAlwaysThrowingInvokes(bool value) { has_always_throwing_invokes_ = value; }
532*795d594fSAndroid Build Coastguard Worker 
GetArtMethod()533*795d594fSAndroid Build Coastguard Worker   ArtMethod* GetArtMethod() const { return art_method_; }
SetArtMethod(ArtMethod * method)534*795d594fSAndroid Build Coastguard Worker   void SetArtMethod(ArtMethod* method) { art_method_ = method; }
535*795d594fSAndroid Build Coastguard Worker 
SetProfilingInfo(ProfilingInfo * info)536*795d594fSAndroid Build Coastguard Worker   void SetProfilingInfo(ProfilingInfo* info) { profiling_info_ = info; }
GetProfilingInfo()537*795d594fSAndroid Build Coastguard Worker   ProfilingInfo* GetProfilingInfo() const { return profiling_info_; }
538*795d594fSAndroid Build Coastguard Worker 
GetInexactObjectRti()539*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo GetInexactObjectRti() {
540*795d594fSAndroid Build Coastguard Worker     return ReferenceTypeInfo::Create(handle_cache_.GetObjectClassHandle(), /* is_exact= */ false);
541*795d594fSAndroid Build Coastguard Worker   }
542*795d594fSAndroid Build Coastguard Worker 
GetNumberOfCHAGuards()543*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfCHAGuards() const { return number_of_cha_guards_; }
SetNumberOfCHAGuards(uint32_t num)544*795d594fSAndroid Build Coastguard Worker   void SetNumberOfCHAGuards(uint32_t num) { number_of_cha_guards_ = num; }
IncrementNumberOfCHAGuards()545*795d594fSAndroid Build Coastguard Worker   void IncrementNumberOfCHAGuards() { number_of_cha_guards_++; }
546*795d594fSAndroid Build Coastguard Worker 
SetUsefulOptimizing()547*795d594fSAndroid Build Coastguard Worker   void SetUsefulOptimizing() { useful_optimizing_ = true; }
IsUsefulOptimizing()548*795d594fSAndroid Build Coastguard Worker   bool IsUsefulOptimizing() const { return useful_optimizing_; }
549*795d594fSAndroid Build Coastguard Worker 
550*795d594fSAndroid Build Coastguard Worker  private:
551*795d594fSAndroid Build Coastguard Worker   void RemoveDeadBlocksInstructionsAsUsersAndDisconnect(const ArenaBitVector& visited) const;
552*795d594fSAndroid Build Coastguard Worker   void RemoveDeadBlocks(const ArenaBitVector& visited);
553*795d594fSAndroid Build Coastguard Worker 
554*795d594fSAndroid Build Coastguard Worker   template <class InstructionType, typename ValueType>
555*795d594fSAndroid Build Coastguard Worker   InstructionType* CreateConstant(ValueType value,
556*795d594fSAndroid Build Coastguard Worker                                   ArenaSafeMap<ValueType, InstructionType*>* cache);
557*795d594fSAndroid Build Coastguard Worker 
558*795d594fSAndroid Build Coastguard Worker   void InsertConstant(HConstant* instruction);
559*795d594fSAndroid Build Coastguard Worker 
560*795d594fSAndroid Build Coastguard Worker   // Cache a float constant into the graph. This method should only be
561*795d594fSAndroid Build Coastguard Worker   // called by the SsaBuilder when creating "equivalent" instructions.
562*795d594fSAndroid Build Coastguard Worker   void CacheFloatConstant(HFloatConstant* constant);
563*795d594fSAndroid Build Coastguard Worker 
564*795d594fSAndroid Build Coastguard Worker   // See CacheFloatConstant comment.
565*795d594fSAndroid Build Coastguard Worker   void CacheDoubleConstant(HDoubleConstant* constant);
566*795d594fSAndroid Build Coastguard Worker 
567*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* const allocator_;
568*795d594fSAndroid Build Coastguard Worker   ArenaStack* const arena_stack_;
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker   HandleCache handle_cache_;
571*795d594fSAndroid Build Coastguard Worker 
572*795d594fSAndroid Build Coastguard Worker   // List of blocks in insertion order.
573*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> blocks_;
574*795d594fSAndroid Build Coastguard Worker 
575*795d594fSAndroid Build Coastguard Worker   // List of blocks to perform a reverse post order tree traversal.
576*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> reverse_post_order_;
577*795d594fSAndroid Build Coastguard Worker 
578*795d594fSAndroid Build Coastguard Worker   // List of blocks to perform a linear order tree traversal. Unlike the reverse
579*795d594fSAndroid Build Coastguard Worker   // post order, this order is not incrementally kept up-to-date.
580*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> linear_order_;
581*795d594fSAndroid Build Coastguard Worker 
582*795d594fSAndroid Build Coastguard Worker   HBasicBlock* entry_block_;
583*795d594fSAndroid Build Coastguard Worker   HBasicBlock* exit_block_;
584*795d594fSAndroid Build Coastguard Worker 
585*795d594fSAndroid Build Coastguard Worker   // The number of virtual registers in this method. Contains the parameters.
586*795d594fSAndroid Build Coastguard Worker   uint16_t number_of_vregs_;
587*795d594fSAndroid Build Coastguard Worker 
588*795d594fSAndroid Build Coastguard Worker   // The number of virtual registers used by parameters of this method.
589*795d594fSAndroid Build Coastguard Worker   uint16_t number_of_in_vregs_;
590*795d594fSAndroid Build Coastguard Worker 
591*795d594fSAndroid Build Coastguard Worker   // Number of vreg size slots that the temporaries use (used in baseline compiler).
592*795d594fSAndroid Build Coastguard Worker   size_t temporaries_vreg_slots_;
593*795d594fSAndroid Build Coastguard Worker 
594*795d594fSAndroid Build Coastguard Worker   // Flag whether there are bounds checks in the graph. We can skip
595*795d594fSAndroid Build Coastguard Worker   // BCE if it's false.
596*795d594fSAndroid Build Coastguard Worker   bool has_bounds_checks_;
597*795d594fSAndroid Build Coastguard Worker 
598*795d594fSAndroid Build Coastguard Worker   // Flag whether there are try/catch blocks in the graph. We will skip
599*795d594fSAndroid Build Coastguard Worker   // try/catch-related passes if it's false.
600*795d594fSAndroid Build Coastguard Worker   bool has_try_catch_;
601*795d594fSAndroid Build Coastguard Worker 
602*795d594fSAndroid Build Coastguard Worker   // Flag whether there are any HMonitorOperation in the graph. If yes this will mandate
603*795d594fSAndroid Build Coastguard Worker   // DexRegisterMap to be present to allow deadlock analysis for non-debuggable code.
604*795d594fSAndroid Build Coastguard Worker   bool has_monitor_operations_;
605*795d594fSAndroid Build Coastguard Worker 
606*795d594fSAndroid Build Coastguard Worker   // Flags whether SIMD (traditional or predicated) instructions appear in the graph.
607*795d594fSAndroid Build Coastguard Worker   // If either is true, the code generators may have to be more careful spilling the wider
608*795d594fSAndroid Build Coastguard Worker   // contents of SIMD registers.
609*795d594fSAndroid Build Coastguard Worker   bool has_traditional_simd_;
610*795d594fSAndroid Build Coastguard Worker   bool has_predicated_simd_;
611*795d594fSAndroid Build Coastguard Worker 
612*795d594fSAndroid Build Coastguard Worker   // Flag whether there are any loops in the graph. We can skip loop
613*795d594fSAndroid Build Coastguard Worker   // optimization if it's false.
614*795d594fSAndroid Build Coastguard Worker   bool has_loops_;
615*795d594fSAndroid Build Coastguard Worker 
616*795d594fSAndroid Build Coastguard Worker   // Flag whether there are any irreducible loops in the graph.
617*795d594fSAndroid Build Coastguard Worker   bool has_irreducible_loops_;
618*795d594fSAndroid Build Coastguard Worker 
619*795d594fSAndroid Build Coastguard Worker   // Flag whether there are any direct calls to native code registered
620*795d594fSAndroid Build Coastguard Worker   // for @CriticalNative methods.
621*795d594fSAndroid Build Coastguard Worker   bool has_direct_critical_native_call_;
622*795d594fSAndroid Build Coastguard Worker 
623*795d594fSAndroid Build Coastguard Worker   // Flag whether the graph contains invokes that always throw.
624*795d594fSAndroid Build Coastguard Worker   bool has_always_throwing_invokes_;
625*795d594fSAndroid Build Coastguard Worker 
626*795d594fSAndroid Build Coastguard Worker   // Is the code known to be robust against eliminating dead references
627*795d594fSAndroid Build Coastguard Worker   // and the effects of early finalization? If false, dead reference variables
628*795d594fSAndroid Build Coastguard Worker   // are kept if they might be visible to the garbage collector.
629*795d594fSAndroid Build Coastguard Worker   // Currently this means that the class was declared to be dead-reference-safe,
630*795d594fSAndroid Build Coastguard Worker   // the method accesses no reachability-sensitive fields or data, and the same
631*795d594fSAndroid Build Coastguard Worker   // is true for any methods that were inlined into the current one.
632*795d594fSAndroid Build Coastguard Worker   bool dead_reference_safe_;
633*795d594fSAndroid Build Coastguard Worker 
634*795d594fSAndroid Build Coastguard Worker   // Indicates whether the graph should be compiled in a way that
635*795d594fSAndroid Build Coastguard Worker   // ensures full debuggability. If false, we can apply more
636*795d594fSAndroid Build Coastguard Worker   // aggressive optimizations that may limit the level of debugging.
637*795d594fSAndroid Build Coastguard Worker   const bool debuggable_;
638*795d594fSAndroid Build Coastguard Worker 
639*795d594fSAndroid Build Coastguard Worker   // The current id to assign to a newly added instruction. See HInstruction.id_.
640*795d594fSAndroid Build Coastguard Worker   int32_t current_instruction_id_;
641*795d594fSAndroid Build Coastguard Worker 
642*795d594fSAndroid Build Coastguard Worker   // The dex file from which the method is from.
643*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
644*795d594fSAndroid Build Coastguard Worker 
645*795d594fSAndroid Build Coastguard Worker   // The method index in the dex file.
646*795d594fSAndroid Build Coastguard Worker   const uint32_t method_idx_;
647*795d594fSAndroid Build Coastguard Worker 
648*795d594fSAndroid Build Coastguard Worker   // If inlined, this encodes how the callee is being invoked.
649*795d594fSAndroid Build Coastguard Worker   const InvokeType invoke_type_;
650*795d594fSAndroid Build Coastguard Worker 
651*795d594fSAndroid Build Coastguard Worker   // Whether the graph has been transformed to SSA form. Only used
652*795d594fSAndroid Build Coastguard Worker   // in debug mode to ensure we are not using properties only valid
653*795d594fSAndroid Build Coastguard Worker   // for non-SSA form (like the number of temporaries).
654*795d594fSAndroid Build Coastguard Worker   bool in_ssa_form_;
655*795d594fSAndroid Build Coastguard Worker 
656*795d594fSAndroid Build Coastguard Worker   // Number of CHA guards in the graph. Used to short-circuit the
657*795d594fSAndroid Build Coastguard Worker   // CHA guard optimization pass when there is no CHA guard left.
658*795d594fSAndroid Build Coastguard Worker   uint32_t number_of_cha_guards_;
659*795d594fSAndroid Build Coastguard Worker 
660*795d594fSAndroid Build Coastguard Worker   const InstructionSet instruction_set_;
661*795d594fSAndroid Build Coastguard Worker 
662*795d594fSAndroid Build Coastguard Worker   // Cached constants.
663*795d594fSAndroid Build Coastguard Worker   HNullConstant* cached_null_constant_;
664*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
665*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
666*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
667*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
668*795d594fSAndroid Build Coastguard Worker 
669*795d594fSAndroid Build Coastguard Worker   HCurrentMethod* cached_current_method_;
670*795d594fSAndroid Build Coastguard Worker 
671*795d594fSAndroid Build Coastguard Worker   // The ArtMethod this graph is for. Note that for AOT, it may be null,
672*795d594fSAndroid Build Coastguard Worker   // for example for methods whose declaring class could not be resolved
673*795d594fSAndroid Build Coastguard Worker   // (such as when the superclass could not be found).
674*795d594fSAndroid Build Coastguard Worker   ArtMethod* art_method_;
675*795d594fSAndroid Build Coastguard Worker 
676*795d594fSAndroid Build Coastguard Worker   // The `ProfilingInfo` associated with the method being compiled.
677*795d594fSAndroid Build Coastguard Worker   ProfilingInfo* profiling_info_;
678*795d594fSAndroid Build Coastguard Worker 
679*795d594fSAndroid Build Coastguard Worker   // How we are compiling the graph: either optimized, osr, or baseline.
680*795d594fSAndroid Build Coastguard Worker   // For osr, we will make all loops seen as irreducible and emit special
681*795d594fSAndroid Build Coastguard Worker   // stack maps to mark compiled code entries which the interpreter can
682*795d594fSAndroid Build Coastguard Worker   // directly jump to.
683*795d594fSAndroid Build Coastguard Worker   const CompilationKind compilation_kind_;
684*795d594fSAndroid Build Coastguard Worker 
685*795d594fSAndroid Build Coastguard Worker   // Whether after compiling baseline it is still useful re-optimizing this
686*795d594fSAndroid Build Coastguard Worker   // method.
687*795d594fSAndroid Build Coastguard Worker   bool useful_optimizing_;
688*795d594fSAndroid Build Coastguard Worker 
689*795d594fSAndroid Build Coastguard Worker   // List of methods that are assumed to have single implementation.
690*795d594fSAndroid Build Coastguard Worker   ArenaSet<ArtMethod*> cha_single_implementation_list_;
691*795d594fSAndroid Build Coastguard Worker 
692*795d594fSAndroid Build Coastguard Worker   friend class SsaBuilder;           // For caching constants.
693*795d594fSAndroid Build Coastguard Worker   friend class SsaLivenessAnalysis;  // For the linear order.
694*795d594fSAndroid Build Coastguard Worker   friend class HInliner;             // For the reverse post order.
695*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
696*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HGraph);
697*795d594fSAndroid Build Coastguard Worker };
698*795d594fSAndroid Build Coastguard Worker 
699*795d594fSAndroid Build Coastguard Worker class HLoopInformation : public ArenaObject<kArenaAllocLoopInfo> {
700*795d594fSAndroid Build Coastguard Worker  public:
HLoopInformation(HBasicBlock * header,HGraph * graph)701*795d594fSAndroid Build Coastguard Worker   HLoopInformation(HBasicBlock* header, HGraph* graph)
702*795d594fSAndroid Build Coastguard Worker       : header_(header),
703*795d594fSAndroid Build Coastguard Worker         suspend_check_(nullptr),
704*795d594fSAndroid Build Coastguard Worker         irreducible_(false),
705*795d594fSAndroid Build Coastguard Worker         contains_irreducible_loop_(false),
706*795d594fSAndroid Build Coastguard Worker         back_edges_(graph->GetAllocator()->Adapter(kArenaAllocLoopInfoBackEdges)),
707*795d594fSAndroid Build Coastguard Worker         // Make bit vector growable, as the number of blocks may change.
708*795d594fSAndroid Build Coastguard Worker         blocks_(graph->GetAllocator(),
709*795d594fSAndroid Build Coastguard Worker                 graph->GetBlocks().size(),
710*795d594fSAndroid Build Coastguard Worker                 true,
711*795d594fSAndroid Build Coastguard Worker                 kArenaAllocLoopInfoBackEdges) {
712*795d594fSAndroid Build Coastguard Worker     back_edges_.reserve(kDefaultNumberOfBackEdges);
713*795d594fSAndroid Build Coastguard Worker   }
714*795d594fSAndroid Build Coastguard Worker 
IsIrreducible()715*795d594fSAndroid Build Coastguard Worker   bool IsIrreducible() const { return irreducible_; }
ContainsIrreducibleLoop()716*795d594fSAndroid Build Coastguard Worker   bool ContainsIrreducibleLoop() const { return contains_irreducible_loop_; }
717*795d594fSAndroid Build Coastguard Worker 
718*795d594fSAndroid Build Coastguard Worker   void Dump(std::ostream& os);
719*795d594fSAndroid Build Coastguard Worker 
GetHeader()720*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetHeader() const {
721*795d594fSAndroid Build Coastguard Worker     return header_;
722*795d594fSAndroid Build Coastguard Worker   }
723*795d594fSAndroid Build Coastguard Worker 
SetHeader(HBasicBlock * block)724*795d594fSAndroid Build Coastguard Worker   void SetHeader(HBasicBlock* block) {
725*795d594fSAndroid Build Coastguard Worker     header_ = block;
726*795d594fSAndroid Build Coastguard Worker   }
727*795d594fSAndroid Build Coastguard Worker 
GetSuspendCheck()728*795d594fSAndroid Build Coastguard Worker   HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
SetSuspendCheck(HSuspendCheck * check)729*795d594fSAndroid Build Coastguard Worker   void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
HasSuspendCheck()730*795d594fSAndroid Build Coastguard Worker   bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
731*795d594fSAndroid Build Coastguard Worker 
AddBackEdge(HBasicBlock * back_edge)732*795d594fSAndroid Build Coastguard Worker   void AddBackEdge(HBasicBlock* back_edge) {
733*795d594fSAndroid Build Coastguard Worker     back_edges_.push_back(back_edge);
734*795d594fSAndroid Build Coastguard Worker   }
735*795d594fSAndroid Build Coastguard Worker 
RemoveBackEdge(HBasicBlock * back_edge)736*795d594fSAndroid Build Coastguard Worker   void RemoveBackEdge(HBasicBlock* back_edge) {
737*795d594fSAndroid Build Coastguard Worker     RemoveElement(back_edges_, back_edge);
738*795d594fSAndroid Build Coastguard Worker   }
739*795d594fSAndroid Build Coastguard Worker 
IsBackEdge(const HBasicBlock & block)740*795d594fSAndroid Build Coastguard Worker   bool IsBackEdge(const HBasicBlock& block) const {
741*795d594fSAndroid Build Coastguard Worker     return ContainsElement(back_edges_, &block);
742*795d594fSAndroid Build Coastguard Worker   }
743*795d594fSAndroid Build Coastguard Worker 
NumberOfBackEdges()744*795d594fSAndroid Build Coastguard Worker   size_t NumberOfBackEdges() const {
745*795d594fSAndroid Build Coastguard Worker     return back_edges_.size();
746*795d594fSAndroid Build Coastguard Worker   }
747*795d594fSAndroid Build Coastguard Worker 
748*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetPreHeader() const;
749*795d594fSAndroid Build Coastguard Worker 
GetBackEdges()750*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetBackEdges() const {
751*795d594fSAndroid Build Coastguard Worker     return back_edges_;
752*795d594fSAndroid Build Coastguard Worker   }
753*795d594fSAndroid Build Coastguard Worker 
754*795d594fSAndroid Build Coastguard Worker   // Returns the lifetime position of the back edge that has the
755*795d594fSAndroid Build Coastguard Worker   // greatest lifetime position.
756*795d594fSAndroid Build Coastguard Worker   size_t GetLifetimeEnd() const;
757*795d594fSAndroid Build Coastguard Worker 
ReplaceBackEdge(HBasicBlock * existing,HBasicBlock * new_back_edge)758*795d594fSAndroid Build Coastguard Worker   void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
759*795d594fSAndroid Build Coastguard Worker     ReplaceElement(back_edges_, existing, new_back_edge);
760*795d594fSAndroid Build Coastguard Worker   }
761*795d594fSAndroid Build Coastguard Worker 
762*795d594fSAndroid Build Coastguard Worker   // Finds blocks that are part of this loop.
763*795d594fSAndroid Build Coastguard Worker   void Populate();
764*795d594fSAndroid Build Coastguard Worker 
765*795d594fSAndroid Build Coastguard Worker   // Updates blocks population of the loop and all of its outer' ones recursively after the
766*795d594fSAndroid Build Coastguard Worker   // population of the inner loop is updated.
767*795d594fSAndroid Build Coastguard Worker   void PopulateInnerLoopUpwards(HLoopInformation* inner_loop);
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker   // Returns whether this loop information contains `block`.
770*795d594fSAndroid Build Coastguard Worker   // Note that this loop information *must* be populated before entering this function.
771*795d594fSAndroid Build Coastguard Worker   bool Contains(const HBasicBlock& block) const;
772*795d594fSAndroid Build Coastguard Worker 
773*795d594fSAndroid Build Coastguard Worker   // Returns whether this loop information is an inner loop of `other`.
774*795d594fSAndroid Build Coastguard Worker   // Note that `other` *must* be populated before entering this function.
775*795d594fSAndroid Build Coastguard Worker   bool IsIn(const HLoopInformation& other) const;
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker   // Returns true if instruction is not defined within this loop.
778*795d594fSAndroid Build Coastguard Worker   bool IsDefinedOutOfTheLoop(HInstruction* instruction) const;
779*795d594fSAndroid Build Coastguard Worker 
GetBlocks()780*795d594fSAndroid Build Coastguard Worker   const ArenaBitVector& GetBlocks() const { return blocks_; }
781*795d594fSAndroid Build Coastguard Worker 
782*795d594fSAndroid Build Coastguard Worker   void Add(HBasicBlock* block);
783*795d594fSAndroid Build Coastguard Worker   void Remove(HBasicBlock* block);
784*795d594fSAndroid Build Coastguard Worker 
ClearAllBlocks()785*795d594fSAndroid Build Coastguard Worker   void ClearAllBlocks() {
786*795d594fSAndroid Build Coastguard Worker     blocks_.ClearAllBits();
787*795d594fSAndroid Build Coastguard Worker   }
788*795d594fSAndroid Build Coastguard Worker 
789*795d594fSAndroid Build Coastguard Worker   bool HasBackEdgeNotDominatedByHeader() const;
790*795d594fSAndroid Build Coastguard Worker 
IsPopulated()791*795d594fSAndroid Build Coastguard Worker   bool IsPopulated() const {
792*795d594fSAndroid Build Coastguard Worker     return blocks_.GetHighestBitSet() != -1;
793*795d594fSAndroid Build Coastguard Worker   }
794*795d594fSAndroid Build Coastguard Worker 
795*795d594fSAndroid Build Coastguard Worker   bool DominatesAllBackEdges(HBasicBlock* block);
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker   bool HasExitEdge() const;
798*795d594fSAndroid Build Coastguard Worker 
799*795d594fSAndroid Build Coastguard Worker   // Resets back edge and blocks-in-loop data.
ResetBasicBlockData()800*795d594fSAndroid Build Coastguard Worker   void ResetBasicBlockData() {
801*795d594fSAndroid Build Coastguard Worker     back_edges_.clear();
802*795d594fSAndroid Build Coastguard Worker     ClearAllBlocks();
803*795d594fSAndroid Build Coastguard Worker   }
804*795d594fSAndroid Build Coastguard Worker 
805*795d594fSAndroid Build Coastguard Worker  private:
806*795d594fSAndroid Build Coastguard Worker   // Internal recursive implementation of `Populate`.
807*795d594fSAndroid Build Coastguard Worker   void PopulateRecursive(HBasicBlock* block);
808*795d594fSAndroid Build Coastguard Worker   void PopulateIrreducibleRecursive(HBasicBlock* block, ArenaBitVector* finalized);
809*795d594fSAndroid Build Coastguard Worker 
810*795d594fSAndroid Build Coastguard Worker   HBasicBlock* header_;
811*795d594fSAndroid Build Coastguard Worker   HSuspendCheck* suspend_check_;
812*795d594fSAndroid Build Coastguard Worker   bool irreducible_;
813*795d594fSAndroid Build Coastguard Worker   bool contains_irreducible_loop_;
814*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> back_edges_;
815*795d594fSAndroid Build Coastguard Worker   ArenaBitVector blocks_;
816*795d594fSAndroid Build Coastguard Worker 
817*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
818*795d594fSAndroid Build Coastguard Worker };
819*795d594fSAndroid Build Coastguard Worker 
820*795d594fSAndroid Build Coastguard Worker // Stores try/catch information for basic blocks.
821*795d594fSAndroid Build Coastguard Worker // Note that HGraph is constructed so that catch blocks cannot simultaneously
822*795d594fSAndroid Build Coastguard Worker // be try blocks.
823*795d594fSAndroid Build Coastguard Worker class TryCatchInformation : public ArenaObject<kArenaAllocTryCatchInfo> {
824*795d594fSAndroid Build Coastguard Worker  public:
825*795d594fSAndroid Build Coastguard Worker   // Try block information constructor.
TryCatchInformation(const HTryBoundary & try_entry)826*795d594fSAndroid Build Coastguard Worker   explicit TryCatchInformation(const HTryBoundary& try_entry)
827*795d594fSAndroid Build Coastguard Worker       : try_entry_(&try_entry),
828*795d594fSAndroid Build Coastguard Worker         catch_dex_file_(nullptr),
829*795d594fSAndroid Build Coastguard Worker         catch_type_index_(dex::TypeIndex::Invalid()) {
830*795d594fSAndroid Build Coastguard Worker     DCHECK(try_entry_ != nullptr);
831*795d594fSAndroid Build Coastguard Worker   }
832*795d594fSAndroid Build Coastguard Worker 
833*795d594fSAndroid Build Coastguard Worker   // Catch block information constructor.
TryCatchInformation(dex::TypeIndex catch_type_index,const DexFile & dex_file)834*795d594fSAndroid Build Coastguard Worker   TryCatchInformation(dex::TypeIndex catch_type_index, const DexFile& dex_file)
835*795d594fSAndroid Build Coastguard Worker       : try_entry_(nullptr),
836*795d594fSAndroid Build Coastguard Worker         catch_dex_file_(&dex_file),
837*795d594fSAndroid Build Coastguard Worker         catch_type_index_(catch_type_index) {}
838*795d594fSAndroid Build Coastguard Worker 
IsTryBlock()839*795d594fSAndroid Build Coastguard Worker   bool IsTryBlock() const { return try_entry_ != nullptr; }
840*795d594fSAndroid Build Coastguard Worker 
GetTryEntry()841*795d594fSAndroid Build Coastguard Worker   const HTryBoundary& GetTryEntry() const {
842*795d594fSAndroid Build Coastguard Worker     DCHECK(IsTryBlock());
843*795d594fSAndroid Build Coastguard Worker     return *try_entry_;
844*795d594fSAndroid Build Coastguard Worker   }
845*795d594fSAndroid Build Coastguard Worker 
IsCatchBlock()846*795d594fSAndroid Build Coastguard Worker   bool IsCatchBlock() const { return catch_dex_file_ != nullptr; }
847*795d594fSAndroid Build Coastguard Worker 
IsValidTypeIndex()848*795d594fSAndroid Build Coastguard Worker   bool IsValidTypeIndex() const {
849*795d594fSAndroid Build Coastguard Worker     DCHECK(IsCatchBlock());
850*795d594fSAndroid Build Coastguard Worker     return catch_type_index_.IsValid();
851*795d594fSAndroid Build Coastguard Worker   }
852*795d594fSAndroid Build Coastguard Worker 
GetCatchTypeIndex()853*795d594fSAndroid Build Coastguard Worker   dex::TypeIndex GetCatchTypeIndex() const {
854*795d594fSAndroid Build Coastguard Worker     DCHECK(IsCatchBlock());
855*795d594fSAndroid Build Coastguard Worker     return catch_type_index_;
856*795d594fSAndroid Build Coastguard Worker   }
857*795d594fSAndroid Build Coastguard Worker 
GetCatchDexFile()858*795d594fSAndroid Build Coastguard Worker   const DexFile& GetCatchDexFile() const {
859*795d594fSAndroid Build Coastguard Worker     DCHECK(IsCatchBlock());
860*795d594fSAndroid Build Coastguard Worker     return *catch_dex_file_;
861*795d594fSAndroid Build Coastguard Worker   }
862*795d594fSAndroid Build Coastguard Worker 
SetInvalidTypeIndex()863*795d594fSAndroid Build Coastguard Worker   void SetInvalidTypeIndex() {
864*795d594fSAndroid Build Coastguard Worker     catch_type_index_ = dex::TypeIndex::Invalid();
865*795d594fSAndroid Build Coastguard Worker   }
866*795d594fSAndroid Build Coastguard Worker 
867*795d594fSAndroid Build Coastguard Worker  private:
868*795d594fSAndroid Build Coastguard Worker   // One of possibly several TryBoundary instructions entering the block's try.
869*795d594fSAndroid Build Coastguard Worker   // Only set for try blocks.
870*795d594fSAndroid Build Coastguard Worker   const HTryBoundary* try_entry_;
871*795d594fSAndroid Build Coastguard Worker 
872*795d594fSAndroid Build Coastguard Worker   // Exception type information. Only set for catch blocks.
873*795d594fSAndroid Build Coastguard Worker   const DexFile* catch_dex_file_;
874*795d594fSAndroid Build Coastguard Worker   dex::TypeIndex catch_type_index_;
875*795d594fSAndroid Build Coastguard Worker };
876*795d594fSAndroid Build Coastguard Worker 
877*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNoLifetime = -1;
878*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kInvalidBlockId = static_cast<uint32_t>(-1);
879*795d594fSAndroid Build Coastguard Worker 
880*795d594fSAndroid Build Coastguard Worker // A block in a method. Contains the list of instructions represented
881*795d594fSAndroid Build Coastguard Worker // as a double linked list. Each block knows its predecessors and
882*795d594fSAndroid Build Coastguard Worker // successors.
883*795d594fSAndroid Build Coastguard Worker 
884*795d594fSAndroid Build Coastguard Worker class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> {
885*795d594fSAndroid Build Coastguard Worker  public:
886*795d594fSAndroid Build Coastguard Worker   explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
graph_(graph)887*795d594fSAndroid Build Coastguard Worker       : graph_(graph),
888*795d594fSAndroid Build Coastguard Worker         predecessors_(graph->GetAllocator()->Adapter(kArenaAllocPredecessors)),
889*795d594fSAndroid Build Coastguard Worker         successors_(graph->GetAllocator()->Adapter(kArenaAllocSuccessors)),
890*795d594fSAndroid Build Coastguard Worker         loop_information_(nullptr),
891*795d594fSAndroid Build Coastguard Worker         dominator_(nullptr),
892*795d594fSAndroid Build Coastguard Worker         dominated_blocks_(graph->GetAllocator()->Adapter(kArenaAllocDominated)),
893*795d594fSAndroid Build Coastguard Worker         block_id_(kInvalidBlockId),
894*795d594fSAndroid Build Coastguard Worker         dex_pc_(dex_pc),
895*795d594fSAndroid Build Coastguard Worker         lifetime_start_(kNoLifetime),
896*795d594fSAndroid Build Coastguard Worker         lifetime_end_(kNoLifetime),
897*795d594fSAndroid Build Coastguard Worker         try_catch_information_(nullptr) {
898*795d594fSAndroid Build Coastguard Worker     predecessors_.reserve(kDefaultNumberOfPredecessors);
899*795d594fSAndroid Build Coastguard Worker     successors_.reserve(kDefaultNumberOfSuccessors);
900*795d594fSAndroid Build Coastguard Worker     dominated_blocks_.reserve(kDefaultNumberOfDominatedBlocks);
901*795d594fSAndroid Build Coastguard Worker   }
902*795d594fSAndroid Build Coastguard Worker 
GetPredecessors()903*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetPredecessors() const {
904*795d594fSAndroid Build Coastguard Worker     return predecessors_;
905*795d594fSAndroid Build Coastguard Worker   }
906*795d594fSAndroid Build Coastguard Worker 
GetNumberOfPredecessors()907*795d594fSAndroid Build Coastguard Worker   size_t GetNumberOfPredecessors() const {
908*795d594fSAndroid Build Coastguard Worker     return GetPredecessors().size();
909*795d594fSAndroid Build Coastguard Worker   }
910*795d594fSAndroid Build Coastguard Worker 
GetSuccessors()911*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetSuccessors() const {
912*795d594fSAndroid Build Coastguard Worker     return successors_;
913*795d594fSAndroid Build Coastguard Worker   }
914*795d594fSAndroid Build Coastguard Worker 
915*795d594fSAndroid Build Coastguard Worker   ArrayRef<HBasicBlock* const> GetNormalSuccessors() const;
916*795d594fSAndroid Build Coastguard Worker   ArrayRef<HBasicBlock* const> GetExceptionalSuccessors() const;
917*795d594fSAndroid Build Coastguard Worker 
918*795d594fSAndroid Build Coastguard Worker   bool HasSuccessor(const HBasicBlock* block, size_t start_from = 0u) {
919*795d594fSAndroid Build Coastguard Worker     return ContainsElement(successors_, block, start_from);
920*795d594fSAndroid Build Coastguard Worker   }
921*795d594fSAndroid Build Coastguard Worker 
GetDominatedBlocks()922*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& GetDominatedBlocks() const {
923*795d594fSAndroid Build Coastguard Worker     return dominated_blocks_;
924*795d594fSAndroid Build Coastguard Worker   }
925*795d594fSAndroid Build Coastguard Worker 
IsEntryBlock()926*795d594fSAndroid Build Coastguard Worker   bool IsEntryBlock() const {
927*795d594fSAndroid Build Coastguard Worker     return graph_->GetEntryBlock() == this;
928*795d594fSAndroid Build Coastguard Worker   }
929*795d594fSAndroid Build Coastguard Worker 
IsExitBlock()930*795d594fSAndroid Build Coastguard Worker   bool IsExitBlock() const {
931*795d594fSAndroid Build Coastguard Worker     return graph_->GetExitBlock() == this;
932*795d594fSAndroid Build Coastguard Worker   }
933*795d594fSAndroid Build Coastguard Worker 
934*795d594fSAndroid Build Coastguard Worker   bool IsSingleGoto() const;
935*795d594fSAndroid Build Coastguard Worker   bool IsSingleReturn() const;
936*795d594fSAndroid Build Coastguard Worker   bool IsSingleReturnOrReturnVoidAllowingPhis() const;
937*795d594fSAndroid Build Coastguard Worker   bool IsSingleTryBoundary() const;
938*795d594fSAndroid Build Coastguard Worker 
939*795d594fSAndroid Build Coastguard Worker   // Returns true if this block emits nothing but a jump.
IsSingleJump()940*795d594fSAndroid Build Coastguard Worker   bool IsSingleJump() const {
941*795d594fSAndroid Build Coastguard Worker     HLoopInformation* loop_info = GetLoopInformation();
942*795d594fSAndroid Build Coastguard Worker     return (IsSingleGoto() || IsSingleTryBoundary())
943*795d594fSAndroid Build Coastguard Worker            // Back edges generate a suspend check.
944*795d594fSAndroid Build Coastguard Worker            && (loop_info == nullptr || !loop_info->IsBackEdge(*this));
945*795d594fSAndroid Build Coastguard Worker   }
946*795d594fSAndroid Build Coastguard Worker 
AddBackEdge(HBasicBlock * back_edge)947*795d594fSAndroid Build Coastguard Worker   void AddBackEdge(HBasicBlock* back_edge) {
948*795d594fSAndroid Build Coastguard Worker     if (loop_information_ == nullptr) {
949*795d594fSAndroid Build Coastguard Worker       loop_information_ = new (graph_->GetAllocator()) HLoopInformation(this, graph_);
950*795d594fSAndroid Build Coastguard Worker     }
951*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(loop_information_->GetHeader(), this);
952*795d594fSAndroid Build Coastguard Worker     loop_information_->AddBackEdge(back_edge);
953*795d594fSAndroid Build Coastguard Worker   }
954*795d594fSAndroid Build Coastguard Worker 
955*795d594fSAndroid Build Coastguard Worker   // Registers a back edge; if the block was not a loop header before the call associates a newly
956*795d594fSAndroid Build Coastguard Worker   // created loop info with it.
957*795d594fSAndroid Build Coastguard Worker   //
958*795d594fSAndroid Build Coastguard Worker   // Used in SuperblockCloner to preserve LoopInformation object instead of reseting loop
959*795d594fSAndroid Build Coastguard Worker   // info for all blocks during back edges recalculation.
AddBackEdgeWhileUpdating(HBasicBlock * back_edge)960*795d594fSAndroid Build Coastguard Worker   void AddBackEdgeWhileUpdating(HBasicBlock* back_edge) {
961*795d594fSAndroid Build Coastguard Worker     if (loop_information_ == nullptr || loop_information_->GetHeader() != this) {
962*795d594fSAndroid Build Coastguard Worker       loop_information_ = new (graph_->GetAllocator()) HLoopInformation(this, graph_);
963*795d594fSAndroid Build Coastguard Worker     }
964*795d594fSAndroid Build Coastguard Worker     loop_information_->AddBackEdge(back_edge);
965*795d594fSAndroid Build Coastguard Worker   }
966*795d594fSAndroid Build Coastguard Worker 
GetGraph()967*795d594fSAndroid Build Coastguard Worker   HGraph* GetGraph() const { return graph_; }
SetGraph(HGraph * graph)968*795d594fSAndroid Build Coastguard Worker   void SetGraph(HGraph* graph) { graph_ = graph; }
969*795d594fSAndroid Build Coastguard Worker 
GetBlockId()970*795d594fSAndroid Build Coastguard Worker   uint32_t GetBlockId() const { return block_id_; }
SetBlockId(int id)971*795d594fSAndroid Build Coastguard Worker   void SetBlockId(int id) { block_id_ = id; }
GetDexPc()972*795d594fSAndroid Build Coastguard Worker   uint32_t GetDexPc() const { return dex_pc_; }
973*795d594fSAndroid Build Coastguard Worker 
GetDominator()974*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetDominator() const { return dominator_; }
SetDominator(HBasicBlock * dominator)975*795d594fSAndroid Build Coastguard Worker   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
AddDominatedBlock(HBasicBlock * block)976*795d594fSAndroid Build Coastguard Worker   void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.push_back(block); }
977*795d594fSAndroid Build Coastguard Worker 
RemoveDominatedBlock(HBasicBlock * block)978*795d594fSAndroid Build Coastguard Worker   void RemoveDominatedBlock(HBasicBlock* block) {
979*795d594fSAndroid Build Coastguard Worker     RemoveElement(dominated_blocks_, block);
980*795d594fSAndroid Build Coastguard Worker   }
981*795d594fSAndroid Build Coastguard Worker 
ReplaceDominatedBlock(HBasicBlock * existing,HBasicBlock * new_block)982*795d594fSAndroid Build Coastguard Worker   void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
983*795d594fSAndroid Build Coastguard Worker     ReplaceElement(dominated_blocks_, existing, new_block);
984*795d594fSAndroid Build Coastguard Worker   }
985*795d594fSAndroid Build Coastguard Worker 
986*795d594fSAndroid Build Coastguard Worker   void ClearDominanceInformation();
987*795d594fSAndroid Build Coastguard Worker 
NumberOfBackEdges()988*795d594fSAndroid Build Coastguard Worker   int NumberOfBackEdges() const {
989*795d594fSAndroid Build Coastguard Worker     return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
990*795d594fSAndroid Build Coastguard Worker   }
991*795d594fSAndroid Build Coastguard Worker 
GetFirstInstruction()992*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
GetLastInstruction()993*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
GetInstructions()994*795d594fSAndroid Build Coastguard Worker   const HInstructionList& GetInstructions() const { return instructions_; }
GetFirstPhi()995*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
GetLastPhi()996*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
GetPhis()997*795d594fSAndroid Build Coastguard Worker   const HInstructionList& GetPhis() const { return phis_; }
998*795d594fSAndroid Build Coastguard Worker 
999*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFirstInstructionDisregardMoves() const;
1000*795d594fSAndroid Build Coastguard Worker 
AddSuccessor(HBasicBlock * block)1001*795d594fSAndroid Build Coastguard Worker   void AddSuccessor(HBasicBlock* block) {
1002*795d594fSAndroid Build Coastguard Worker     successors_.push_back(block);
1003*795d594fSAndroid Build Coastguard Worker     block->predecessors_.push_back(this);
1004*795d594fSAndroid Build Coastguard Worker   }
1005*795d594fSAndroid Build Coastguard Worker 
ReplaceSuccessor(HBasicBlock * existing,HBasicBlock * new_block)1006*795d594fSAndroid Build Coastguard Worker   void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
1007*795d594fSAndroid Build Coastguard Worker     size_t successor_index = GetSuccessorIndexOf(existing);
1008*795d594fSAndroid Build Coastguard Worker     existing->RemovePredecessor(this);
1009*795d594fSAndroid Build Coastguard Worker     new_block->predecessors_.push_back(this);
1010*795d594fSAndroid Build Coastguard Worker     successors_[successor_index] = new_block;
1011*795d594fSAndroid Build Coastguard Worker   }
1012*795d594fSAndroid Build Coastguard Worker 
ReplacePredecessor(HBasicBlock * existing,HBasicBlock * new_block)1013*795d594fSAndroid Build Coastguard Worker   void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
1014*795d594fSAndroid Build Coastguard Worker     size_t predecessor_index = GetPredecessorIndexOf(existing);
1015*795d594fSAndroid Build Coastguard Worker     existing->RemoveSuccessor(this);
1016*795d594fSAndroid Build Coastguard Worker     new_block->successors_.push_back(this);
1017*795d594fSAndroid Build Coastguard Worker     predecessors_[predecessor_index] = new_block;
1018*795d594fSAndroid Build Coastguard Worker   }
1019*795d594fSAndroid Build Coastguard Worker 
1020*795d594fSAndroid Build Coastguard Worker   // Insert `this` between `predecessor` and `successor. This method
1021*795d594fSAndroid Build Coastguard Worker   // preserves the indices, and will update the first edge found between
1022*795d594fSAndroid Build Coastguard Worker   // `predecessor` and `successor`.
InsertBetween(HBasicBlock * predecessor,HBasicBlock * successor)1023*795d594fSAndroid Build Coastguard Worker   void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
1024*795d594fSAndroid Build Coastguard Worker     size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
1025*795d594fSAndroid Build Coastguard Worker     size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
1026*795d594fSAndroid Build Coastguard Worker     successor->predecessors_[predecessor_index] = this;
1027*795d594fSAndroid Build Coastguard Worker     predecessor->successors_[successor_index] = this;
1028*795d594fSAndroid Build Coastguard Worker     successors_.push_back(successor);
1029*795d594fSAndroid Build Coastguard Worker     predecessors_.push_back(predecessor);
1030*795d594fSAndroid Build Coastguard Worker   }
1031*795d594fSAndroid Build Coastguard Worker 
RemovePredecessor(HBasicBlock * block)1032*795d594fSAndroid Build Coastguard Worker   void RemovePredecessor(HBasicBlock* block) {
1033*795d594fSAndroid Build Coastguard Worker     predecessors_.erase(predecessors_.begin() + GetPredecessorIndexOf(block));
1034*795d594fSAndroid Build Coastguard Worker   }
1035*795d594fSAndroid Build Coastguard Worker 
RemoveSuccessor(HBasicBlock * block)1036*795d594fSAndroid Build Coastguard Worker   void RemoveSuccessor(HBasicBlock* block) {
1037*795d594fSAndroid Build Coastguard Worker     successors_.erase(successors_.begin() + GetSuccessorIndexOf(block));
1038*795d594fSAndroid Build Coastguard Worker   }
1039*795d594fSAndroid Build Coastguard Worker 
ClearAllPredecessors()1040*795d594fSAndroid Build Coastguard Worker   void ClearAllPredecessors() {
1041*795d594fSAndroid Build Coastguard Worker     predecessors_.clear();
1042*795d594fSAndroid Build Coastguard Worker   }
1043*795d594fSAndroid Build Coastguard Worker 
AddPredecessor(HBasicBlock * block)1044*795d594fSAndroid Build Coastguard Worker   void AddPredecessor(HBasicBlock* block) {
1045*795d594fSAndroid Build Coastguard Worker     predecessors_.push_back(block);
1046*795d594fSAndroid Build Coastguard Worker     block->successors_.push_back(this);
1047*795d594fSAndroid Build Coastguard Worker   }
1048*795d594fSAndroid Build Coastguard Worker 
SwapPredecessors()1049*795d594fSAndroid Build Coastguard Worker   void SwapPredecessors() {
1050*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(predecessors_.size(), 2u);
1051*795d594fSAndroid Build Coastguard Worker     std::swap(predecessors_[0], predecessors_[1]);
1052*795d594fSAndroid Build Coastguard Worker   }
1053*795d594fSAndroid Build Coastguard Worker 
SwapSuccessors()1054*795d594fSAndroid Build Coastguard Worker   void SwapSuccessors() {
1055*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(successors_.size(), 2u);
1056*795d594fSAndroid Build Coastguard Worker     std::swap(successors_[0], successors_[1]);
1057*795d594fSAndroid Build Coastguard Worker   }
1058*795d594fSAndroid Build Coastguard Worker 
GetPredecessorIndexOf(HBasicBlock * predecessor)1059*795d594fSAndroid Build Coastguard Worker   size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const {
1060*795d594fSAndroid Build Coastguard Worker     return IndexOfElement(predecessors_, predecessor);
1061*795d594fSAndroid Build Coastguard Worker   }
1062*795d594fSAndroid Build Coastguard Worker 
GetSuccessorIndexOf(HBasicBlock * successor)1063*795d594fSAndroid Build Coastguard Worker   size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
1064*795d594fSAndroid Build Coastguard Worker     return IndexOfElement(successors_, successor);
1065*795d594fSAndroid Build Coastguard Worker   }
1066*795d594fSAndroid Build Coastguard Worker 
GetSinglePredecessor()1067*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetSinglePredecessor() const {
1068*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetPredecessors().size(), 1u);
1069*795d594fSAndroid Build Coastguard Worker     return GetPredecessors()[0];
1070*795d594fSAndroid Build Coastguard Worker   }
1071*795d594fSAndroid Build Coastguard Worker 
GetSingleSuccessor()1072*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetSingleSuccessor() const {
1073*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetSuccessors().size(), 1u);
1074*795d594fSAndroid Build Coastguard Worker     return GetSuccessors()[0];
1075*795d594fSAndroid Build Coastguard Worker   }
1076*795d594fSAndroid Build Coastguard Worker 
1077*795d594fSAndroid Build Coastguard Worker   // Returns whether the first occurrence of `predecessor` in the list of
1078*795d594fSAndroid Build Coastguard Worker   // predecessors is at index `idx`.
IsFirstIndexOfPredecessor(HBasicBlock * predecessor,size_t idx)1079*795d594fSAndroid Build Coastguard Worker   bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const {
1080*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetPredecessors()[idx], predecessor);
1081*795d594fSAndroid Build Coastguard Worker     return GetPredecessorIndexOf(predecessor) == idx;
1082*795d594fSAndroid Build Coastguard Worker   }
1083*795d594fSAndroid Build Coastguard Worker 
1084*795d594fSAndroid Build Coastguard Worker   // Create a new block between this block and its predecessors. The new block
1085*795d594fSAndroid Build Coastguard Worker   // is added to the graph, all predecessor edges are relinked to it and an edge
1086*795d594fSAndroid Build Coastguard Worker   // is created to `this`. Returns the new empty block. Reverse post order or
1087*795d594fSAndroid Build Coastguard Worker   // loop and try/catch information are not updated.
1088*795d594fSAndroid Build Coastguard Worker   HBasicBlock* CreateImmediateDominator();
1089*795d594fSAndroid Build Coastguard Worker 
1090*795d594fSAndroid Build Coastguard Worker   // Split the block into two blocks just before `cursor`. Returns the newly
1091*795d594fSAndroid Build Coastguard Worker   // created, latter block. Note that this method will add the block to the
1092*795d594fSAndroid Build Coastguard Worker   // graph, create a Goto at the end of the former block and will create an edge
1093*795d594fSAndroid Build Coastguard Worker   // between the blocks. It will not, however, update the reverse post order or
1094*795d594fSAndroid Build Coastguard Worker   // loop and try/catch information.
1095*795d594fSAndroid Build Coastguard Worker   HBasicBlock* SplitBefore(HInstruction* cursor, bool require_graph_not_in_ssa_form = true);
1096*795d594fSAndroid Build Coastguard Worker 
1097*795d594fSAndroid Build Coastguard Worker   // Split the block into two blocks just before `cursor`. Returns the newly
1098*795d594fSAndroid Build Coastguard Worker   // created block. Note that this method just updates raw block information,
1099*795d594fSAndroid Build Coastguard Worker   // like predecessors, successors, dominators, and instruction list. It does not
1100*795d594fSAndroid Build Coastguard Worker   // update the graph, reverse post order, loop information, nor make sure the
1101*795d594fSAndroid Build Coastguard Worker   // blocks are consistent (for example ending with a control flow instruction).
1102*795d594fSAndroid Build Coastguard Worker   HBasicBlock* SplitBeforeForInlining(HInstruction* cursor);
1103*795d594fSAndroid Build Coastguard Worker 
1104*795d594fSAndroid Build Coastguard Worker   // Similar to `SplitBeforeForInlining` but does it after `cursor`.
1105*795d594fSAndroid Build Coastguard Worker   HBasicBlock* SplitAfterForInlining(HInstruction* cursor);
1106*795d594fSAndroid Build Coastguard Worker 
1107*795d594fSAndroid Build Coastguard Worker   // Merge `other` at the end of `this`. Successors and dominated blocks of
1108*795d594fSAndroid Build Coastguard Worker   // `other` are changed to be successors and dominated blocks of `this`. Note
1109*795d594fSAndroid Build Coastguard Worker   // that this method does not update the graph, reverse post order, loop
1110*795d594fSAndroid Build Coastguard Worker   // information, nor make sure the blocks are consistent (for example ending
1111*795d594fSAndroid Build Coastguard Worker   // with a control flow instruction).
1112*795d594fSAndroid Build Coastguard Worker   void MergeWithInlined(HBasicBlock* other);
1113*795d594fSAndroid Build Coastguard Worker 
1114*795d594fSAndroid Build Coastguard Worker   // Replace `this` with `other`. Predecessors, successors, and dominated blocks
1115*795d594fSAndroid Build Coastguard Worker   // of `this` are moved to `other`.
1116*795d594fSAndroid Build Coastguard Worker   // Note that this method does not update the graph, reverse post order, loop
1117*795d594fSAndroid Build Coastguard Worker   // information, nor make sure the blocks are consistent (for example ending
1118*795d594fSAndroid Build Coastguard Worker   // with a control flow instruction).
1119*795d594fSAndroid Build Coastguard Worker   void ReplaceWith(HBasicBlock* other);
1120*795d594fSAndroid Build Coastguard Worker 
1121*795d594fSAndroid Build Coastguard Worker   // Merges the instructions of `other` at the end of `this`.
1122*795d594fSAndroid Build Coastguard Worker   void MergeInstructionsWith(HBasicBlock* other);
1123*795d594fSAndroid Build Coastguard Worker 
1124*795d594fSAndroid Build Coastguard Worker   // Merge `other` at the end of `this`. This method updates loops, reverse post
1125*795d594fSAndroid Build Coastguard Worker   // order, links to predecessors, successors, dominators and deletes the block
1126*795d594fSAndroid Build Coastguard Worker   // from the graph. The two blocks must be successive, i.e. `this` the only
1127*795d594fSAndroid Build Coastguard Worker   // predecessor of `other` and vice versa.
1128*795d594fSAndroid Build Coastguard Worker   void MergeWith(HBasicBlock* other);
1129*795d594fSAndroid Build Coastguard Worker 
1130*795d594fSAndroid Build Coastguard Worker   // Disconnects `this` from all its predecessors, successors and dominator,
1131*795d594fSAndroid Build Coastguard Worker   // removes it from all loops it is included in and eventually from the graph.
1132*795d594fSAndroid Build Coastguard Worker   // The block must not dominate any other block. Predecessors and successors
1133*795d594fSAndroid Build Coastguard Worker   // are safely updated.
1134*795d594fSAndroid Build Coastguard Worker   void DisconnectAndDelete();
1135*795d594fSAndroid Build Coastguard Worker 
1136*795d594fSAndroid Build Coastguard Worker   // Disconnects `this` from all its successors and updates their phis, if the successors have them.
1137*795d594fSAndroid Build Coastguard Worker   // If `visited` is provided, it will use the information to know if a successor is reachable and
1138*795d594fSAndroid Build Coastguard Worker   // skip updating those phis.
1139*795d594fSAndroid Build Coastguard Worker   void DisconnectFromSuccessors(const ArenaBitVector* visited = nullptr);
1140*795d594fSAndroid Build Coastguard Worker 
1141*795d594fSAndroid Build Coastguard Worker   // Removes the catch phi uses of the instructions in `this`, and then remove the instruction
1142*795d594fSAndroid Build Coastguard Worker   // itself. If `building_dominator_tree` is true, it will not remove the instruction as user, since
1143*795d594fSAndroid Build Coastguard Worker   // we do it in a previous step. This is a special case for building up the dominator tree: we want
1144*795d594fSAndroid Build Coastguard Worker   // to eliminate uses before inputs but we don't have domination information, so we remove all
1145*795d594fSAndroid Build Coastguard Worker   // connections from input/uses first before removing any instruction.
1146*795d594fSAndroid Build Coastguard Worker   // This method assumes the instructions have been removed from all users with the exception of
1147*795d594fSAndroid Build Coastguard Worker   // catch phis because of missing exceptional edges in the graph.
1148*795d594fSAndroid Build Coastguard Worker   void RemoveCatchPhiUsesAndInstruction(bool building_dominator_tree);
1149*795d594fSAndroid Build Coastguard Worker 
1150*795d594fSAndroid Build Coastguard Worker   void AddInstruction(HInstruction* instruction);
1151*795d594fSAndroid Build Coastguard Worker   // Insert `instruction` before/after an existing instruction `cursor`.
1152*795d594fSAndroid Build Coastguard Worker   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
1153*795d594fSAndroid Build Coastguard Worker   void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
1154*795d594fSAndroid Build Coastguard Worker   // Replace phi `initial` with `replacement` within this block.
1155*795d594fSAndroid Build Coastguard Worker   void ReplaceAndRemovePhiWith(HPhi* initial, HPhi* replacement);
1156*795d594fSAndroid Build Coastguard Worker   // Replace instruction `initial` with `replacement` within this block.
1157*795d594fSAndroid Build Coastguard Worker   void ReplaceAndRemoveInstructionWith(HInstruction* initial,
1158*795d594fSAndroid Build Coastguard Worker                                        HInstruction* replacement);
1159*795d594fSAndroid Build Coastguard Worker   void AddPhi(HPhi* phi);
1160*795d594fSAndroid Build Coastguard Worker   void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
1161*795d594fSAndroid Build Coastguard Worker   // RemoveInstruction and RemovePhi delete a given instruction from the respective
1162*795d594fSAndroid Build Coastguard Worker   // instruction list. With 'ensure_safety' set to true, it verifies that the
1163*795d594fSAndroid Build Coastguard Worker   // instruction is not in use and removes it from the use lists of its inputs.
1164*795d594fSAndroid Build Coastguard Worker   void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
1165*795d594fSAndroid Build Coastguard Worker   void RemovePhi(HPhi* phi, bool ensure_safety = true);
1166*795d594fSAndroid Build Coastguard Worker   void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
1167*795d594fSAndroid Build Coastguard Worker 
IsLoopHeader()1168*795d594fSAndroid Build Coastguard Worker   bool IsLoopHeader() const {
1169*795d594fSAndroid Build Coastguard Worker     return IsInLoop() && (loop_information_->GetHeader() == this);
1170*795d594fSAndroid Build Coastguard Worker   }
1171*795d594fSAndroid Build Coastguard Worker 
IsLoopPreHeaderFirstPredecessor()1172*795d594fSAndroid Build Coastguard Worker   bool IsLoopPreHeaderFirstPredecessor() const {
1173*795d594fSAndroid Build Coastguard Worker     DCHECK(IsLoopHeader());
1174*795d594fSAndroid Build Coastguard Worker     return GetPredecessors()[0] == GetLoopInformation()->GetPreHeader();
1175*795d594fSAndroid Build Coastguard Worker   }
1176*795d594fSAndroid Build Coastguard Worker 
IsFirstPredecessorBackEdge()1177*795d594fSAndroid Build Coastguard Worker   bool IsFirstPredecessorBackEdge() const {
1178*795d594fSAndroid Build Coastguard Worker     DCHECK(IsLoopHeader());
1179*795d594fSAndroid Build Coastguard Worker     return GetLoopInformation()->IsBackEdge(*GetPredecessors()[0]);
1180*795d594fSAndroid Build Coastguard Worker   }
1181*795d594fSAndroid Build Coastguard Worker 
GetLoopInformation()1182*795d594fSAndroid Build Coastguard Worker   HLoopInformation* GetLoopInformation() const {
1183*795d594fSAndroid Build Coastguard Worker     return loop_information_;
1184*795d594fSAndroid Build Coastguard Worker   }
1185*795d594fSAndroid Build Coastguard Worker 
1186*795d594fSAndroid Build Coastguard Worker   // Set the loop_information_ on this block. Overrides the current
1187*795d594fSAndroid Build Coastguard Worker   // loop_information if it is an outer loop of the passed loop information.
1188*795d594fSAndroid Build Coastguard Worker   // Note that this method is called while creating the loop information.
SetInLoop(HLoopInformation * info)1189*795d594fSAndroid Build Coastguard Worker   void SetInLoop(HLoopInformation* info) {
1190*795d594fSAndroid Build Coastguard Worker     if (IsLoopHeader()) {
1191*795d594fSAndroid Build Coastguard Worker       // Nothing to do. This just means `info` is an outer loop.
1192*795d594fSAndroid Build Coastguard Worker     } else if (!IsInLoop()) {
1193*795d594fSAndroid Build Coastguard Worker       loop_information_ = info;
1194*795d594fSAndroid Build Coastguard Worker     } else if (loop_information_->Contains(*info->GetHeader())) {
1195*795d594fSAndroid Build Coastguard Worker       // Block is currently part of an outer loop. Make it part of this inner loop.
1196*795d594fSAndroid Build Coastguard Worker       // Note that a non loop header having a loop information means this loop information
1197*795d594fSAndroid Build Coastguard Worker       // has already been populated
1198*795d594fSAndroid Build Coastguard Worker       loop_information_ = info;
1199*795d594fSAndroid Build Coastguard Worker     } else {
1200*795d594fSAndroid Build Coastguard Worker       // Block is part of an inner loop. Do not update the loop information.
1201*795d594fSAndroid Build Coastguard Worker       // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
1202*795d594fSAndroid Build Coastguard Worker       // at this point, because this method is being called while populating `info`.
1203*795d594fSAndroid Build Coastguard Worker     }
1204*795d594fSAndroid Build Coastguard Worker   }
1205*795d594fSAndroid Build Coastguard Worker 
1206*795d594fSAndroid Build Coastguard Worker   // Raw update of the loop information.
SetLoopInformation(HLoopInformation * info)1207*795d594fSAndroid Build Coastguard Worker   void SetLoopInformation(HLoopInformation* info) {
1208*795d594fSAndroid Build Coastguard Worker     loop_information_ = info;
1209*795d594fSAndroid Build Coastguard Worker   }
1210*795d594fSAndroid Build Coastguard Worker 
IsInLoop()1211*795d594fSAndroid Build Coastguard Worker   bool IsInLoop() const { return loop_information_ != nullptr; }
1212*795d594fSAndroid Build Coastguard Worker 
GetTryCatchInformation()1213*795d594fSAndroid Build Coastguard Worker   TryCatchInformation* GetTryCatchInformation() const { return try_catch_information_; }
1214*795d594fSAndroid Build Coastguard Worker 
SetTryCatchInformation(TryCatchInformation * try_catch_information)1215*795d594fSAndroid Build Coastguard Worker   void SetTryCatchInformation(TryCatchInformation* try_catch_information) {
1216*795d594fSAndroid Build Coastguard Worker     try_catch_information_ = try_catch_information;
1217*795d594fSAndroid Build Coastguard Worker   }
1218*795d594fSAndroid Build Coastguard Worker 
IsTryBlock()1219*795d594fSAndroid Build Coastguard Worker   bool IsTryBlock() const {
1220*795d594fSAndroid Build Coastguard Worker     return try_catch_information_ != nullptr && try_catch_information_->IsTryBlock();
1221*795d594fSAndroid Build Coastguard Worker   }
1222*795d594fSAndroid Build Coastguard Worker 
IsCatchBlock()1223*795d594fSAndroid Build Coastguard Worker   bool IsCatchBlock() const {
1224*795d594fSAndroid Build Coastguard Worker     return try_catch_information_ != nullptr && try_catch_information_->IsCatchBlock();
1225*795d594fSAndroid Build Coastguard Worker   }
1226*795d594fSAndroid Build Coastguard Worker 
1227*795d594fSAndroid Build Coastguard Worker   // Returns the try entry that this block's successors should have. They will
1228*795d594fSAndroid Build Coastguard Worker   // be in the same try, unless the block ends in a try boundary. In that case,
1229*795d594fSAndroid Build Coastguard Worker   // the appropriate try entry will be returned.
1230*795d594fSAndroid Build Coastguard Worker   const HTryBoundary* ComputeTryEntryOfSuccessors() const;
1231*795d594fSAndroid Build Coastguard Worker 
1232*795d594fSAndroid Build Coastguard Worker   bool HasThrowingInstructions() const;
1233*795d594fSAndroid Build Coastguard Worker 
1234*795d594fSAndroid Build Coastguard Worker   // Returns whether this block dominates the blocked passed as parameter.
1235*795d594fSAndroid Build Coastguard Worker   bool Dominates(const HBasicBlock* block) const;
1236*795d594fSAndroid Build Coastguard Worker 
GetLifetimeStart()1237*795d594fSAndroid Build Coastguard Worker   size_t GetLifetimeStart() const { return lifetime_start_; }
GetLifetimeEnd()1238*795d594fSAndroid Build Coastguard Worker   size_t GetLifetimeEnd() const { return lifetime_end_; }
1239*795d594fSAndroid Build Coastguard Worker 
SetLifetimeStart(size_t start)1240*795d594fSAndroid Build Coastguard Worker   void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
SetLifetimeEnd(size_t end)1241*795d594fSAndroid Build Coastguard Worker   void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
1242*795d594fSAndroid Build Coastguard Worker 
1243*795d594fSAndroid Build Coastguard Worker   bool EndsWithControlFlowInstruction() const;
1244*795d594fSAndroid Build Coastguard Worker   bool EndsWithReturn() const;
1245*795d594fSAndroid Build Coastguard Worker   bool EndsWithIf() const;
1246*795d594fSAndroid Build Coastguard Worker   bool EndsWithTryBoundary() const;
1247*795d594fSAndroid Build Coastguard Worker   bool HasSinglePhi() const;
1248*795d594fSAndroid Build Coastguard Worker 
1249*795d594fSAndroid Build Coastguard Worker  private:
1250*795d594fSAndroid Build Coastguard Worker   HGraph* graph_;
1251*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> predecessors_;
1252*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> successors_;
1253*795d594fSAndroid Build Coastguard Worker   HInstructionList instructions_;
1254*795d594fSAndroid Build Coastguard Worker   HInstructionList phis_;
1255*795d594fSAndroid Build Coastguard Worker   HLoopInformation* loop_information_;
1256*795d594fSAndroid Build Coastguard Worker   HBasicBlock* dominator_;
1257*795d594fSAndroid Build Coastguard Worker   ArenaVector<HBasicBlock*> dominated_blocks_;
1258*795d594fSAndroid Build Coastguard Worker   uint32_t block_id_;
1259*795d594fSAndroid Build Coastguard Worker   // The dex program counter of the first instruction of this block.
1260*795d594fSAndroid Build Coastguard Worker   const uint32_t dex_pc_;
1261*795d594fSAndroid Build Coastguard Worker   size_t lifetime_start_;
1262*795d594fSAndroid Build Coastguard Worker   size_t lifetime_end_;
1263*795d594fSAndroid Build Coastguard Worker   TryCatchInformation* try_catch_information_;
1264*795d594fSAndroid Build Coastguard Worker 
1265*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
1266*795d594fSAndroid Build Coastguard Worker   friend class HInstruction;
1267*795d594fSAndroid Build Coastguard Worker   // Allow manual control of the ordering of predecessors/successors
1268*795d594fSAndroid Build Coastguard Worker   friend class OptimizingUnitTestHelper;
1269*795d594fSAndroid Build Coastguard Worker 
1270*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
1271*795d594fSAndroid Build Coastguard Worker };
1272*795d594fSAndroid Build Coastguard Worker 
1273*795d594fSAndroid Build Coastguard Worker // Iterates over the LoopInformation of all loops which contain 'block'
1274*795d594fSAndroid Build Coastguard Worker // from the innermost to the outermost.
1275*795d594fSAndroid Build Coastguard Worker class HLoopInformationOutwardIterator : public ValueObject {
1276*795d594fSAndroid Build Coastguard Worker  public:
HLoopInformationOutwardIterator(const HBasicBlock & block)1277*795d594fSAndroid Build Coastguard Worker   explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
1278*795d594fSAndroid Build Coastguard Worker       : current_(block.GetLoopInformation()) {}
1279*795d594fSAndroid Build Coastguard Worker 
Done()1280*795d594fSAndroid Build Coastguard Worker   bool Done() const { return current_ == nullptr; }
1281*795d594fSAndroid Build Coastguard Worker 
Advance()1282*795d594fSAndroid Build Coastguard Worker   void Advance() {
1283*795d594fSAndroid Build Coastguard Worker     DCHECK(!Done());
1284*795d594fSAndroid Build Coastguard Worker     current_ = current_->GetPreHeader()->GetLoopInformation();
1285*795d594fSAndroid Build Coastguard Worker   }
1286*795d594fSAndroid Build Coastguard Worker 
Current()1287*795d594fSAndroid Build Coastguard Worker   HLoopInformation* Current() const {
1288*795d594fSAndroid Build Coastguard Worker     DCHECK(!Done());
1289*795d594fSAndroid Build Coastguard Worker     return current_;
1290*795d594fSAndroid Build Coastguard Worker   }
1291*795d594fSAndroid Build Coastguard Worker 
1292*795d594fSAndroid Build Coastguard Worker  private:
1293*795d594fSAndroid Build Coastguard Worker   HLoopInformation* current_;
1294*795d594fSAndroid Build Coastguard Worker 
1295*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
1296*795d594fSAndroid Build Coastguard Worker };
1297*795d594fSAndroid Build Coastguard Worker 
1298*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(M)                  \
1299*795d594fSAndroid Build Coastguard Worker   M(Above, Condition)                                                   \
1300*795d594fSAndroid Build Coastguard Worker   M(AboveOrEqual, Condition)                                            \
1301*795d594fSAndroid Build Coastguard Worker   M(Abs, UnaryOperation)                                                \
1302*795d594fSAndroid Build Coastguard Worker   M(Add, BinaryOperation)                                               \
1303*795d594fSAndroid Build Coastguard Worker   M(And, BinaryOperation)                                               \
1304*795d594fSAndroid Build Coastguard Worker   M(ArrayGet, Instruction)                                              \
1305*795d594fSAndroid Build Coastguard Worker   M(ArrayLength, Instruction)                                           \
1306*795d594fSAndroid Build Coastguard Worker   M(ArraySet, Instruction)                                              \
1307*795d594fSAndroid Build Coastguard Worker   M(Below, Condition)                                                   \
1308*795d594fSAndroid Build Coastguard Worker   M(BelowOrEqual, Condition)                                            \
1309*795d594fSAndroid Build Coastguard Worker   M(BitwiseNegatedRight, BinaryOperation)                               \
1310*795d594fSAndroid Build Coastguard Worker   M(BooleanNot, UnaryOperation)                                         \
1311*795d594fSAndroid Build Coastguard Worker   M(BoundsCheck, Instruction)                                           \
1312*795d594fSAndroid Build Coastguard Worker   M(BoundType, Instruction)                                             \
1313*795d594fSAndroid Build Coastguard Worker   M(CheckCast, Instruction)                                             \
1314*795d594fSAndroid Build Coastguard Worker   M(ClassTableGet, Instruction)                                         \
1315*795d594fSAndroid Build Coastguard Worker   M(ClearException, Instruction)                                        \
1316*795d594fSAndroid Build Coastguard Worker   M(ClinitCheck, Instruction)                                           \
1317*795d594fSAndroid Build Coastguard Worker   M(Compare, BinaryOperation)                                           \
1318*795d594fSAndroid Build Coastguard Worker   M(ConstructorFence, Instruction)                                      \
1319*795d594fSAndroid Build Coastguard Worker   M(CurrentMethod, Instruction)                                         \
1320*795d594fSAndroid Build Coastguard Worker   M(ShouldDeoptimizeFlag, Instruction)                                  \
1321*795d594fSAndroid Build Coastguard Worker   M(Deoptimize, Instruction)                                            \
1322*795d594fSAndroid Build Coastguard Worker   M(Div, BinaryOperation)                                               \
1323*795d594fSAndroid Build Coastguard Worker   M(DivZeroCheck, Instruction)                                          \
1324*795d594fSAndroid Build Coastguard Worker   M(DoubleConstant, Constant)                                           \
1325*795d594fSAndroid Build Coastguard Worker   M(Equal, Condition)                                                   \
1326*795d594fSAndroid Build Coastguard Worker   M(Exit, Instruction)                                                  \
1327*795d594fSAndroid Build Coastguard Worker   M(FloatConstant, Constant)                                            \
1328*795d594fSAndroid Build Coastguard Worker   M(Goto, Instruction)                                                  \
1329*795d594fSAndroid Build Coastguard Worker   M(GreaterThan, Condition)                                             \
1330*795d594fSAndroid Build Coastguard Worker   M(GreaterThanOrEqual, Condition)                                      \
1331*795d594fSAndroid Build Coastguard Worker   M(If, Instruction)                                                    \
1332*795d594fSAndroid Build Coastguard Worker   M(InstanceFieldGet, Instruction)                                      \
1333*795d594fSAndroid Build Coastguard Worker   M(InstanceFieldSet, Instruction)                                      \
1334*795d594fSAndroid Build Coastguard Worker   M(InstanceOf, Instruction)                                            \
1335*795d594fSAndroid Build Coastguard Worker   M(IntConstant, Constant)                                              \
1336*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddress, Instruction)                                   \
1337*795d594fSAndroid Build Coastguard Worker   M(InvokeUnresolved, Invoke)                                           \
1338*795d594fSAndroid Build Coastguard Worker   M(InvokeInterface, Invoke)                                            \
1339*795d594fSAndroid Build Coastguard Worker   M(InvokeStaticOrDirect, Invoke)                                       \
1340*795d594fSAndroid Build Coastguard Worker   M(InvokeVirtual, Invoke)                                              \
1341*795d594fSAndroid Build Coastguard Worker   M(InvokePolymorphic, Invoke)                                          \
1342*795d594fSAndroid Build Coastguard Worker   M(InvokeCustom, Invoke)                                               \
1343*795d594fSAndroid Build Coastguard Worker   M(LessThan, Condition)                                                \
1344*795d594fSAndroid Build Coastguard Worker   M(LessThanOrEqual, Condition)                                         \
1345*795d594fSAndroid Build Coastguard Worker   M(LoadClass, Instruction)                                             \
1346*795d594fSAndroid Build Coastguard Worker   M(LoadException, Instruction)                                         \
1347*795d594fSAndroid Build Coastguard Worker   M(LoadMethodHandle, Instruction)                                      \
1348*795d594fSAndroid Build Coastguard Worker   M(LoadMethodType, Instruction)                                        \
1349*795d594fSAndroid Build Coastguard Worker   M(LoadString, Instruction)                                            \
1350*795d594fSAndroid Build Coastguard Worker   M(LongConstant, Constant)                                             \
1351*795d594fSAndroid Build Coastguard Worker   M(Max, Instruction)                                                   \
1352*795d594fSAndroid Build Coastguard Worker   M(MemoryBarrier, Instruction)                                         \
1353*795d594fSAndroid Build Coastguard Worker   M(MethodEntryHook, Instruction)                                       \
1354*795d594fSAndroid Build Coastguard Worker   M(MethodExitHook, Instruction)                                        \
1355*795d594fSAndroid Build Coastguard Worker   M(Min, BinaryOperation)                                               \
1356*795d594fSAndroid Build Coastguard Worker   M(MonitorOperation, Instruction)                                      \
1357*795d594fSAndroid Build Coastguard Worker   M(Mul, BinaryOperation)                                               \
1358*795d594fSAndroid Build Coastguard Worker   M(Neg, UnaryOperation)                                                \
1359*795d594fSAndroid Build Coastguard Worker   M(NewArray, Instruction)                                              \
1360*795d594fSAndroid Build Coastguard Worker   M(NewInstance, Instruction)                                           \
1361*795d594fSAndroid Build Coastguard Worker   M(Nop, Instruction)                                                   \
1362*795d594fSAndroid Build Coastguard Worker   M(Not, UnaryOperation)                                                \
1363*795d594fSAndroid Build Coastguard Worker   M(NotEqual, Condition)                                                \
1364*795d594fSAndroid Build Coastguard Worker   M(NullConstant, Instruction)                                          \
1365*795d594fSAndroid Build Coastguard Worker   M(NullCheck, Instruction)                                             \
1366*795d594fSAndroid Build Coastguard Worker   M(Or, BinaryOperation)                                                \
1367*795d594fSAndroid Build Coastguard Worker   M(PackedSwitch, Instruction)                                          \
1368*795d594fSAndroid Build Coastguard Worker   M(ParallelMove, Instruction)                                          \
1369*795d594fSAndroid Build Coastguard Worker   M(ParameterValue, Instruction)                                        \
1370*795d594fSAndroid Build Coastguard Worker   M(Phi, Instruction)                                                   \
1371*795d594fSAndroid Build Coastguard Worker   M(Rem, BinaryOperation)                                               \
1372*795d594fSAndroid Build Coastguard Worker   M(Return, Instruction)                                                \
1373*795d594fSAndroid Build Coastguard Worker   M(ReturnVoid, Instruction)                                            \
1374*795d594fSAndroid Build Coastguard Worker   M(Rol, BinaryOperation)                                               \
1375*795d594fSAndroid Build Coastguard Worker   M(Ror, BinaryOperation)                                               \
1376*795d594fSAndroid Build Coastguard Worker   M(Shl, BinaryOperation)                                               \
1377*795d594fSAndroid Build Coastguard Worker   M(Shr, BinaryOperation)                                               \
1378*795d594fSAndroid Build Coastguard Worker   M(StaticFieldGet, Instruction)                                        \
1379*795d594fSAndroid Build Coastguard Worker   M(StaticFieldSet, Instruction)                                        \
1380*795d594fSAndroid Build Coastguard Worker   M(StringBuilderAppend, Instruction)                                   \
1381*795d594fSAndroid Build Coastguard Worker   M(UnresolvedInstanceFieldGet, Instruction)                            \
1382*795d594fSAndroid Build Coastguard Worker   M(UnresolvedInstanceFieldSet, Instruction)                            \
1383*795d594fSAndroid Build Coastguard Worker   M(UnresolvedStaticFieldGet, Instruction)                              \
1384*795d594fSAndroid Build Coastguard Worker   M(UnresolvedStaticFieldSet, Instruction)                              \
1385*795d594fSAndroid Build Coastguard Worker   M(Select, Instruction)                                                \
1386*795d594fSAndroid Build Coastguard Worker   M(Sub, BinaryOperation)                                               \
1387*795d594fSAndroid Build Coastguard Worker   M(SuspendCheck, Instruction)                                          \
1388*795d594fSAndroid Build Coastguard Worker   M(Throw, Instruction)                                                 \
1389*795d594fSAndroid Build Coastguard Worker   M(TryBoundary, Instruction)                                           \
1390*795d594fSAndroid Build Coastguard Worker   M(TypeConversion, Instruction)                                        \
1391*795d594fSAndroid Build Coastguard Worker   M(UShr, BinaryOperation)                                              \
1392*795d594fSAndroid Build Coastguard Worker   M(Xor, BinaryOperation)
1393*795d594fSAndroid Build Coastguard Worker 
1394*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(M)                  \
1395*795d594fSAndroid Build Coastguard Worker   M(VecReplicateScalar, VecUnaryOperation)                              \
1396*795d594fSAndroid Build Coastguard Worker   M(VecExtractScalar, VecUnaryOperation)                                \
1397*795d594fSAndroid Build Coastguard Worker   M(VecReduce, VecUnaryOperation)                                       \
1398*795d594fSAndroid Build Coastguard Worker   M(VecCnv, VecUnaryOperation)                                          \
1399*795d594fSAndroid Build Coastguard Worker   M(VecNeg, VecUnaryOperation)                                          \
1400*795d594fSAndroid Build Coastguard Worker   M(VecAbs, VecUnaryOperation)                                          \
1401*795d594fSAndroid Build Coastguard Worker   M(VecNot, VecUnaryOperation)                                          \
1402*795d594fSAndroid Build Coastguard Worker   M(VecAdd, VecBinaryOperation)                                         \
1403*795d594fSAndroid Build Coastguard Worker   M(VecHalvingAdd, VecBinaryOperation)                                  \
1404*795d594fSAndroid Build Coastguard Worker   M(VecSub, VecBinaryOperation)                                         \
1405*795d594fSAndroid Build Coastguard Worker   M(VecMul, VecBinaryOperation)                                         \
1406*795d594fSAndroid Build Coastguard Worker   M(VecDiv, VecBinaryOperation)                                         \
1407*795d594fSAndroid Build Coastguard Worker   M(VecMin, VecBinaryOperation)                                         \
1408*795d594fSAndroid Build Coastguard Worker   M(VecMax, VecBinaryOperation)                                         \
1409*795d594fSAndroid Build Coastguard Worker   M(VecAnd, VecBinaryOperation)                                         \
1410*795d594fSAndroid Build Coastguard Worker   M(VecAndNot, VecBinaryOperation)                                      \
1411*795d594fSAndroid Build Coastguard Worker   M(VecOr, VecBinaryOperation)                                          \
1412*795d594fSAndroid Build Coastguard Worker   M(VecXor, VecBinaryOperation)                                         \
1413*795d594fSAndroid Build Coastguard Worker   M(VecSaturationAdd, VecBinaryOperation)                               \
1414*795d594fSAndroid Build Coastguard Worker   M(VecSaturationSub, VecBinaryOperation)                               \
1415*795d594fSAndroid Build Coastguard Worker   M(VecShl, VecBinaryOperation)                                         \
1416*795d594fSAndroid Build Coastguard Worker   M(VecShr, VecBinaryOperation)                                         \
1417*795d594fSAndroid Build Coastguard Worker   M(VecUShr, VecBinaryOperation)                                        \
1418*795d594fSAndroid Build Coastguard Worker   M(VecSetScalars, VecOperation)                                        \
1419*795d594fSAndroid Build Coastguard Worker   M(VecMultiplyAccumulate, VecOperation)                                \
1420*795d594fSAndroid Build Coastguard Worker   M(VecSADAccumulate, VecOperation)                                     \
1421*795d594fSAndroid Build Coastguard Worker   M(VecDotProd, VecOperation)                                           \
1422*795d594fSAndroid Build Coastguard Worker   M(VecLoad, VecMemoryOperation)                                        \
1423*795d594fSAndroid Build Coastguard Worker   M(VecStore, VecMemoryOperation)                                       \
1424*795d594fSAndroid Build Coastguard Worker   M(VecPredSetAll, VecPredSetOperation)                                 \
1425*795d594fSAndroid Build Coastguard Worker   M(VecPredWhile, VecPredSetOperation)                                  \
1426*795d594fSAndroid Build Coastguard Worker   M(VecPredToBoolean, VecOperation)                                     \
1427*795d594fSAndroid Build Coastguard Worker   M(VecEqual, VecCondition)                                             \
1428*795d594fSAndroid Build Coastguard Worker   M(VecNotEqual, VecCondition)                                          \
1429*795d594fSAndroid Build Coastguard Worker   M(VecLessThan, VecCondition)                                          \
1430*795d594fSAndroid Build Coastguard Worker   M(VecLessThanOrEqual, VecCondition)                                   \
1431*795d594fSAndroid Build Coastguard Worker   M(VecGreaterThan, VecCondition)                                       \
1432*795d594fSAndroid Build Coastguard Worker   M(VecGreaterThanOrEqual, VecCondition)                                \
1433*795d594fSAndroid Build Coastguard Worker   M(VecBelow, VecCondition)                                             \
1434*795d594fSAndroid Build Coastguard Worker   M(VecBelowOrEqual, VecCondition)                                      \
1435*795d594fSAndroid Build Coastguard Worker   M(VecAbove, VecCondition)                                             \
1436*795d594fSAndroid Build Coastguard Worker   M(VecAboveOrEqual, VecCondition)                                      \
1437*795d594fSAndroid Build Coastguard Worker   M(VecPredNot, VecPredSetOperation)
1438*795d594fSAndroid Build Coastguard Worker 
1439*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M)                         \
1440*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SCALAR_COMMON(M)                        \
1441*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_VECTOR_COMMON(M)
1442*795d594fSAndroid Build Coastguard Worker 
1443*795d594fSAndroid Build Coastguard Worker /*
1444*795d594fSAndroid Build Coastguard Worker  * Instructions, shared across several (not all) architectures.
1445*795d594fSAndroid Build Coastguard Worker  */
1446*795d594fSAndroid Build Coastguard Worker #if !defined(ART_ENABLE_CODEGEN_arm) && !defined(ART_ENABLE_CODEGEN_arm64)
1447*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M)
1448*795d594fSAndroid Build Coastguard Worker #else
1449*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M)                         \
1450*795d594fSAndroid Build Coastguard Worker   M(DataProcWithShifterOp, Instruction)                                 \
1451*795d594fSAndroid Build Coastguard Worker   M(MultiplyAccumulate, Instruction)                                    \
1452*795d594fSAndroid Build Coastguard Worker   M(IntermediateAddressIndex, Instruction)
1453*795d594fSAndroid Build Coastguard Worker #endif
1454*795d594fSAndroid Build Coastguard Worker 
1455*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)
1456*795d594fSAndroid Build Coastguard Worker 
1457*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
1458*795d594fSAndroid Build Coastguard Worker 
1459*795d594fSAndroid Build Coastguard Worker #if defined(ART_ENABLE_CODEGEN_riscv64)
1460*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M) M(Riscv64ShiftAdd, Instruction)
1461*795d594fSAndroid Build Coastguard Worker #else
1462*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M)
1463*795d594fSAndroid Build Coastguard Worker #endif
1464*795d594fSAndroid Build Coastguard Worker 
1465*795d594fSAndroid Build Coastguard Worker #ifndef ART_ENABLE_CODEGEN_x86
1466*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
1467*795d594fSAndroid Build Coastguard Worker #else
1468*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)                            \
1469*795d594fSAndroid Build Coastguard Worker   M(X86ComputeBaseMethodAddress, Instruction)                           \
1470*795d594fSAndroid Build Coastguard Worker   M(X86LoadFromConstantTable, Instruction)                              \
1471*795d594fSAndroid Build Coastguard Worker   M(X86FPNeg, Instruction)                                              \
1472*795d594fSAndroid Build Coastguard Worker   M(X86PackedSwitch, Instruction)
1473*795d594fSAndroid Build Coastguard Worker #endif
1474*795d594fSAndroid Build Coastguard Worker 
1475*795d594fSAndroid Build Coastguard Worker #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
1476*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M)                     \
1477*795d594fSAndroid Build Coastguard Worker   M(X86AndNot, Instruction)                                             \
1478*795d594fSAndroid Build Coastguard Worker   M(X86MaskOrResetLeastSetBit, Instruction)
1479*795d594fSAndroid Build Coastguard Worker #else
1480*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M)
1481*795d594fSAndroid Build Coastguard Worker #endif
1482*795d594fSAndroid Build Coastguard Worker 
1483*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
1484*795d594fSAndroid Build Coastguard Worker 
1485*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_CONCRETE_INSTRUCTION(M)                                \
1486*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M)                               \
1487*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_SHARED(M)                               \
1488*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)                                  \
1489*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)                                \
1490*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_RISCV64(M)                              \
1491*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_X86(M)                                  \
1492*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)                               \
1493*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION_X86_COMMON(M)
1494*795d594fSAndroid Build Coastguard Worker 
1495*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_ABSTRACT_INSTRUCTION(M)                                \
1496*795d594fSAndroid Build Coastguard Worker   M(Condition, BinaryOperation)                                         \
1497*795d594fSAndroid Build Coastguard Worker   M(Constant, Instruction)                                              \
1498*795d594fSAndroid Build Coastguard Worker   M(UnaryOperation, Instruction)                                        \
1499*795d594fSAndroid Build Coastguard Worker   M(BinaryOperation, Instruction)                                       \
1500*795d594fSAndroid Build Coastguard Worker   M(Invoke, Instruction)                                                \
1501*795d594fSAndroid Build Coastguard Worker   M(VecOperation, Instruction)                                          \
1502*795d594fSAndroid Build Coastguard Worker   M(VecUnaryOperation, VecOperation)                                    \
1503*795d594fSAndroid Build Coastguard Worker   M(VecBinaryOperation, VecOperation)                                   \
1504*795d594fSAndroid Build Coastguard Worker   M(VecMemoryOperation, VecOperation)                                   \
1505*795d594fSAndroid Build Coastguard Worker   M(VecPredSetOperation, VecOperation)                                  \
1506*795d594fSAndroid Build Coastguard Worker   M(VecCondition, VecPredSetOperation)
1507*795d594fSAndroid Build Coastguard Worker 
1508*795d594fSAndroid Build Coastguard Worker #define FOR_EACH_INSTRUCTION(M)                                         \
1509*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION(M)                                      \
1510*795d594fSAndroid Build Coastguard Worker   FOR_EACH_ABSTRACT_INSTRUCTION(M)
1511*795d594fSAndroid Build Coastguard Worker 
1512*795d594fSAndroid Build Coastguard Worker #define FORWARD_DECLARATION(type, super) class H##type;
FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)1513*795d594fSAndroid Build Coastguard Worker FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
1514*795d594fSAndroid Build Coastguard Worker #undef FORWARD_DECLARATION
1515*795d594fSAndroid Build Coastguard Worker 
1516*795d594fSAndroid Build Coastguard Worker #define DECLARE_INSTRUCTION(type)                                         \
1517*795d594fSAndroid Build Coastguard Worker   private:                                                                \
1518*795d594fSAndroid Build Coastguard Worker   H##type& operator=(const H##type&) = delete;                            \
1519*795d594fSAndroid Build Coastguard Worker   public:                                                                 \
1520*795d594fSAndroid Build Coastguard Worker   const char* DebugName() const override { return #type; }                \
1521*795d594fSAndroid Build Coastguard Worker   HInstruction* Clone(ArenaAllocator* arena) const override {             \
1522*795d594fSAndroid Build Coastguard Worker     DCHECK(IsClonable());                                                 \
1523*795d594fSAndroid Build Coastguard Worker     return new (arena) H##type(*this);                                    \
1524*795d594fSAndroid Build Coastguard Worker   }                                                                       \
1525*795d594fSAndroid Build Coastguard Worker   void Accept(HGraphVisitor* visitor) override
1526*795d594fSAndroid Build Coastguard Worker 
1527*795d594fSAndroid Build Coastguard Worker #define DECLARE_ABSTRACT_INSTRUCTION(type)                              \
1528*795d594fSAndroid Build Coastguard Worker   private:                                                              \
1529*795d594fSAndroid Build Coastguard Worker   H##type& operator=(const H##type&) = delete;                          \
1530*795d594fSAndroid Build Coastguard Worker   public:
1531*795d594fSAndroid Build Coastguard Worker 
1532*795d594fSAndroid Build Coastguard Worker #define DEFAULT_COPY_CONSTRUCTOR(type) H##type(const H##type& other) = default;
1533*795d594fSAndroid Build Coastguard Worker 
1534*795d594fSAndroid Build Coastguard Worker template <typename T>
1535*795d594fSAndroid Build Coastguard Worker class HUseListNode : public ArenaObject<kArenaAllocUseListNode>,
1536*795d594fSAndroid Build Coastguard Worker                      public IntrusiveForwardListNode<HUseListNode<T>> {
1537*795d594fSAndroid Build Coastguard Worker  public:
1538*795d594fSAndroid Build Coastguard Worker   // Get the instruction which has this use as one of the inputs.
1539*795d594fSAndroid Build Coastguard Worker   T GetUser() const { return user_; }
1540*795d594fSAndroid Build Coastguard Worker   // Get the position of the input record that this use corresponds to.
1541*795d594fSAndroid Build Coastguard Worker   size_t GetIndex() const { return index_; }
1542*795d594fSAndroid Build Coastguard Worker   // Set the position of the input record that this use corresponds to.
1543*795d594fSAndroid Build Coastguard Worker   void SetIndex(size_t index) { index_ = index; }
1544*795d594fSAndroid Build Coastguard Worker 
1545*795d594fSAndroid Build Coastguard Worker  private:
1546*795d594fSAndroid Build Coastguard Worker   HUseListNode(T user, size_t index)
1547*795d594fSAndroid Build Coastguard Worker       : user_(user), index_(index) {}
1548*795d594fSAndroid Build Coastguard Worker 
1549*795d594fSAndroid Build Coastguard Worker   T const user_;
1550*795d594fSAndroid Build Coastguard Worker   size_t index_;
1551*795d594fSAndroid Build Coastguard Worker 
1552*795d594fSAndroid Build Coastguard Worker   friend class HInstruction;
1553*795d594fSAndroid Build Coastguard Worker 
1554*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HUseListNode);
1555*795d594fSAndroid Build Coastguard Worker };
1556*795d594fSAndroid Build Coastguard Worker 
1557*795d594fSAndroid Build Coastguard Worker template <typename T>
1558*795d594fSAndroid Build Coastguard Worker using HUseList = IntrusiveForwardList<HUseListNode<T>>;
1559*795d594fSAndroid Build Coastguard Worker 
1560*795d594fSAndroid Build Coastguard Worker // This class is used by HEnvironment and HInstruction classes to record the
1561*795d594fSAndroid Build Coastguard Worker // instructions they use and pointers to the corresponding HUseListNodes kept
1562*795d594fSAndroid Build Coastguard Worker // by the used instructions.
1563*795d594fSAndroid Build Coastguard Worker template <typename T>
1564*795d594fSAndroid Build Coastguard Worker class HUserRecord : public ValueObject {
1565*795d594fSAndroid Build Coastguard Worker  public:
HUserRecord()1566*795d594fSAndroid Build Coastguard Worker   HUserRecord() : instruction_(nullptr), before_use_node_() {}
HUserRecord(HInstruction * instruction)1567*795d594fSAndroid Build Coastguard Worker   explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), before_use_node_() {}
1568*795d594fSAndroid Build Coastguard Worker 
HUserRecord(const HUserRecord<T> & old_record,typename HUseList<T>::iterator before_use_node)1569*795d594fSAndroid Build Coastguard Worker   HUserRecord(const HUserRecord<T>& old_record, typename HUseList<T>::iterator before_use_node)
1570*795d594fSAndroid Build Coastguard Worker       : HUserRecord(old_record.instruction_, before_use_node) {}
HUserRecord(HInstruction * instruction,typename HUseList<T>::iterator before_use_node)1571*795d594fSAndroid Build Coastguard Worker   HUserRecord(HInstruction* instruction, typename HUseList<T>::iterator before_use_node)
1572*795d594fSAndroid Build Coastguard Worker       : instruction_(instruction), before_use_node_(before_use_node) {
1573*795d594fSAndroid Build Coastguard Worker     DCHECK(instruction_ != nullptr);
1574*795d594fSAndroid Build Coastguard Worker   }
1575*795d594fSAndroid Build Coastguard Worker 
GetInstruction()1576*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInstruction() const { return instruction_; }
GetBeforeUseNode()1577*795d594fSAndroid Build Coastguard Worker   typename HUseList<T>::iterator GetBeforeUseNode() const { return before_use_node_; }
GetUseNode()1578*795d594fSAndroid Build Coastguard Worker   typename HUseList<T>::iterator GetUseNode() const { return ++GetBeforeUseNode(); }
1579*795d594fSAndroid Build Coastguard Worker 
1580*795d594fSAndroid Build Coastguard Worker  private:
1581*795d594fSAndroid Build Coastguard Worker   // Instruction used by the user.
1582*795d594fSAndroid Build Coastguard Worker   HInstruction* instruction_;
1583*795d594fSAndroid Build Coastguard Worker 
1584*795d594fSAndroid Build Coastguard Worker   // Iterator before the corresponding entry in the use list kept by 'instruction_'.
1585*795d594fSAndroid Build Coastguard Worker   typename HUseList<T>::iterator before_use_node_;
1586*795d594fSAndroid Build Coastguard Worker };
1587*795d594fSAndroid Build Coastguard Worker 
1588*795d594fSAndroid Build Coastguard Worker // Helper class that extracts the input instruction from HUserRecord<HInstruction*>.
1589*795d594fSAndroid Build Coastguard Worker // This is used for HInstruction::GetInputs() to return a container wrapper providing
1590*795d594fSAndroid Build Coastguard Worker // HInstruction* values even though the underlying container has HUserRecord<>s.
1591*795d594fSAndroid Build Coastguard Worker struct HInputExtractor {
operatorHInputExtractor1592*795d594fSAndroid Build Coastguard Worker   HInstruction* operator()(HUserRecord<HInstruction*>& record) const {
1593*795d594fSAndroid Build Coastguard Worker     return record.GetInstruction();
1594*795d594fSAndroid Build Coastguard Worker   }
operatorHInputExtractor1595*795d594fSAndroid Build Coastguard Worker   const HInstruction* operator()(const HUserRecord<HInstruction*>& record) const {
1596*795d594fSAndroid Build Coastguard Worker     return record.GetInstruction();
1597*795d594fSAndroid Build Coastguard Worker   }
1598*795d594fSAndroid Build Coastguard Worker };
1599*795d594fSAndroid Build Coastguard Worker 
1600*795d594fSAndroid Build Coastguard Worker using HInputsRef = TransformArrayRef<HUserRecord<HInstruction*>, HInputExtractor>;
1601*795d594fSAndroid Build Coastguard Worker using HConstInputsRef = TransformArrayRef<const HUserRecord<HInstruction*>, HInputExtractor>;
1602*795d594fSAndroid Build Coastguard Worker 
1603*795d594fSAndroid Build Coastguard Worker /**
1604*795d594fSAndroid Build Coastguard Worker  * Side-effects representation.
1605*795d594fSAndroid Build Coastguard Worker  *
1606*795d594fSAndroid Build Coastguard Worker  * For write/read dependences on fields/arrays, the dependence analysis uses
1607*795d594fSAndroid Build Coastguard Worker  * type disambiguation (e.g. a float field write cannot modify the value of an
1608*795d594fSAndroid Build Coastguard Worker  * integer field read) and the access type (e.g.  a reference array write cannot
1609*795d594fSAndroid Build Coastguard Worker  * modify the value of a reference field read [although it may modify the
1610*795d594fSAndroid Build Coastguard Worker  * reference fetch prior to reading the field, which is represented by its own
1611*795d594fSAndroid Build Coastguard Worker  * write/read dependence]). The analysis makes conservative points-to
1612*795d594fSAndroid Build Coastguard Worker  * assumptions on reference types (e.g. two same typed arrays are assumed to be
1613*795d594fSAndroid Build Coastguard Worker  * the same, and any reference read depends on any reference read without
1614*795d594fSAndroid Build Coastguard Worker  * further regard of its type).
1615*795d594fSAndroid Build Coastguard Worker  *
1616*795d594fSAndroid Build Coastguard Worker  * kDependsOnGCBit is defined in the following way: instructions with kDependsOnGCBit must not be
1617*795d594fSAndroid Build Coastguard Worker  * alive across the point where garbage collection might happen.
1618*795d594fSAndroid Build Coastguard Worker  *
1619*795d594fSAndroid Build Coastguard Worker  * Note: Instructions with kCanTriggerGCBit do not depend on each other.
1620*795d594fSAndroid Build Coastguard Worker  *
1621*795d594fSAndroid Build Coastguard Worker  * kCanTriggerGCBit must be used for instructions for which GC might happen on the path across
1622*795d594fSAndroid Build Coastguard Worker  * those instructions from the compiler perspective (between this instruction and the next one
1623*795d594fSAndroid Build Coastguard Worker  * in the IR).
1624*795d594fSAndroid Build Coastguard Worker  *
1625*795d594fSAndroid Build Coastguard Worker  * Note: Instructions which can cause GC only on a fatal slow path do not need
1626*795d594fSAndroid Build Coastguard Worker  *       kCanTriggerGCBit as the execution never returns to the instruction next to the exceptional
1627*795d594fSAndroid Build Coastguard Worker  *       one. However the execution may return to compiled code if there is a catch block in the
1628*795d594fSAndroid Build Coastguard Worker  *       current method; for this purpose the TryBoundary exit instruction has kCanTriggerGCBit
1629*795d594fSAndroid Build Coastguard Worker  *       set.
1630*795d594fSAndroid Build Coastguard Worker  *
1631*795d594fSAndroid Build Coastguard Worker  * The internal representation uses 38-bit and is described in the table below.
1632*795d594fSAndroid Build Coastguard Worker  * The first line indicates the side effect, and for field/array accesses the
1633*795d594fSAndroid Build Coastguard Worker  * second line indicates the type of the access (in the order of the
1634*795d594fSAndroid Build Coastguard Worker  * DataType::Type enum).
1635*795d594fSAndroid Build Coastguard Worker  * The two numbered lines below indicate the bit position in the bitfield (read
1636*795d594fSAndroid Build Coastguard Worker  * vertically).
1637*795d594fSAndroid Build Coastguard Worker  *
1638*795d594fSAndroid Build Coastguard Worker  *   |Depends on GC|ARRAY-R  |FIELD-R  |Can trigger GC|ARRAY-W  |FIELD-W  |
1639*795d594fSAndroid Build Coastguard Worker  *   +-------------+---------+---------+--------------+---------+---------+
1640*795d594fSAndroid Build Coastguard Worker  *   |             |DFJISCBZL|DFJISCBZL|              |DFJISCBZL|DFJISCBZL|
1641*795d594fSAndroid Build Coastguard Worker  *   |      3      |333333322|222222221|       1      |111111110|000000000|
1642*795d594fSAndroid Build Coastguard Worker  *   |      7      |654321098|765432109|       8      |765432109|876543210|
1643*795d594fSAndroid Build Coastguard Worker  *
1644*795d594fSAndroid Build Coastguard Worker  * Note that, to ease the implementation, 'changes' bits are least significant
1645*795d594fSAndroid Build Coastguard Worker  * bits, while 'dependency' bits are most significant bits.
1646*795d594fSAndroid Build Coastguard Worker  */
1647*795d594fSAndroid Build Coastguard Worker class SideEffects : public ValueObject {
1648*795d594fSAndroid Build Coastguard Worker  public:
SideEffects()1649*795d594fSAndroid Build Coastguard Worker   SideEffects() : flags_(0) {}
1650*795d594fSAndroid Build Coastguard Worker 
None()1651*795d594fSAndroid Build Coastguard Worker   static SideEffects None() {
1652*795d594fSAndroid Build Coastguard Worker     return SideEffects(0);
1653*795d594fSAndroid Build Coastguard Worker   }
1654*795d594fSAndroid Build Coastguard Worker 
All()1655*795d594fSAndroid Build Coastguard Worker   static SideEffects All() {
1656*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllChangeBits | kAllDependOnBits);
1657*795d594fSAndroid Build Coastguard Worker   }
1658*795d594fSAndroid Build Coastguard Worker 
AllChanges()1659*795d594fSAndroid Build Coastguard Worker   static SideEffects AllChanges() {
1660*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllChangeBits);
1661*795d594fSAndroid Build Coastguard Worker   }
1662*795d594fSAndroid Build Coastguard Worker 
AllDependencies()1663*795d594fSAndroid Build Coastguard Worker   static SideEffects AllDependencies() {
1664*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllDependOnBits);
1665*795d594fSAndroid Build Coastguard Worker   }
1666*795d594fSAndroid Build Coastguard Worker 
AllExceptGCDependency()1667*795d594fSAndroid Build Coastguard Worker   static SideEffects AllExceptGCDependency() {
1668*795d594fSAndroid Build Coastguard Worker     return AllWritesAndReads().Union(SideEffects::CanTriggerGC());
1669*795d594fSAndroid Build Coastguard Worker   }
1670*795d594fSAndroid Build Coastguard Worker 
AllWritesAndReads()1671*795d594fSAndroid Build Coastguard Worker   static SideEffects AllWritesAndReads() {
1672*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllWrites | kAllReads);
1673*795d594fSAndroid Build Coastguard Worker   }
1674*795d594fSAndroid Build Coastguard Worker 
AllWrites()1675*795d594fSAndroid Build Coastguard Worker   static SideEffects AllWrites() {
1676*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllWrites);
1677*795d594fSAndroid Build Coastguard Worker   }
1678*795d594fSAndroid Build Coastguard Worker 
AllReads()1679*795d594fSAndroid Build Coastguard Worker   static SideEffects AllReads() {
1680*795d594fSAndroid Build Coastguard Worker     return SideEffects(kAllReads);
1681*795d594fSAndroid Build Coastguard Worker   }
1682*795d594fSAndroid Build Coastguard Worker 
FieldWriteOfType(DataType::Type type,bool is_volatile)1683*795d594fSAndroid Build Coastguard Worker   static SideEffects FieldWriteOfType(DataType::Type type, bool is_volatile) {
1684*795d594fSAndroid Build Coastguard Worker     return is_volatile
1685*795d594fSAndroid Build Coastguard Worker         ? AllWritesAndReads()
1686*795d594fSAndroid Build Coastguard Worker         : SideEffects(TypeFlag(type, kFieldWriteOffset));
1687*795d594fSAndroid Build Coastguard Worker   }
1688*795d594fSAndroid Build Coastguard Worker 
ArrayWriteOfType(DataType::Type type)1689*795d594fSAndroid Build Coastguard Worker   static SideEffects ArrayWriteOfType(DataType::Type type) {
1690*795d594fSAndroid Build Coastguard Worker     return SideEffects(TypeFlag(type, kArrayWriteOffset));
1691*795d594fSAndroid Build Coastguard Worker   }
1692*795d594fSAndroid Build Coastguard Worker 
FieldReadOfType(DataType::Type type,bool is_volatile)1693*795d594fSAndroid Build Coastguard Worker   static SideEffects FieldReadOfType(DataType::Type type, bool is_volatile) {
1694*795d594fSAndroid Build Coastguard Worker     return is_volatile
1695*795d594fSAndroid Build Coastguard Worker         ? AllWritesAndReads()
1696*795d594fSAndroid Build Coastguard Worker         : SideEffects(TypeFlag(type, kFieldReadOffset));
1697*795d594fSAndroid Build Coastguard Worker   }
1698*795d594fSAndroid Build Coastguard Worker 
ArrayReadOfType(DataType::Type type)1699*795d594fSAndroid Build Coastguard Worker   static SideEffects ArrayReadOfType(DataType::Type type) {
1700*795d594fSAndroid Build Coastguard Worker     return SideEffects(TypeFlag(type, kArrayReadOffset));
1701*795d594fSAndroid Build Coastguard Worker   }
1702*795d594fSAndroid Build Coastguard Worker 
1703*795d594fSAndroid Build Coastguard Worker   // Returns whether GC might happen across this instruction from the compiler perspective so
1704*795d594fSAndroid Build Coastguard Worker   // the next instruction in the IR would see that.
1705*795d594fSAndroid Build Coastguard Worker   //
1706*795d594fSAndroid Build Coastguard Worker   // See the SideEffect class comments.
CanTriggerGC()1707*795d594fSAndroid Build Coastguard Worker   static SideEffects CanTriggerGC() {
1708*795d594fSAndroid Build Coastguard Worker     return SideEffects(1ULL << kCanTriggerGCBit);
1709*795d594fSAndroid Build Coastguard Worker   }
1710*795d594fSAndroid Build Coastguard Worker 
1711*795d594fSAndroid Build Coastguard Worker   // Returns whether the instruction must not be alive across a GC point.
1712*795d594fSAndroid Build Coastguard Worker   //
1713*795d594fSAndroid Build Coastguard Worker   // See the SideEffect class comments.
DependsOnGC()1714*795d594fSAndroid Build Coastguard Worker   static SideEffects DependsOnGC() {
1715*795d594fSAndroid Build Coastguard Worker     return SideEffects(1ULL << kDependsOnGCBit);
1716*795d594fSAndroid Build Coastguard Worker   }
1717*795d594fSAndroid Build Coastguard Worker 
1718*795d594fSAndroid Build Coastguard Worker   // Combines the side-effects of this and the other.
Union(SideEffects other)1719*795d594fSAndroid Build Coastguard Worker   SideEffects Union(SideEffects other) const {
1720*795d594fSAndroid Build Coastguard Worker     return SideEffects(flags_ | other.flags_);
1721*795d594fSAndroid Build Coastguard Worker   }
1722*795d594fSAndroid Build Coastguard Worker 
Exclusion(SideEffects other)1723*795d594fSAndroid Build Coastguard Worker   SideEffects Exclusion(SideEffects other) const {
1724*795d594fSAndroid Build Coastguard Worker     return SideEffects(flags_ & ~other.flags_);
1725*795d594fSAndroid Build Coastguard Worker   }
1726*795d594fSAndroid Build Coastguard Worker 
Add(SideEffects other)1727*795d594fSAndroid Build Coastguard Worker   void Add(SideEffects other) {
1728*795d594fSAndroid Build Coastguard Worker     flags_ |= other.flags_;
1729*795d594fSAndroid Build Coastguard Worker   }
1730*795d594fSAndroid Build Coastguard Worker 
Includes(SideEffects other)1731*795d594fSAndroid Build Coastguard Worker   bool Includes(SideEffects other) const {
1732*795d594fSAndroid Build Coastguard Worker     return (other.flags_ & flags_) == other.flags_;
1733*795d594fSAndroid Build Coastguard Worker   }
1734*795d594fSAndroid Build Coastguard Worker 
HasSideEffects()1735*795d594fSAndroid Build Coastguard Worker   bool HasSideEffects() const {
1736*795d594fSAndroid Build Coastguard Worker     return (flags_ & kAllChangeBits);
1737*795d594fSAndroid Build Coastguard Worker   }
1738*795d594fSAndroid Build Coastguard Worker 
HasDependencies()1739*795d594fSAndroid Build Coastguard Worker   bool HasDependencies() const {
1740*795d594fSAndroid Build Coastguard Worker     return (flags_ & kAllDependOnBits);
1741*795d594fSAndroid Build Coastguard Worker   }
1742*795d594fSAndroid Build Coastguard Worker 
1743*795d594fSAndroid Build Coastguard Worker   // Returns true if there are no side effects or dependencies.
DoesNothing()1744*795d594fSAndroid Build Coastguard Worker   bool DoesNothing() const {
1745*795d594fSAndroid Build Coastguard Worker     return flags_ == 0;
1746*795d594fSAndroid Build Coastguard Worker   }
1747*795d594fSAndroid Build Coastguard Worker 
1748*795d594fSAndroid Build Coastguard Worker   // Returns true if something is written.
DoesAnyWrite()1749*795d594fSAndroid Build Coastguard Worker   bool DoesAnyWrite() const {
1750*795d594fSAndroid Build Coastguard Worker     return (flags_ & kAllWrites);
1751*795d594fSAndroid Build Coastguard Worker   }
1752*795d594fSAndroid Build Coastguard Worker 
1753*795d594fSAndroid Build Coastguard Worker   // Returns true if something is read.
DoesAnyRead()1754*795d594fSAndroid Build Coastguard Worker   bool DoesAnyRead() const {
1755*795d594fSAndroid Build Coastguard Worker     return (flags_ & kAllReads);
1756*795d594fSAndroid Build Coastguard Worker   }
1757*795d594fSAndroid Build Coastguard Worker 
1758*795d594fSAndroid Build Coastguard Worker   // Returns true if potentially everything is written and read
1759*795d594fSAndroid Build Coastguard Worker   // (every type and every kind of access).
DoesAllReadWrite()1760*795d594fSAndroid Build Coastguard Worker   bool DoesAllReadWrite() const {
1761*795d594fSAndroid Build Coastguard Worker     return (flags_ & (kAllWrites | kAllReads)) == (kAllWrites | kAllReads);
1762*795d594fSAndroid Build Coastguard Worker   }
1763*795d594fSAndroid Build Coastguard Worker 
DoesAll()1764*795d594fSAndroid Build Coastguard Worker   bool DoesAll() const {
1765*795d594fSAndroid Build Coastguard Worker     return flags_ == (kAllChangeBits | kAllDependOnBits);
1766*795d594fSAndroid Build Coastguard Worker   }
1767*795d594fSAndroid Build Coastguard Worker 
1768*795d594fSAndroid Build Coastguard Worker   // Returns true if `this` may read something written by `other`.
MayDependOn(SideEffects other)1769*795d594fSAndroid Build Coastguard Worker   bool MayDependOn(SideEffects other) const {
1770*795d594fSAndroid Build Coastguard Worker     const uint64_t depends_on_flags = (flags_ & kAllDependOnBits) >> kChangeBits;
1771*795d594fSAndroid Build Coastguard Worker     return (other.flags_ & depends_on_flags);
1772*795d594fSAndroid Build Coastguard Worker   }
1773*795d594fSAndroid Build Coastguard Worker 
1774*795d594fSAndroid Build Coastguard Worker   // Returns string representation of flags (for debugging only).
1775*795d594fSAndroid Build Coastguard Worker   // Format: |x|DFJISCBZL|DFJISCBZL|y|DFJISCBZL|DFJISCBZL|
ToString()1776*795d594fSAndroid Build Coastguard Worker   std::string ToString() const {
1777*795d594fSAndroid Build Coastguard Worker     std::string flags = "|";
1778*795d594fSAndroid Build Coastguard Worker     for (int s = kLastBit; s >= 0; s--) {
1779*795d594fSAndroid Build Coastguard Worker       bool current_bit_is_set = ((flags_ >> s) & 1) != 0;
1780*795d594fSAndroid Build Coastguard Worker       if ((s == kDependsOnGCBit) || (s == kCanTriggerGCBit)) {
1781*795d594fSAndroid Build Coastguard Worker         // This is a bit for the GC side effect.
1782*795d594fSAndroid Build Coastguard Worker         if (current_bit_is_set) {
1783*795d594fSAndroid Build Coastguard Worker           flags += "GC";
1784*795d594fSAndroid Build Coastguard Worker         }
1785*795d594fSAndroid Build Coastguard Worker         flags += "|";
1786*795d594fSAndroid Build Coastguard Worker       } else {
1787*795d594fSAndroid Build Coastguard Worker         // This is a bit for the array/field analysis.
1788*795d594fSAndroid Build Coastguard Worker         // The underscore character stands for the 'can trigger GC' bit.
1789*795d594fSAndroid Build Coastguard Worker         static const char *kDebug = "LZBCSIJFDLZBCSIJFD_LZBCSIJFDLZBCSIJFD";
1790*795d594fSAndroid Build Coastguard Worker         if (current_bit_is_set) {
1791*795d594fSAndroid Build Coastguard Worker           flags += kDebug[s];
1792*795d594fSAndroid Build Coastguard Worker         }
1793*795d594fSAndroid Build Coastguard Worker         if ((s == kFieldWriteOffset) || (s == kArrayWriteOffset) ||
1794*795d594fSAndroid Build Coastguard Worker             (s == kFieldReadOffset) || (s == kArrayReadOffset)) {
1795*795d594fSAndroid Build Coastguard Worker           flags += "|";
1796*795d594fSAndroid Build Coastguard Worker         }
1797*795d594fSAndroid Build Coastguard Worker       }
1798*795d594fSAndroid Build Coastguard Worker     }
1799*795d594fSAndroid Build Coastguard Worker     return flags;
1800*795d594fSAndroid Build Coastguard Worker   }
1801*795d594fSAndroid Build Coastguard Worker 
Equals(const SideEffects & other)1802*795d594fSAndroid Build Coastguard Worker   bool Equals(const SideEffects& other) const { return flags_ == other.flags_; }
1803*795d594fSAndroid Build Coastguard Worker 
1804*795d594fSAndroid Build Coastguard Worker  private:
1805*795d594fSAndroid Build Coastguard Worker   static constexpr int kFieldArrayAnalysisBits = 9;
1806*795d594fSAndroid Build Coastguard Worker 
1807*795d594fSAndroid Build Coastguard Worker   static constexpr int kFieldWriteOffset = 0;
1808*795d594fSAndroid Build Coastguard Worker   static constexpr int kArrayWriteOffset = kFieldWriteOffset + kFieldArrayAnalysisBits;
1809*795d594fSAndroid Build Coastguard Worker   static constexpr int kLastBitForWrites = kArrayWriteOffset + kFieldArrayAnalysisBits - 1;
1810*795d594fSAndroid Build Coastguard Worker   static constexpr int kCanTriggerGCBit = kLastBitForWrites + 1;
1811*795d594fSAndroid Build Coastguard Worker 
1812*795d594fSAndroid Build Coastguard Worker   static constexpr int kChangeBits = kCanTriggerGCBit + 1;
1813*795d594fSAndroid Build Coastguard Worker 
1814*795d594fSAndroid Build Coastguard Worker   static constexpr int kFieldReadOffset = kCanTriggerGCBit + 1;
1815*795d594fSAndroid Build Coastguard Worker   static constexpr int kArrayReadOffset = kFieldReadOffset + kFieldArrayAnalysisBits;
1816*795d594fSAndroid Build Coastguard Worker   static constexpr int kLastBitForReads = kArrayReadOffset + kFieldArrayAnalysisBits - 1;
1817*795d594fSAndroid Build Coastguard Worker   static constexpr int kDependsOnGCBit = kLastBitForReads + 1;
1818*795d594fSAndroid Build Coastguard Worker 
1819*795d594fSAndroid Build Coastguard Worker   static constexpr int kLastBit = kDependsOnGCBit;
1820*795d594fSAndroid Build Coastguard Worker   static constexpr int kDependOnBits = kLastBit + 1 - kChangeBits;
1821*795d594fSAndroid Build Coastguard Worker 
1822*795d594fSAndroid Build Coastguard Worker   // Aliases.
1823*795d594fSAndroid Build Coastguard Worker 
1824*795d594fSAndroid Build Coastguard Worker   static_assert(kChangeBits == kDependOnBits,
1825*795d594fSAndroid Build Coastguard Worker                 "the 'change' bits should match the 'depend on' bits.");
1826*795d594fSAndroid Build Coastguard Worker 
1827*795d594fSAndroid Build Coastguard Worker   static constexpr uint64_t kAllChangeBits = ((1ULL << kChangeBits) - 1);
1828*795d594fSAndroid Build Coastguard Worker   static constexpr uint64_t kAllDependOnBits = ((1ULL << kDependOnBits) - 1) << kChangeBits;
1829*795d594fSAndroid Build Coastguard Worker   static constexpr uint64_t kAllWrites =
1830*795d594fSAndroid Build Coastguard Worker       ((1ULL << (kLastBitForWrites + 1 - kFieldWriteOffset)) - 1) << kFieldWriteOffset;
1831*795d594fSAndroid Build Coastguard Worker   static constexpr uint64_t kAllReads =
1832*795d594fSAndroid Build Coastguard Worker       ((1ULL << (kLastBitForReads + 1 - kFieldReadOffset)) - 1) << kFieldReadOffset;
1833*795d594fSAndroid Build Coastguard Worker 
1834*795d594fSAndroid Build Coastguard Worker   // Translates type to bit flag. The type must correspond to a Java type.
TypeFlag(DataType::Type type,int offset)1835*795d594fSAndroid Build Coastguard Worker   static uint64_t TypeFlag(DataType::Type type, int offset) {
1836*795d594fSAndroid Build Coastguard Worker     int shift;
1837*795d594fSAndroid Build Coastguard Worker     switch (type) {
1838*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kReference: shift = 0; break;
1839*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kBool:      shift = 1; break;
1840*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt8:      shift = 2; break;
1841*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kUint16:    shift = 3; break;
1842*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt16:     shift = 4; break;
1843*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt32:     shift = 5; break;
1844*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kInt64:     shift = 6; break;
1845*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kFloat32:   shift = 7; break;
1846*795d594fSAndroid Build Coastguard Worker       case DataType::Type::kFloat64:   shift = 8; break;
1847*795d594fSAndroid Build Coastguard Worker       default:
1848*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unexpected data type " << type;
1849*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
1850*795d594fSAndroid Build Coastguard Worker     }
1851*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(kFieldWriteOffset, shift);
1852*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(shift, kArrayWriteOffset);
1853*795d594fSAndroid Build Coastguard Worker     return UINT64_C(1) << (shift + offset);
1854*795d594fSAndroid Build Coastguard Worker   }
1855*795d594fSAndroid Build Coastguard Worker 
1856*795d594fSAndroid Build Coastguard Worker   // Private constructor on direct flags value.
SideEffects(uint64_t flags)1857*795d594fSAndroid Build Coastguard Worker   explicit SideEffects(uint64_t flags) : flags_(flags) {}
1858*795d594fSAndroid Build Coastguard Worker 
1859*795d594fSAndroid Build Coastguard Worker   uint64_t flags_;
1860*795d594fSAndroid Build Coastguard Worker };
1861*795d594fSAndroid Build Coastguard Worker 
1862*795d594fSAndroid Build Coastguard Worker // A HEnvironment object contains the values of virtual registers at a given location.
1863*795d594fSAndroid Build Coastguard Worker class HEnvironment : public ArenaObject<kArenaAllocEnvironment> {
1864*795d594fSAndroid Build Coastguard Worker  public:
Create(ArenaAllocator * allocator,size_t number_of_vregs,ArtMethod * method,uint32_t dex_pc,HInstruction * holder)1865*795d594fSAndroid Build Coastguard Worker   static HEnvironment* Create(ArenaAllocator* allocator,
1866*795d594fSAndroid Build Coastguard Worker                               size_t number_of_vregs,
1867*795d594fSAndroid Build Coastguard Worker                               ArtMethod* method,
1868*795d594fSAndroid Build Coastguard Worker                               uint32_t dex_pc,
1869*795d594fSAndroid Build Coastguard Worker                               HInstruction* holder) {
1870*795d594fSAndroid Build Coastguard Worker     // The storage for vreg records is allocated right after the `HEnvironment` itself.
1871*795d594fSAndroid Build Coastguard Worker     static_assert(IsAligned<alignof(HUserRecord<HEnvironment*>)>(sizeof(HEnvironment)));
1872*795d594fSAndroid Build Coastguard Worker     static_assert(IsAligned<alignof(HUserRecord<HEnvironment*>)>(ArenaAllocator::kAlignment));
1873*795d594fSAndroid Build Coastguard Worker     size_t alloc_size = sizeof(HEnvironment) + number_of_vregs * sizeof(HUserRecord<HEnvironment*>);
1874*795d594fSAndroid Build Coastguard Worker     void* storage = allocator->Alloc(alloc_size, kArenaAllocEnvironment);
1875*795d594fSAndroid Build Coastguard Worker     return new (storage) HEnvironment(number_of_vregs, method, dex_pc, holder);
1876*795d594fSAndroid Build Coastguard Worker   }
1877*795d594fSAndroid Build Coastguard Worker 
Create(ArenaAllocator * allocator,const HEnvironment & to_copy,HInstruction * holder)1878*795d594fSAndroid Build Coastguard Worker   static HEnvironment* Create(ArenaAllocator* allocator,
1879*795d594fSAndroid Build Coastguard Worker                               const HEnvironment& to_copy,
1880*795d594fSAndroid Build Coastguard Worker                               HInstruction* holder) {
1881*795d594fSAndroid Build Coastguard Worker     return Create(allocator, to_copy.Size(), to_copy.GetMethod(), to_copy.GetDexPc(), holder);
1882*795d594fSAndroid Build Coastguard Worker   }
1883*795d594fSAndroid Build Coastguard Worker 
AllocateLocations(ArenaAllocator * allocator)1884*795d594fSAndroid Build Coastguard Worker   void AllocateLocations(ArenaAllocator* allocator) {
1885*795d594fSAndroid Build Coastguard Worker     DCHECK(locations_ == nullptr);
1886*795d594fSAndroid Build Coastguard Worker     if (Size() != 0u) {
1887*795d594fSAndroid Build Coastguard Worker       locations_ = allocator->AllocArray<Location>(Size(), kArenaAllocEnvironmentLocations);
1888*795d594fSAndroid Build Coastguard Worker     }
1889*795d594fSAndroid Build Coastguard Worker   }
1890*795d594fSAndroid Build Coastguard Worker 
SetAndCopyParentChain(ArenaAllocator * allocator,HEnvironment * parent)1891*795d594fSAndroid Build Coastguard Worker   void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
1892*795d594fSAndroid Build Coastguard Worker     if (parent_ != nullptr) {
1893*795d594fSAndroid Build Coastguard Worker       parent_->SetAndCopyParentChain(allocator, parent);
1894*795d594fSAndroid Build Coastguard Worker     } else {
1895*795d594fSAndroid Build Coastguard Worker       parent_ = Create(allocator, *parent, holder_);
1896*795d594fSAndroid Build Coastguard Worker       parent_->CopyFrom(parent);
1897*795d594fSAndroid Build Coastguard Worker       if (parent->GetParent() != nullptr) {
1898*795d594fSAndroid Build Coastguard Worker         parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1899*795d594fSAndroid Build Coastguard Worker       }
1900*795d594fSAndroid Build Coastguard Worker     }
1901*795d594fSAndroid Build Coastguard Worker   }
1902*795d594fSAndroid Build Coastguard Worker 
1903*795d594fSAndroid Build Coastguard Worker   void CopyFrom(ArrayRef<HInstruction* const> locals);
1904*795d594fSAndroid Build Coastguard Worker   void CopyFrom(const HEnvironment* environment);
1905*795d594fSAndroid Build Coastguard Worker 
1906*795d594fSAndroid Build Coastguard Worker   // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1907*795d594fSAndroid Build Coastguard Worker   // input to the loop phi instead. This is for inserting instructions that
1908*795d594fSAndroid Build Coastguard Worker   // require an environment (like HDeoptimization) in the loop pre-header.
1909*795d594fSAndroid Build Coastguard Worker   void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
1910*795d594fSAndroid Build Coastguard Worker 
SetRawEnvAt(size_t index,HInstruction * instruction)1911*795d594fSAndroid Build Coastguard Worker   void SetRawEnvAt(size_t index, HInstruction* instruction) {
1912*795d594fSAndroid Build Coastguard Worker     GetVRegs()[index] = HUserRecord<HEnvironment*>(instruction);
1913*795d594fSAndroid Build Coastguard Worker   }
1914*795d594fSAndroid Build Coastguard Worker 
GetInstructionAt(size_t index)1915*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInstructionAt(size_t index) const {
1916*795d594fSAndroid Build Coastguard Worker     return GetVRegs()[index].GetInstruction();
1917*795d594fSAndroid Build Coastguard Worker   }
1918*795d594fSAndroid Build Coastguard Worker 
1919*795d594fSAndroid Build Coastguard Worker   void RemoveAsUserOfInput(size_t index) const;
1920*795d594fSAndroid Build Coastguard Worker 
1921*795d594fSAndroid Build Coastguard Worker   // Replaces the input at the position 'index' with the replacement; the replacement and old
1922*795d594fSAndroid Build Coastguard Worker   // input instructions' env_uses_ lists are adjusted. The function works similar to
1923*795d594fSAndroid Build Coastguard Worker   // HInstruction::ReplaceInput.
1924*795d594fSAndroid Build Coastguard Worker   void ReplaceInput(HInstruction* replacement, size_t index);
1925*795d594fSAndroid Build Coastguard Worker 
Size()1926*795d594fSAndroid Build Coastguard Worker   size_t Size() const { return number_of_vregs_; }
1927*795d594fSAndroid Build Coastguard Worker 
GetParent()1928*795d594fSAndroid Build Coastguard Worker   HEnvironment* GetParent() const { return parent_; }
1929*795d594fSAndroid Build Coastguard Worker 
SetLocationAt(size_t index,Location location)1930*795d594fSAndroid Build Coastguard Worker   void SetLocationAt(size_t index, Location location) {
1931*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(index, number_of_vregs_);
1932*795d594fSAndroid Build Coastguard Worker     DCHECK(locations_ != nullptr);
1933*795d594fSAndroid Build Coastguard Worker     locations_[index] = location;
1934*795d594fSAndroid Build Coastguard Worker   }
1935*795d594fSAndroid Build Coastguard Worker 
GetLocationAt(size_t index)1936*795d594fSAndroid Build Coastguard Worker   Location GetLocationAt(size_t index) const {
1937*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(index, number_of_vregs_);
1938*795d594fSAndroid Build Coastguard Worker     DCHECK(locations_ != nullptr);
1939*795d594fSAndroid Build Coastguard Worker     return locations_[index];
1940*795d594fSAndroid Build Coastguard Worker   }
1941*795d594fSAndroid Build Coastguard Worker 
GetDexPc()1942*795d594fSAndroid Build Coastguard Worker   uint32_t GetDexPc() const {
1943*795d594fSAndroid Build Coastguard Worker     return dex_pc_;
1944*795d594fSAndroid Build Coastguard Worker   }
1945*795d594fSAndroid Build Coastguard Worker 
GetMethod()1946*795d594fSAndroid Build Coastguard Worker   ArtMethod* GetMethod() const {
1947*795d594fSAndroid Build Coastguard Worker     return method_;
1948*795d594fSAndroid Build Coastguard Worker   }
1949*795d594fSAndroid Build Coastguard Worker 
GetHolder()1950*795d594fSAndroid Build Coastguard Worker   HInstruction* GetHolder() const {
1951*795d594fSAndroid Build Coastguard Worker     return holder_;
1952*795d594fSAndroid Build Coastguard Worker   }
1953*795d594fSAndroid Build Coastguard Worker 
1954*795d594fSAndroid Build Coastguard Worker 
IsFromInlinedInvoke()1955*795d594fSAndroid Build Coastguard Worker   bool IsFromInlinedInvoke() const {
1956*795d594fSAndroid Build Coastguard Worker     return GetParent() != nullptr;
1957*795d594fSAndroid Build Coastguard Worker   }
1958*795d594fSAndroid Build Coastguard Worker 
1959*795d594fSAndroid Build Coastguard Worker   class EnvInputSelector {
1960*795d594fSAndroid Build Coastguard Worker    public:
EnvInputSelector(const HEnvironment * e)1961*795d594fSAndroid Build Coastguard Worker     explicit EnvInputSelector(const HEnvironment* e) : env_(e) {}
operator()1962*795d594fSAndroid Build Coastguard Worker     HInstruction* operator()(size_t s) const {
1963*795d594fSAndroid Build Coastguard Worker       return env_->GetInstructionAt(s);
1964*795d594fSAndroid Build Coastguard Worker     }
1965*795d594fSAndroid Build Coastguard Worker    private:
1966*795d594fSAndroid Build Coastguard Worker     const HEnvironment* env_;
1967*795d594fSAndroid Build Coastguard Worker   };
1968*795d594fSAndroid Build Coastguard Worker 
1969*795d594fSAndroid Build Coastguard Worker   using HConstEnvInputRef = TransformIterator<CountIter, EnvInputSelector>;
GetEnvInputs()1970*795d594fSAndroid Build Coastguard Worker   IterationRange<HConstEnvInputRef> GetEnvInputs() const {
1971*795d594fSAndroid Build Coastguard Worker     IterationRange<CountIter> range(Range(Size()));
1972*795d594fSAndroid Build Coastguard Worker     return MakeIterationRange(MakeTransformIterator(range.begin(), EnvInputSelector(this)),
1973*795d594fSAndroid Build Coastguard Worker                               MakeTransformIterator(range.end(), EnvInputSelector(this)));
1974*795d594fSAndroid Build Coastguard Worker   }
1975*795d594fSAndroid Build Coastguard Worker 
1976*795d594fSAndroid Build Coastguard Worker  private:
HEnvironment(size_t number_of_vregs,ArtMethod * method,uint32_t dex_pc,HInstruction * holder)1977*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE HEnvironment(size_t number_of_vregs,
1978*795d594fSAndroid Build Coastguard Worker                              ArtMethod* method,
1979*795d594fSAndroid Build Coastguard Worker                              uint32_t dex_pc,
1980*795d594fSAndroid Build Coastguard Worker                              HInstruction* holder)
1981*795d594fSAndroid Build Coastguard Worker       : number_of_vregs_(dchecked_integral_cast<uint32_t>(number_of_vregs)),
1982*795d594fSAndroid Build Coastguard Worker         dex_pc_(dex_pc),
1983*795d594fSAndroid Build Coastguard Worker         holder_(holder),
1984*795d594fSAndroid Build Coastguard Worker         parent_(nullptr),
1985*795d594fSAndroid Build Coastguard Worker         method_(method),
1986*795d594fSAndroid Build Coastguard Worker         locations_(nullptr) {
1987*795d594fSAndroid Build Coastguard Worker   }
1988*795d594fSAndroid Build Coastguard Worker 
GetVRegs()1989*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HEnvironment*>> GetVRegs() {
1990*795d594fSAndroid Build Coastguard Worker     auto* vregs = reinterpret_cast<HUserRecord<HEnvironment*>*>(this + 1);
1991*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HEnvironment*>>(vregs, number_of_vregs_);
1992*795d594fSAndroid Build Coastguard Worker   }
1993*795d594fSAndroid Build Coastguard Worker 
GetVRegs()1994*795d594fSAndroid Build Coastguard Worker   ArrayRef<const HUserRecord<HEnvironment*>> GetVRegs() const {
1995*795d594fSAndroid Build Coastguard Worker     auto* vregs = reinterpret_cast<const HUserRecord<HEnvironment*>*>(this + 1);
1996*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const HUserRecord<HEnvironment*>>(vregs, number_of_vregs_);
1997*795d594fSAndroid Build Coastguard Worker   }
1998*795d594fSAndroid Build Coastguard Worker 
1999*795d594fSAndroid Build Coastguard Worker   const uint32_t number_of_vregs_;
2000*795d594fSAndroid Build Coastguard Worker   const uint32_t dex_pc_;
2001*795d594fSAndroid Build Coastguard Worker 
2002*795d594fSAndroid Build Coastguard Worker   // The instruction that holds this environment.
2003*795d594fSAndroid Build Coastguard Worker   HInstruction* const holder_;
2004*795d594fSAndroid Build Coastguard Worker 
2005*795d594fSAndroid Build Coastguard Worker   // The parent environment for inlined code.
2006*795d594fSAndroid Build Coastguard Worker   HEnvironment* parent_;
2007*795d594fSAndroid Build Coastguard Worker 
2008*795d594fSAndroid Build Coastguard Worker   // The environment's method, if resolved.
2009*795d594fSAndroid Build Coastguard Worker   ArtMethod* method_;
2010*795d594fSAndroid Build Coastguard Worker 
2011*795d594fSAndroid Build Coastguard Worker   // Locations assigned by the register allocator.
2012*795d594fSAndroid Build Coastguard Worker   Location* locations_;
2013*795d594fSAndroid Build Coastguard Worker 
2014*795d594fSAndroid Build Coastguard Worker   friend class HInstruction;
2015*795d594fSAndroid Build Coastguard Worker 
2016*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HEnvironment);
2017*795d594fSAndroid Build Coastguard Worker };
2018*795d594fSAndroid Build Coastguard Worker 
2019*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HInstruction& rhs);
2020*795d594fSAndroid Build Coastguard Worker 
2021*795d594fSAndroid Build Coastguard Worker // Iterates over the Environments
2022*795d594fSAndroid Build Coastguard Worker class HEnvironmentIterator : public ValueObject {
2023*795d594fSAndroid Build Coastguard Worker  public:
2024*795d594fSAndroid Build Coastguard Worker   using iterator_category = std::forward_iterator_tag;
2025*795d594fSAndroid Build Coastguard Worker   using value_type = HEnvironment*;
2026*795d594fSAndroid Build Coastguard Worker   using difference_type = ptrdiff_t;
2027*795d594fSAndroid Build Coastguard Worker   using pointer = void;
2028*795d594fSAndroid Build Coastguard Worker   using reference = void;
2029*795d594fSAndroid Build Coastguard Worker 
HEnvironmentIterator(HEnvironment * cur)2030*795d594fSAndroid Build Coastguard Worker   explicit HEnvironmentIterator(HEnvironment* cur) : cur_(cur) {}
2031*795d594fSAndroid Build Coastguard Worker 
2032*795d594fSAndroid Build Coastguard Worker   HEnvironment* operator*() const {
2033*795d594fSAndroid Build Coastguard Worker     return cur_;
2034*795d594fSAndroid Build Coastguard Worker   }
2035*795d594fSAndroid Build Coastguard Worker 
2036*795d594fSAndroid Build Coastguard Worker   HEnvironmentIterator& operator++() {
2037*795d594fSAndroid Build Coastguard Worker     DCHECK(cur_ != nullptr);
2038*795d594fSAndroid Build Coastguard Worker     cur_ = cur_->GetParent();
2039*795d594fSAndroid Build Coastguard Worker     return *this;
2040*795d594fSAndroid Build Coastguard Worker   }
2041*795d594fSAndroid Build Coastguard Worker 
2042*795d594fSAndroid Build Coastguard Worker   HEnvironmentIterator operator++(int) {
2043*795d594fSAndroid Build Coastguard Worker     HEnvironmentIterator prev(*this);
2044*795d594fSAndroid Build Coastguard Worker     ++(*this);
2045*795d594fSAndroid Build Coastguard Worker     return prev;
2046*795d594fSAndroid Build Coastguard Worker   }
2047*795d594fSAndroid Build Coastguard Worker 
2048*795d594fSAndroid Build Coastguard Worker   bool operator==(const HEnvironmentIterator& other) const {
2049*795d594fSAndroid Build Coastguard Worker     return other.cur_ == cur_;
2050*795d594fSAndroid Build Coastguard Worker   }
2051*795d594fSAndroid Build Coastguard Worker 
2052*795d594fSAndroid Build Coastguard Worker   bool operator!=(const HEnvironmentIterator& other) const {
2053*795d594fSAndroid Build Coastguard Worker     return !(*this == other);
2054*795d594fSAndroid Build Coastguard Worker   }
2055*795d594fSAndroid Build Coastguard Worker 
2056*795d594fSAndroid Build Coastguard Worker  private:
2057*795d594fSAndroid Build Coastguard Worker   HEnvironment* cur_;
2058*795d594fSAndroid Build Coastguard Worker };
2059*795d594fSAndroid Build Coastguard Worker 
2060*795d594fSAndroid Build Coastguard Worker class HInstruction : public ArenaObject<kArenaAllocInstruction> {
2061*795d594fSAndroid Build Coastguard Worker  public:
2062*795d594fSAndroid Build Coastguard Worker #define DECLARE_KIND(type, super) k##type,
2063*795d594fSAndroid Build Coastguard Worker   enum InstructionKind {  // private marker to avoid generate-operator-out.py from processing.
2064*795d594fSAndroid Build Coastguard Worker     FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_KIND)
2065*795d594fSAndroid Build Coastguard Worker     kLastInstructionKind
2066*795d594fSAndroid Build Coastguard Worker   };
2067*795d594fSAndroid Build Coastguard Worker #undef DECLARE_KIND
2068*795d594fSAndroid Build Coastguard Worker 
HInstruction(InstructionKind kind,SideEffects side_effects,uint32_t dex_pc)2069*795d594fSAndroid Build Coastguard Worker   HInstruction(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
2070*795d594fSAndroid Build Coastguard Worker       : HInstruction(kind, DataType::Type::kVoid, side_effects, dex_pc) {}
2071*795d594fSAndroid Build Coastguard Worker 
HInstruction(InstructionKind kind,DataType::Type type,SideEffects side_effects,uint32_t dex_pc)2072*795d594fSAndroid Build Coastguard Worker   HInstruction(InstructionKind kind, DataType::Type type, SideEffects side_effects, uint32_t dex_pc)
2073*795d594fSAndroid Build Coastguard Worker       : previous_(nullptr),
2074*795d594fSAndroid Build Coastguard Worker         next_(nullptr),
2075*795d594fSAndroid Build Coastguard Worker         block_(nullptr),
2076*795d594fSAndroid Build Coastguard Worker         dex_pc_(dex_pc),
2077*795d594fSAndroid Build Coastguard Worker         id_(-1),
2078*795d594fSAndroid Build Coastguard Worker         ssa_index_(-1),
2079*795d594fSAndroid Build Coastguard Worker         packed_fields_(0u),
2080*795d594fSAndroid Build Coastguard Worker         environment_(nullptr),
2081*795d594fSAndroid Build Coastguard Worker         locations_(nullptr),
2082*795d594fSAndroid Build Coastguard Worker         live_interval_(nullptr),
2083*795d594fSAndroid Build Coastguard Worker         lifetime_position_(kNoLifetime),
2084*795d594fSAndroid Build Coastguard Worker         side_effects_(side_effects),
2085*795d594fSAndroid Build Coastguard Worker         reference_type_handle_(ReferenceTypeInfo::CreateInvalid().GetTypeHandle()) {
2086*795d594fSAndroid Build Coastguard Worker     SetPackedField<InstructionKindField>(kind);
2087*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(type);
2088*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagReferenceTypeIsExact>(ReferenceTypeInfo::CreateInvalid().IsExact());
2089*795d594fSAndroid Build Coastguard Worker   }
2090*795d594fSAndroid Build Coastguard Worker 
~HInstruction()2091*795d594fSAndroid Build Coastguard Worker   virtual ~HInstruction() {}
2092*795d594fSAndroid Build Coastguard Worker 
2093*795d594fSAndroid Build Coastguard Worker   std::ostream& Dump(std::ostream& os, bool dump_args = false);
2094*795d594fSAndroid Build Coastguard Worker 
2095*795d594fSAndroid Build Coastguard Worker   // Helper for dumping without argument information using operator<<
2096*795d594fSAndroid Build Coastguard Worker   struct NoArgsDump {
2097*795d594fSAndroid Build Coastguard Worker     const HInstruction* ins;
2098*795d594fSAndroid Build Coastguard Worker   };
DumpWithoutArgs()2099*795d594fSAndroid Build Coastguard Worker   NoArgsDump DumpWithoutArgs() const {
2100*795d594fSAndroid Build Coastguard Worker     return NoArgsDump{this};
2101*795d594fSAndroid Build Coastguard Worker   }
2102*795d594fSAndroid Build Coastguard Worker   // Helper for dumping with argument information using operator<<
2103*795d594fSAndroid Build Coastguard Worker   struct ArgsDump {
2104*795d594fSAndroid Build Coastguard Worker     const HInstruction* ins;
2105*795d594fSAndroid Build Coastguard Worker   };
DumpWithArgs()2106*795d594fSAndroid Build Coastguard Worker   ArgsDump DumpWithArgs() const {
2107*795d594fSAndroid Build Coastguard Worker     return ArgsDump{this};
2108*795d594fSAndroid Build Coastguard Worker   }
2109*795d594fSAndroid Build Coastguard Worker 
GetNext()2110*795d594fSAndroid Build Coastguard Worker   HInstruction* GetNext() const { return next_; }
GetPrevious()2111*795d594fSAndroid Build Coastguard Worker   HInstruction* GetPrevious() const { return previous_; }
2112*795d594fSAndroid Build Coastguard Worker 
2113*795d594fSAndroid Build Coastguard Worker   HInstruction* GetNextDisregardingMoves() const;
2114*795d594fSAndroid Build Coastguard Worker   HInstruction* GetPreviousDisregardingMoves() const;
2115*795d594fSAndroid Build Coastguard Worker 
GetBlock()2116*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetBlock() const { return block_; }
GetAllocator()2117*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* GetAllocator() const { return block_->GetGraph()->GetAllocator(); }
SetBlock(HBasicBlock * block)2118*795d594fSAndroid Build Coastguard Worker   void SetBlock(HBasicBlock* block) { block_ = block; }
IsInBlock()2119*795d594fSAndroid Build Coastguard Worker   bool IsInBlock() const { return block_ != nullptr; }
IsInLoop()2120*795d594fSAndroid Build Coastguard Worker   bool IsInLoop() const { return block_->IsInLoop(); }
IsLoopHeaderPhi()2121*795d594fSAndroid Build Coastguard Worker   bool IsLoopHeaderPhi() const { return IsPhi() && block_->IsLoopHeader(); }
IsIrreducibleLoopHeaderPhi()2122*795d594fSAndroid Build Coastguard Worker   bool IsIrreducibleLoopHeaderPhi() const {
2123*795d594fSAndroid Build Coastguard Worker     return IsLoopHeaderPhi() && GetBlock()->GetLoopInformation()->IsIrreducible();
2124*795d594fSAndroid Build Coastguard Worker   }
2125*795d594fSAndroid Build Coastguard Worker 
2126*795d594fSAndroid Build Coastguard Worker   virtual ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() = 0;
2127*795d594fSAndroid Build Coastguard Worker 
GetInputRecords()2128*795d594fSAndroid Build Coastguard Worker   ArrayRef<const HUserRecord<HInstruction*>> GetInputRecords() const {
2129*795d594fSAndroid Build Coastguard Worker     // One virtual method is enough, just const_cast<> and then re-add the const.
2130*795d594fSAndroid Build Coastguard Worker     return ArrayRef<const HUserRecord<HInstruction*>>(
2131*795d594fSAndroid Build Coastguard Worker         const_cast<HInstruction*>(this)->GetInputRecords());
2132*795d594fSAndroid Build Coastguard Worker   }
2133*795d594fSAndroid Build Coastguard Worker 
GetInputs()2134*795d594fSAndroid Build Coastguard Worker   HInputsRef GetInputs() {
2135*795d594fSAndroid Build Coastguard Worker     return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
2136*795d594fSAndroid Build Coastguard Worker   }
2137*795d594fSAndroid Build Coastguard Worker 
GetInputs()2138*795d594fSAndroid Build Coastguard Worker   HConstInputsRef GetInputs() const {
2139*795d594fSAndroid Build Coastguard Worker     return MakeTransformArrayRef(GetInputRecords(), HInputExtractor());
2140*795d594fSAndroid Build Coastguard Worker   }
2141*795d594fSAndroid Build Coastguard Worker 
InputCount()2142*795d594fSAndroid Build Coastguard Worker   size_t InputCount() const { return GetInputRecords().size(); }
InputAt(size_t i)2143*795d594fSAndroid Build Coastguard Worker   HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
2144*795d594fSAndroid Build Coastguard Worker 
HasInput(HInstruction * input)2145*795d594fSAndroid Build Coastguard Worker   bool HasInput(HInstruction* input) const {
2146*795d594fSAndroid Build Coastguard Worker     for (const HInstruction* i : GetInputs()) {
2147*795d594fSAndroid Build Coastguard Worker       if (i == input) {
2148*795d594fSAndroid Build Coastguard Worker         return true;
2149*795d594fSAndroid Build Coastguard Worker       }
2150*795d594fSAndroid Build Coastguard Worker     }
2151*795d594fSAndroid Build Coastguard Worker     return false;
2152*795d594fSAndroid Build Coastguard Worker   }
2153*795d594fSAndroid Build Coastguard Worker 
SetRawInputAt(size_t index,HInstruction * input)2154*795d594fSAndroid Build Coastguard Worker   void SetRawInputAt(size_t index, HInstruction* input) {
2155*795d594fSAndroid Build Coastguard Worker     SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
2156*795d594fSAndroid Build Coastguard Worker   }
2157*795d594fSAndroid Build Coastguard Worker 
2158*795d594fSAndroid Build Coastguard Worker   virtual void Accept(HGraphVisitor* visitor) = 0;
2159*795d594fSAndroid Build Coastguard Worker   virtual const char* DebugName() const = 0;
2160*795d594fSAndroid Build Coastguard Worker 
GetType()2161*795d594fSAndroid Build Coastguard Worker   DataType::Type GetType() const {
2162*795d594fSAndroid Build Coastguard Worker     return TypeField::Decode(GetPackedFields());
2163*795d594fSAndroid Build Coastguard Worker   }
2164*795d594fSAndroid Build Coastguard Worker 
NeedsEnvironment()2165*795d594fSAndroid Build Coastguard Worker   virtual bool NeedsEnvironment() const { return false; }
NeedsBss()2166*795d594fSAndroid Build Coastguard Worker   virtual bool NeedsBss() const {
2167*795d594fSAndroid Build Coastguard Worker     return false;
2168*795d594fSAndroid Build Coastguard Worker   }
2169*795d594fSAndroid Build Coastguard Worker 
GetDexPc()2170*795d594fSAndroid Build Coastguard Worker   uint32_t GetDexPc() const { return dex_pc_; }
2171*795d594fSAndroid Build Coastguard Worker 
IsControlFlow()2172*795d594fSAndroid Build Coastguard Worker   virtual bool IsControlFlow() const { return false; }
2173*795d594fSAndroid Build Coastguard Worker 
2174*795d594fSAndroid Build Coastguard Worker   // Can the instruction throw?
2175*795d594fSAndroid Build Coastguard Worker   // TODO: We should rename to CanVisiblyThrow, as some instructions (like HNewInstance),
2176*795d594fSAndroid Build Coastguard Worker   // could throw OOME, but it is still OK to remove them if they are unused.
CanThrow()2177*795d594fSAndroid Build Coastguard Worker   virtual bool CanThrow() const { return false; }
2178*795d594fSAndroid Build Coastguard Worker 
2179*795d594fSAndroid Build Coastguard Worker   // Does the instruction always throw an exception unconditionally?
AlwaysThrows()2180*795d594fSAndroid Build Coastguard Worker   virtual bool AlwaysThrows() const { return false; }
2181*795d594fSAndroid Build Coastguard Worker   // Will this instruction only cause async exceptions if it causes any at all?
OnlyThrowsAsyncExceptions()2182*795d594fSAndroid Build Coastguard Worker   virtual bool OnlyThrowsAsyncExceptions() const {
2183*795d594fSAndroid Build Coastguard Worker     return false;
2184*795d594fSAndroid Build Coastguard Worker   }
2185*795d594fSAndroid Build Coastguard Worker 
CanThrowIntoCatchBlock()2186*795d594fSAndroid Build Coastguard Worker   bool CanThrowIntoCatchBlock() const { return CanThrow() && block_->IsTryBlock(); }
2187*795d594fSAndroid Build Coastguard Worker 
HasSideEffects()2188*795d594fSAndroid Build Coastguard Worker   bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
DoesAnyWrite()2189*795d594fSAndroid Build Coastguard Worker   bool DoesAnyWrite() const { return side_effects_.DoesAnyWrite(); }
2190*795d594fSAndroid Build Coastguard Worker 
2191*795d594fSAndroid Build Coastguard Worker   // Does not apply for all instructions, but having this at top level greatly
2192*795d594fSAndroid Build Coastguard Worker   // simplifies the null check elimination.
2193*795d594fSAndroid Build Coastguard Worker   // TODO: Consider merging can_be_null into ReferenceTypeInfo.
CanBeNull()2194*795d594fSAndroid Build Coastguard Worker   virtual bool CanBeNull() const {
2195*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetType(), DataType::Type::kReference) << "CanBeNull only applies to reference types";
2196*795d594fSAndroid Build Coastguard Worker     return true;
2197*795d594fSAndroid Build Coastguard Worker   }
2198*795d594fSAndroid Build Coastguard Worker 
CanDoImplicitNullCheckOn(HInstruction * obj)2199*795d594fSAndroid Build Coastguard Worker   virtual bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const { return false; }
2200*795d594fSAndroid Build Coastguard Worker 
2201*795d594fSAndroid Build Coastguard Worker   // If this instruction will do an implicit null check, return the `HNullCheck` associated
2202*795d594fSAndroid Build Coastguard Worker   // with it. Otherwise return null.
GetImplicitNullCheck()2203*795d594fSAndroid Build Coastguard Worker   HNullCheck* GetImplicitNullCheck() const {
2204*795d594fSAndroid Build Coastguard Worker     // Go over previous non-move instructions that are emitted at use site.
2205*795d594fSAndroid Build Coastguard Worker     HInstruction* prev_not_move = GetPreviousDisregardingMoves();
2206*795d594fSAndroid Build Coastguard Worker     while (prev_not_move != nullptr && prev_not_move->IsEmittedAtUseSite()) {
2207*795d594fSAndroid Build Coastguard Worker       if (prev_not_move->IsNullCheck()) {
2208*795d594fSAndroid Build Coastguard Worker         return prev_not_move->AsNullCheck();
2209*795d594fSAndroid Build Coastguard Worker       }
2210*795d594fSAndroid Build Coastguard Worker       prev_not_move = prev_not_move->GetPreviousDisregardingMoves();
2211*795d594fSAndroid Build Coastguard Worker     }
2212*795d594fSAndroid Build Coastguard Worker     return nullptr;
2213*795d594fSAndroid Build Coastguard Worker   }
2214*795d594fSAndroid Build Coastguard Worker 
IsActualObject()2215*795d594fSAndroid Build Coastguard Worker   virtual bool IsActualObject() const {
2216*795d594fSAndroid Build Coastguard Worker     return GetType() == DataType::Type::kReference;
2217*795d594fSAndroid Build Coastguard Worker   }
2218*795d594fSAndroid Build Coastguard Worker 
2219*795d594fSAndroid Build Coastguard Worker   // Sets the ReferenceTypeInfo. The RTI must be valid.
2220*795d594fSAndroid Build Coastguard Worker   void SetReferenceTypeInfo(ReferenceTypeInfo rti);
2221*795d594fSAndroid Build Coastguard Worker   // Same as above, but we only set it if it's valid. Otherwise, we don't change the current RTI.
2222*795d594fSAndroid Build Coastguard Worker   void SetReferenceTypeInfoIfValid(ReferenceTypeInfo rti);
2223*795d594fSAndroid Build Coastguard Worker 
GetReferenceTypeInfo()2224*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo GetReferenceTypeInfo() const {
2225*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetType(), DataType::Type::kReference);
2226*795d594fSAndroid Build Coastguard Worker     return ReferenceTypeInfo::CreateUnchecked(reference_type_handle_,
2227*795d594fSAndroid Build Coastguard Worker                                               GetPackedFlag<kFlagReferenceTypeIsExact>());
2228*795d594fSAndroid Build Coastguard Worker   }
2229*795d594fSAndroid Build Coastguard Worker 
AddUseAt(HInstruction * user,size_t index)2230*795d594fSAndroid Build Coastguard Worker   void AddUseAt(HInstruction* user, size_t index) {
2231*795d594fSAndroid Build Coastguard Worker     DCHECK(user != nullptr);
2232*795d594fSAndroid Build Coastguard Worker     // Note: fixup_end remains valid across push_front().
2233*795d594fSAndroid Build Coastguard Worker     auto fixup_end = uses_.empty() ? uses_.begin() : ++uses_.begin();
2234*795d594fSAndroid Build Coastguard Worker     ArenaAllocator* allocator = user->GetBlock()->GetGraph()->GetAllocator();
2235*795d594fSAndroid Build Coastguard Worker     HUseListNode<HInstruction*>* new_node =
2236*795d594fSAndroid Build Coastguard Worker         new (allocator) HUseListNode<HInstruction*>(user, index);
2237*795d594fSAndroid Build Coastguard Worker     uses_.push_front(*new_node);
2238*795d594fSAndroid Build Coastguard Worker     FixUpUserRecordsAfterUseInsertion(fixup_end);
2239*795d594fSAndroid Build Coastguard Worker   }
2240*795d594fSAndroid Build Coastguard Worker 
AddEnvUseAt(HEnvironment * user,size_t index)2241*795d594fSAndroid Build Coastguard Worker   void AddEnvUseAt(HEnvironment* user, size_t index) {
2242*795d594fSAndroid Build Coastguard Worker     DCHECK(user != nullptr);
2243*795d594fSAndroid Build Coastguard Worker     // Note: env_fixup_end remains valid across push_front().
2244*795d594fSAndroid Build Coastguard Worker     auto env_fixup_end = env_uses_.empty() ? env_uses_.begin() : ++env_uses_.begin();
2245*795d594fSAndroid Build Coastguard Worker     HUseListNode<HEnvironment*>* new_node =
2246*795d594fSAndroid Build Coastguard Worker         new (GetBlock()->GetGraph()->GetAllocator()) HUseListNode<HEnvironment*>(user, index);
2247*795d594fSAndroid Build Coastguard Worker     env_uses_.push_front(*new_node);
2248*795d594fSAndroid Build Coastguard Worker     FixUpUserRecordsAfterEnvUseInsertion(env_fixup_end);
2249*795d594fSAndroid Build Coastguard Worker   }
2250*795d594fSAndroid Build Coastguard Worker 
RemoveAsUserOfInput(size_t input)2251*795d594fSAndroid Build Coastguard Worker   void RemoveAsUserOfInput(size_t input) {
2252*795d594fSAndroid Build Coastguard Worker     HUserRecord<HInstruction*> input_use = InputRecordAt(input);
2253*795d594fSAndroid Build Coastguard Worker     HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
2254*795d594fSAndroid Build Coastguard Worker     input_use.GetInstruction()->uses_.erase_after(before_use_node);
2255*795d594fSAndroid Build Coastguard Worker     input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
2256*795d594fSAndroid Build Coastguard Worker   }
2257*795d594fSAndroid Build Coastguard Worker 
RemoveAsUserOfAllInputs()2258*795d594fSAndroid Build Coastguard Worker   void RemoveAsUserOfAllInputs() {
2259*795d594fSAndroid Build Coastguard Worker     for (const HUserRecord<HInstruction*>& input_use : GetInputRecords()) {
2260*795d594fSAndroid Build Coastguard Worker       HUseList<HInstruction*>::iterator before_use_node = input_use.GetBeforeUseNode();
2261*795d594fSAndroid Build Coastguard Worker       input_use.GetInstruction()->uses_.erase_after(before_use_node);
2262*795d594fSAndroid Build Coastguard Worker       input_use.GetInstruction()->FixUpUserRecordsAfterUseRemoval(before_use_node);
2263*795d594fSAndroid Build Coastguard Worker     }
2264*795d594fSAndroid Build Coastguard Worker   }
2265*795d594fSAndroid Build Coastguard Worker 
GetUses()2266*795d594fSAndroid Build Coastguard Worker   const HUseList<HInstruction*>& GetUses() const { return uses_; }
GetEnvUses()2267*795d594fSAndroid Build Coastguard Worker   const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
2268*795d594fSAndroid Build Coastguard Worker 
HasUses()2269*795d594fSAndroid Build Coastguard Worker   bool HasUses() const { return !uses_.empty() || !env_uses_.empty(); }
HasEnvironmentUses()2270*795d594fSAndroid Build Coastguard Worker   bool HasEnvironmentUses() const { return !env_uses_.empty(); }
HasNonEnvironmentUses()2271*795d594fSAndroid Build Coastguard Worker   bool HasNonEnvironmentUses() const { return !uses_.empty(); }
HasOnlyOneNonEnvironmentUse()2272*795d594fSAndroid Build Coastguard Worker   bool HasOnlyOneNonEnvironmentUse() const {
2273*795d594fSAndroid Build Coastguard Worker     return !HasEnvironmentUses() && GetUses().HasExactlyOneElement();
2274*795d594fSAndroid Build Coastguard Worker   }
2275*795d594fSAndroid Build Coastguard Worker 
IsRemovable()2276*795d594fSAndroid Build Coastguard Worker   bool IsRemovable() const {
2277*795d594fSAndroid Build Coastguard Worker     return
2278*795d594fSAndroid Build Coastguard Worker         !DoesAnyWrite() &&
2279*795d594fSAndroid Build Coastguard Worker         // TODO(solanes): Merge calls from IsSuspendCheck to IsControlFlow into one that doesn't
2280*795d594fSAndroid Build Coastguard Worker         // do virtual dispatching.
2281*795d594fSAndroid Build Coastguard Worker         !IsSuspendCheck() &&
2282*795d594fSAndroid Build Coastguard Worker         !IsNop() &&
2283*795d594fSAndroid Build Coastguard Worker         !IsParameterValue() &&
2284*795d594fSAndroid Build Coastguard Worker         // If we added an explicit barrier then we should keep it.
2285*795d594fSAndroid Build Coastguard Worker         !IsMemoryBarrier() &&
2286*795d594fSAndroid Build Coastguard Worker         !IsConstructorFence() &&
2287*795d594fSAndroid Build Coastguard Worker         !IsControlFlow() &&
2288*795d594fSAndroid Build Coastguard Worker         !CanThrow();
2289*795d594fSAndroid Build Coastguard Worker   }
2290*795d594fSAndroid Build Coastguard Worker 
IsDeadAndRemovable()2291*795d594fSAndroid Build Coastguard Worker   bool IsDeadAndRemovable() const {
2292*795d594fSAndroid Build Coastguard Worker     return !HasUses() && IsRemovable();
2293*795d594fSAndroid Build Coastguard Worker   }
2294*795d594fSAndroid Build Coastguard Worker 
IsPhiDeadAndRemovable()2295*795d594fSAndroid Build Coastguard Worker   bool IsPhiDeadAndRemovable() const {
2296*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPhi());
2297*795d594fSAndroid Build Coastguard Worker     DCHECK(IsRemovable()) << " phis are always removable";
2298*795d594fSAndroid Build Coastguard Worker     return !HasUses();
2299*795d594fSAndroid Build Coastguard Worker   }
2300*795d594fSAndroid Build Coastguard Worker 
2301*795d594fSAndroid Build Coastguard Worker   // Does this instruction dominate `other_instruction`?
2302*795d594fSAndroid Build Coastguard Worker   // Aborts if this instruction and `other_instruction` are different phis.
2303*795d594fSAndroid Build Coastguard Worker   bool Dominates(HInstruction* other_instruction) const;
2304*795d594fSAndroid Build Coastguard Worker 
2305*795d594fSAndroid Build Coastguard Worker   // Same but with `strictly dominates` i.e. returns false if this instruction and
2306*795d594fSAndroid Build Coastguard Worker   // `other_instruction` are the same.
2307*795d594fSAndroid Build Coastguard Worker   bool StrictlyDominates(HInstruction* other_instruction) const;
2308*795d594fSAndroid Build Coastguard Worker 
GetId()2309*795d594fSAndroid Build Coastguard Worker   int GetId() const { return id_; }
SetId(int id)2310*795d594fSAndroid Build Coastguard Worker   void SetId(int id) { id_ = id; }
2311*795d594fSAndroid Build Coastguard Worker 
GetSsaIndex()2312*795d594fSAndroid Build Coastguard Worker   int GetSsaIndex() const { return ssa_index_; }
SetSsaIndex(int ssa_index)2313*795d594fSAndroid Build Coastguard Worker   void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
HasSsaIndex()2314*795d594fSAndroid Build Coastguard Worker   bool HasSsaIndex() const { return ssa_index_ != -1; }
2315*795d594fSAndroid Build Coastguard Worker 
HasEnvironment()2316*795d594fSAndroid Build Coastguard Worker   bool HasEnvironment() const { return environment_ != nullptr; }
GetEnvironment()2317*795d594fSAndroid Build Coastguard Worker   HEnvironment* GetEnvironment() const { return environment_; }
GetAllEnvironments()2318*795d594fSAndroid Build Coastguard Worker   IterationRange<HEnvironmentIterator> GetAllEnvironments() const {
2319*795d594fSAndroid Build Coastguard Worker     return MakeIterationRange(HEnvironmentIterator(GetEnvironment()),
2320*795d594fSAndroid Build Coastguard Worker                               HEnvironmentIterator(nullptr));
2321*795d594fSAndroid Build Coastguard Worker   }
2322*795d594fSAndroid Build Coastguard Worker   // Set the `environment_` field. Raw because this method does not
2323*795d594fSAndroid Build Coastguard Worker   // update the uses lists.
SetRawEnvironment(HEnvironment * environment)2324*795d594fSAndroid Build Coastguard Worker   void SetRawEnvironment(HEnvironment* environment) {
2325*795d594fSAndroid Build Coastguard Worker     DCHECK(environment_ == nullptr);
2326*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(environment->GetHolder(), this);
2327*795d594fSAndroid Build Coastguard Worker     environment_ = environment;
2328*795d594fSAndroid Build Coastguard Worker   }
2329*795d594fSAndroid Build Coastguard Worker 
InsertRawEnvironment(HEnvironment * environment)2330*795d594fSAndroid Build Coastguard Worker   void InsertRawEnvironment(HEnvironment* environment) {
2331*795d594fSAndroid Build Coastguard Worker     DCHECK(environment_ != nullptr);
2332*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(environment->GetHolder(), this);
2333*795d594fSAndroid Build Coastguard Worker     DCHECK(environment->GetParent() == nullptr);
2334*795d594fSAndroid Build Coastguard Worker     environment->parent_ = environment_;
2335*795d594fSAndroid Build Coastguard Worker     environment_ = environment;
2336*795d594fSAndroid Build Coastguard Worker   }
2337*795d594fSAndroid Build Coastguard Worker 
2338*795d594fSAndroid Build Coastguard Worker   void RemoveEnvironment();
2339*795d594fSAndroid Build Coastguard Worker 
2340*795d594fSAndroid Build Coastguard Worker   // Set the environment of this instruction, copying it from `environment`. While
2341*795d594fSAndroid Build Coastguard Worker   // copying, the uses lists are being updated.
CopyEnvironmentFrom(HEnvironment * environment)2342*795d594fSAndroid Build Coastguard Worker   void CopyEnvironmentFrom(HEnvironment* environment) {
2343*795d594fSAndroid Build Coastguard Worker     DCHECK(environment_ == nullptr);
2344*795d594fSAndroid Build Coastguard Worker     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetAllocator();
2345*795d594fSAndroid Build Coastguard Worker     environment_ = HEnvironment::Create(allocator, *environment, this);
2346*795d594fSAndroid Build Coastguard Worker     environment_->CopyFrom(environment);
2347*795d594fSAndroid Build Coastguard Worker     if (environment->GetParent() != nullptr) {
2348*795d594fSAndroid Build Coastguard Worker       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
2349*795d594fSAndroid Build Coastguard Worker     }
2350*795d594fSAndroid Build Coastguard Worker   }
2351*795d594fSAndroid Build Coastguard Worker 
CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment * environment,HBasicBlock * block)2352*795d594fSAndroid Build Coastguard Worker   void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
2353*795d594fSAndroid Build Coastguard Worker                                                 HBasicBlock* block) {
2354*795d594fSAndroid Build Coastguard Worker     DCHECK(environment_ == nullptr);
2355*795d594fSAndroid Build Coastguard Worker     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetAllocator();
2356*795d594fSAndroid Build Coastguard Worker     environment_ = HEnvironment::Create(allocator, *environment, this);
2357*795d594fSAndroid Build Coastguard Worker     environment_->CopyFromWithLoopPhiAdjustment(environment, block);
2358*795d594fSAndroid Build Coastguard Worker     if (environment->GetParent() != nullptr) {
2359*795d594fSAndroid Build Coastguard Worker       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
2360*795d594fSAndroid Build Coastguard Worker     }
2361*795d594fSAndroid Build Coastguard Worker   }
2362*795d594fSAndroid Build Coastguard Worker 
2363*795d594fSAndroid Build Coastguard Worker   // Returns the number of entries in the environment. Typically, that is the
2364*795d594fSAndroid Build Coastguard Worker   // number of dex registers in a method. It could be more in case of inlining.
2365*795d594fSAndroid Build Coastguard Worker   size_t EnvironmentSize() const;
2366*795d594fSAndroid Build Coastguard Worker 
GetLocations()2367*795d594fSAndroid Build Coastguard Worker   LocationSummary* GetLocations() const { return locations_; }
SetLocations(LocationSummary * locations)2368*795d594fSAndroid Build Coastguard Worker   void SetLocations(LocationSummary* locations) { locations_ = locations; }
2369*795d594fSAndroid Build Coastguard Worker 
2370*795d594fSAndroid Build Coastguard Worker   void ReplaceWith(HInstruction* instruction);
2371*795d594fSAndroid Build Coastguard Worker   void ReplaceUsesDominatedBy(HInstruction* dominator,
2372*795d594fSAndroid Build Coastguard Worker                               HInstruction* replacement,
2373*795d594fSAndroid Build Coastguard Worker                               bool strictly_dominated = true);
2374*795d594fSAndroid Build Coastguard Worker   void ReplaceEnvUsesDominatedBy(HInstruction* dominator, HInstruction* replacement);
2375*795d594fSAndroid Build Coastguard Worker   void ReplaceInput(HInstruction* replacement, size_t index);
2376*795d594fSAndroid Build Coastguard Worker 
2377*795d594fSAndroid Build Coastguard Worker   // This is almost the same as doing `ReplaceWith()`. But in this helper, the
2378*795d594fSAndroid Build Coastguard Worker   // uses of this instruction by `other` are *not* updated.
ReplaceWithExceptInReplacementAtIndex(HInstruction * other,size_t use_index)2379*795d594fSAndroid Build Coastguard Worker   void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
2380*795d594fSAndroid Build Coastguard Worker     ReplaceWith(other);
2381*795d594fSAndroid Build Coastguard Worker     other->ReplaceInput(this, use_index);
2382*795d594fSAndroid Build Coastguard Worker   }
2383*795d594fSAndroid Build Coastguard Worker 
2384*795d594fSAndroid Build Coastguard Worker   // Move `this` instruction before `cursor`
2385*795d594fSAndroid Build Coastguard Worker   void MoveBefore(HInstruction* cursor, bool do_checks = true);
2386*795d594fSAndroid Build Coastguard Worker 
2387*795d594fSAndroid Build Coastguard Worker   // Move `this` before its first user and out of any loops. If there is no
2388*795d594fSAndroid Build Coastguard Worker   // out-of-loop user that dominates all other users, move the instruction
2389*795d594fSAndroid Build Coastguard Worker   // to the end of the out-of-loop common dominator of the user's blocks.
2390*795d594fSAndroid Build Coastguard Worker   //
2391*795d594fSAndroid Build Coastguard Worker   // This can be used only on non-throwing instructions with no side effects that
2392*795d594fSAndroid Build Coastguard Worker   // have at least one use but no environment uses.
2393*795d594fSAndroid Build Coastguard Worker   void MoveBeforeFirstUserAndOutOfLoops();
2394*795d594fSAndroid Build Coastguard Worker 
2395*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CHECK(type, super)                                    \
2396*795d594fSAndroid Build Coastguard Worker   bool Is##type() const;
2397*795d594fSAndroid Build Coastguard Worker 
2398*795d594fSAndroid Build Coastguard Worker   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
2399*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CHECK
2400*795d594fSAndroid Build Coastguard Worker 
2401*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CAST(type, super)                                     \
2402*795d594fSAndroid Build Coastguard Worker   const H##type* As##type() const;                                             \
2403*795d594fSAndroid Build Coastguard Worker   H##type* As##type();                                                         \
2404*795d594fSAndroid Build Coastguard Worker   const H##type* As##type##OrNull() const;                                     \
2405*795d594fSAndroid Build Coastguard Worker   H##type* As##type##OrNull();
2406*795d594fSAndroid Build Coastguard Worker 
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CAST)2407*795d594fSAndroid Build Coastguard Worker   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CAST)
2408*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CAST
2409*795d594fSAndroid Build Coastguard Worker 
2410*795d594fSAndroid Build Coastguard Worker   // Return a clone of the instruction if it is clonable (shallow copy by default, custom copy
2411*795d594fSAndroid Build Coastguard Worker   // if a custom copy-constructor is provided for a particular type). If IsClonable() is false for
2412*795d594fSAndroid Build Coastguard Worker   // the instruction then the behaviour of this function is undefined.
2413*795d594fSAndroid Build Coastguard Worker   //
2414*795d594fSAndroid Build Coastguard Worker   // Note: It is semantically valid to create a clone of the instruction only until
2415*795d594fSAndroid Build Coastguard Worker   // prepare_for_register_allocator phase as lifetime, intervals and codegen info are not
2416*795d594fSAndroid Build Coastguard Worker   // copied.
2417*795d594fSAndroid Build Coastguard Worker   //
2418*795d594fSAndroid Build Coastguard Worker   // Note: HEnvironment and some other fields are not copied and are set to default values, see
2419*795d594fSAndroid Build Coastguard Worker   // 'explicit HInstruction(const HInstruction& other)' for details.
2420*795d594fSAndroid Build Coastguard Worker   virtual HInstruction* Clone([[maybe_unused]] ArenaAllocator* arena) const {
2421*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Cloning is not implemented for the instruction " <<
2422*795d594fSAndroid Build Coastguard Worker                   DebugName() << " " << GetId();
2423*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
2424*795d594fSAndroid Build Coastguard Worker   }
2425*795d594fSAndroid Build Coastguard Worker 
IsFieldAccess()2426*795d594fSAndroid Build Coastguard Worker   virtual bool IsFieldAccess() const {
2427*795d594fSAndroid Build Coastguard Worker     return false;
2428*795d594fSAndroid Build Coastguard Worker   }
2429*795d594fSAndroid Build Coastguard Worker 
GetFieldInfo()2430*795d594fSAndroid Build Coastguard Worker   virtual const FieldInfo& GetFieldInfo() const {
2431*795d594fSAndroid Build Coastguard Worker     CHECK(IsFieldAccess()) << "Only callable on field accessors not " << DebugName() << " "
2432*795d594fSAndroid Build Coastguard Worker                            << *this;
2433*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "Must be overridden by field accessors. Not implemented by " << *this;
2434*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
2435*795d594fSAndroid Build Coastguard Worker   }
2436*795d594fSAndroid Build Coastguard Worker 
2437*795d594fSAndroid Build Coastguard Worker   // Return whether instruction can be cloned (copied).
IsClonable()2438*795d594fSAndroid Build Coastguard Worker   virtual bool IsClonable() const { return false; }
2439*795d594fSAndroid Build Coastguard Worker 
2440*795d594fSAndroid Build Coastguard Worker   // Returns whether the instruction can be moved within the graph.
2441*795d594fSAndroid Build Coastguard Worker   // TODO: this method is used by LICM and GVN with possibly different
2442*795d594fSAndroid Build Coastguard Worker   //       meanings? split and rename?
CanBeMoved()2443*795d594fSAndroid Build Coastguard Worker   virtual bool CanBeMoved() const { return false; }
2444*795d594fSAndroid Build Coastguard Worker 
2445*795d594fSAndroid Build Coastguard Worker   // Returns whether any data encoded in the two instructions is equal.
2446*795d594fSAndroid Build Coastguard Worker   // This method does not look at the inputs. Both instructions must be
2447*795d594fSAndroid Build Coastguard Worker   // of the same type, otherwise the method has undefined behavior.
InstructionDataEquals(const HInstruction * other)2448*795d594fSAndroid Build Coastguard Worker   virtual bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const {
2449*795d594fSAndroid Build Coastguard Worker     return false;
2450*795d594fSAndroid Build Coastguard Worker   }
2451*795d594fSAndroid Build Coastguard Worker 
2452*795d594fSAndroid Build Coastguard Worker   // Returns whether two instructions are equal, that is:
2453*795d594fSAndroid Build Coastguard Worker   // 1) They have the same type and contain the same data (InstructionDataEquals).
2454*795d594fSAndroid Build Coastguard Worker   // 2) Their inputs are identical.
2455*795d594fSAndroid Build Coastguard Worker   bool Equals(const HInstruction* other) const;
2456*795d594fSAndroid Build Coastguard Worker 
GetKind()2457*795d594fSAndroid Build Coastguard Worker   InstructionKind GetKind() const { return GetPackedField<InstructionKindField>(); }
2458*795d594fSAndroid Build Coastguard Worker 
ComputeHashCode()2459*795d594fSAndroid Build Coastguard Worker   virtual size_t ComputeHashCode() const {
2460*795d594fSAndroid Build Coastguard Worker     size_t result = GetKind();
2461*795d594fSAndroid Build Coastguard Worker     for (const HInstruction* input : GetInputs()) {
2462*795d594fSAndroid Build Coastguard Worker       result = (result * 31) + input->GetId();
2463*795d594fSAndroid Build Coastguard Worker     }
2464*795d594fSAndroid Build Coastguard Worker     return result;
2465*795d594fSAndroid Build Coastguard Worker   }
2466*795d594fSAndroid Build Coastguard Worker 
GetSideEffects()2467*795d594fSAndroid Build Coastguard Worker   SideEffects GetSideEffects() const { return side_effects_; }
SetSideEffects(SideEffects other)2468*795d594fSAndroid Build Coastguard Worker   void SetSideEffects(SideEffects other) { side_effects_ = other; }
AddSideEffects(SideEffects other)2469*795d594fSAndroid Build Coastguard Worker   void AddSideEffects(SideEffects other) { side_effects_.Add(other); }
2470*795d594fSAndroid Build Coastguard Worker 
GetLifetimePosition()2471*795d594fSAndroid Build Coastguard Worker   size_t GetLifetimePosition() const { return lifetime_position_; }
SetLifetimePosition(size_t position)2472*795d594fSAndroid Build Coastguard Worker   void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
GetLiveInterval()2473*795d594fSAndroid Build Coastguard Worker   LiveInterval* GetLiveInterval() const { return live_interval_; }
SetLiveInterval(LiveInterval * interval)2474*795d594fSAndroid Build Coastguard Worker   void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
HasLiveInterval()2475*795d594fSAndroid Build Coastguard Worker   bool HasLiveInterval() const { return live_interval_ != nullptr; }
2476*795d594fSAndroid Build Coastguard Worker 
IsSuspendCheckEntry()2477*795d594fSAndroid Build Coastguard Worker   bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
2478*795d594fSAndroid Build Coastguard Worker 
2479*795d594fSAndroid Build Coastguard Worker   // Returns whether the code generation of the instruction will require to have access
2480*795d594fSAndroid Build Coastguard Worker   // to the current method. Such instructions are:
2481*795d594fSAndroid Build Coastguard Worker   // (1): Instructions that require an environment, as calling the runtime requires
2482*795d594fSAndroid Build Coastguard Worker   //      to walk the stack and have the current method stored at a specific stack address.
2483*795d594fSAndroid Build Coastguard Worker   // (2): HCurrentMethod, potentially used by HInvokeStaticOrDirect, HLoadString, or HLoadClass
2484*795d594fSAndroid Build Coastguard Worker   //      to access the dex cache.
NeedsCurrentMethod()2485*795d594fSAndroid Build Coastguard Worker   bool NeedsCurrentMethod() const {
2486*795d594fSAndroid Build Coastguard Worker     return NeedsEnvironment() || IsCurrentMethod();
2487*795d594fSAndroid Build Coastguard Worker   }
2488*795d594fSAndroid Build Coastguard Worker 
2489*795d594fSAndroid Build Coastguard Worker   // Does this instruction have any use in an environment before
2490*795d594fSAndroid Build Coastguard Worker   // control flow hits 'other'?
2491*795d594fSAndroid Build Coastguard Worker   bool HasAnyEnvironmentUseBefore(HInstruction* other);
2492*795d594fSAndroid Build Coastguard Worker 
2493*795d594fSAndroid Build Coastguard Worker   // Remove all references to environment uses of this instruction.
2494*795d594fSAndroid Build Coastguard Worker   // The caller must ensure that this is safe to do.
2495*795d594fSAndroid Build Coastguard Worker   void RemoveEnvironmentUsers();
2496*795d594fSAndroid Build Coastguard Worker 
IsEmittedAtUseSite()2497*795d594fSAndroid Build Coastguard Worker   bool IsEmittedAtUseSite() const { return GetPackedFlag<kFlagEmittedAtUseSite>(); }
MarkEmittedAtUseSite()2498*795d594fSAndroid Build Coastguard Worker   void MarkEmittedAtUseSite() { SetPackedFlag<kFlagEmittedAtUseSite>(true); }
2499*795d594fSAndroid Build Coastguard Worker 
2500*795d594fSAndroid Build Coastguard Worker  protected:
2501*795d594fSAndroid Build Coastguard Worker   // If set, the machine code for this instruction is assumed to be generated by
2502*795d594fSAndroid Build Coastguard Worker   // its users. Used by liveness analysis to compute use positions accordingly.
2503*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagEmittedAtUseSite = 0u;
2504*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagReferenceTypeIsExact = kFlagEmittedAtUseSite + 1;
2505*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldInstructionKind = kFlagReferenceTypeIsExact + 1;
2506*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldInstructionKindSize =
2507*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(InstructionKind::kLastInstructionKind - 1));
2508*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldType =
2509*795d594fSAndroid Build Coastguard Worker       kFieldInstructionKind + kFieldInstructionKindSize;
2510*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldTypeSize =
2511*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
2512*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfGenericPackedBits = kFieldType + kFieldTypeSize;
2513*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxNumberOfPackedBits = sizeof(uint32_t) * kBitsPerByte;
2514*795d594fSAndroid Build Coastguard Worker 
2515*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfGenericPackedBits <= kMaxNumberOfPackedBits,
2516*795d594fSAndroid Build Coastguard Worker                 "Too many generic packed fields");
2517*795d594fSAndroid Build Coastguard Worker 
2518*795d594fSAndroid Build Coastguard Worker   using TypeField = BitField<DataType::Type, kFieldType, kFieldTypeSize>;
2519*795d594fSAndroid Build Coastguard Worker 
InputRecordAt(size_t i)2520*795d594fSAndroid Build Coastguard Worker   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const {
2521*795d594fSAndroid Build Coastguard Worker     return GetInputRecords()[i];
2522*795d594fSAndroid Build Coastguard Worker   }
2523*795d594fSAndroid Build Coastguard Worker 
SetRawInputRecordAt(size_t index,const HUserRecord<HInstruction * > & input)2524*795d594fSAndroid Build Coastguard Worker   void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) {
2525*795d594fSAndroid Build Coastguard Worker     ArrayRef<HUserRecord<HInstruction*>> input_records = GetInputRecords();
2526*795d594fSAndroid Build Coastguard Worker     input_records[index] = input;
2527*795d594fSAndroid Build Coastguard Worker   }
2528*795d594fSAndroid Build Coastguard Worker 
GetPackedFields()2529*795d594fSAndroid Build Coastguard Worker   uint32_t GetPackedFields() const {
2530*795d594fSAndroid Build Coastguard Worker     return packed_fields_;
2531*795d594fSAndroid Build Coastguard Worker   }
2532*795d594fSAndroid Build Coastguard Worker 
2533*795d594fSAndroid Build Coastguard Worker   template <size_t flag>
GetPackedFlag()2534*795d594fSAndroid Build Coastguard Worker   bool GetPackedFlag() const {
2535*795d594fSAndroid Build Coastguard Worker     return (packed_fields_ & (1u << flag)) != 0u;
2536*795d594fSAndroid Build Coastguard Worker   }
2537*795d594fSAndroid Build Coastguard Worker 
2538*795d594fSAndroid Build Coastguard Worker   template <size_t flag>
2539*795d594fSAndroid Build Coastguard Worker   void SetPackedFlag(bool value = true) {
2540*795d594fSAndroid Build Coastguard Worker     packed_fields_ = (packed_fields_ & ~(1u << flag)) | ((value ? 1u : 0u) << flag);
2541*795d594fSAndroid Build Coastguard Worker   }
2542*795d594fSAndroid Build Coastguard Worker 
2543*795d594fSAndroid Build Coastguard Worker   template <typename BitFieldType>
GetPackedField()2544*795d594fSAndroid Build Coastguard Worker   typename BitFieldType::value_type GetPackedField() const {
2545*795d594fSAndroid Build Coastguard Worker     return BitFieldType::Decode(packed_fields_);
2546*795d594fSAndroid Build Coastguard Worker   }
2547*795d594fSAndroid Build Coastguard Worker 
2548*795d594fSAndroid Build Coastguard Worker   template <typename BitFieldType>
SetPackedField(typename BitFieldType::value_type value)2549*795d594fSAndroid Build Coastguard Worker   void SetPackedField(typename BitFieldType::value_type value) {
2550*795d594fSAndroid Build Coastguard Worker     DCHECK(IsUint<BitFieldType::size>(static_cast<uintptr_t>(value)));
2551*795d594fSAndroid Build Coastguard Worker     packed_fields_ = BitFieldType::Update(value, packed_fields_);
2552*795d594fSAndroid Build Coastguard Worker   }
2553*795d594fSAndroid Build Coastguard Worker 
2554*795d594fSAndroid Build Coastguard Worker   // Copy construction for the instruction (used for Clone function).
2555*795d594fSAndroid Build Coastguard Worker   //
2556*795d594fSAndroid Build Coastguard Worker   // Fields (e.g. lifetime, intervals and codegen info) associated with phases starting from
2557*795d594fSAndroid Build Coastguard Worker   // prepare_for_register_allocator are not copied (set to default values).
2558*795d594fSAndroid Build Coastguard Worker   //
2559*795d594fSAndroid Build Coastguard Worker   // Copy constructors must be provided for every HInstruction type; default copy constructor is
2560*795d594fSAndroid Build Coastguard Worker   // fine for most of them. However for some of the instructions a custom copy constructor must be
2561*795d594fSAndroid Build Coastguard Worker   // specified (when instruction has non-trivially copyable fields and must have a special behaviour
2562*795d594fSAndroid Build Coastguard Worker   // for copying them).
HInstruction(const HInstruction & other)2563*795d594fSAndroid Build Coastguard Worker   explicit HInstruction(const HInstruction& other)
2564*795d594fSAndroid Build Coastguard Worker       : previous_(nullptr),
2565*795d594fSAndroid Build Coastguard Worker         next_(nullptr),
2566*795d594fSAndroid Build Coastguard Worker         block_(nullptr),
2567*795d594fSAndroid Build Coastguard Worker         dex_pc_(other.dex_pc_),
2568*795d594fSAndroid Build Coastguard Worker         id_(-1),
2569*795d594fSAndroid Build Coastguard Worker         ssa_index_(-1),
2570*795d594fSAndroid Build Coastguard Worker         packed_fields_(other.packed_fields_),
2571*795d594fSAndroid Build Coastguard Worker         environment_(nullptr),
2572*795d594fSAndroid Build Coastguard Worker         locations_(nullptr),
2573*795d594fSAndroid Build Coastguard Worker         live_interval_(nullptr),
2574*795d594fSAndroid Build Coastguard Worker         lifetime_position_(kNoLifetime),
2575*795d594fSAndroid Build Coastguard Worker         side_effects_(other.side_effects_),
2576*795d594fSAndroid Build Coastguard Worker         reference_type_handle_(other.reference_type_handle_) {
2577*795d594fSAndroid Build Coastguard Worker   }
2578*795d594fSAndroid Build Coastguard Worker 
2579*795d594fSAndroid Build Coastguard Worker  private:
2580*795d594fSAndroid Build Coastguard Worker   using InstructionKindField =
2581*795d594fSAndroid Build Coastguard Worker       BitField<InstructionKind, kFieldInstructionKind, kFieldInstructionKindSize>;
2582*795d594fSAndroid Build Coastguard Worker 
FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction * >::iterator fixup_end)2583*795d594fSAndroid Build Coastguard Worker   void FixUpUserRecordsAfterUseInsertion(HUseList<HInstruction*>::iterator fixup_end) {
2584*795d594fSAndroid Build Coastguard Worker     auto before_use_node = uses_.before_begin();
2585*795d594fSAndroid Build Coastguard Worker     for (auto use_node = uses_.begin(); use_node != fixup_end; ++use_node) {
2586*795d594fSAndroid Build Coastguard Worker       HInstruction* user = use_node->GetUser();
2587*795d594fSAndroid Build Coastguard Worker       size_t input_index = use_node->GetIndex();
2588*795d594fSAndroid Build Coastguard Worker       user->SetRawInputRecordAt(input_index, HUserRecord<HInstruction*>(this, before_use_node));
2589*795d594fSAndroid Build Coastguard Worker       before_use_node = use_node;
2590*795d594fSAndroid Build Coastguard Worker     }
2591*795d594fSAndroid Build Coastguard Worker   }
2592*795d594fSAndroid Build Coastguard Worker 
FixUpUserRecordsAfterUseRemoval(HUseList<HInstruction * >::iterator before_use_node)2593*795d594fSAndroid Build Coastguard Worker   void FixUpUserRecordsAfterUseRemoval(HUseList<HInstruction*>::iterator before_use_node) {
2594*795d594fSAndroid Build Coastguard Worker     auto next = ++HUseList<HInstruction*>::iterator(before_use_node);
2595*795d594fSAndroid Build Coastguard Worker     if (next != uses_.end()) {
2596*795d594fSAndroid Build Coastguard Worker       HInstruction* next_user = next->GetUser();
2597*795d594fSAndroid Build Coastguard Worker       size_t next_index = next->GetIndex();
2598*795d594fSAndroid Build Coastguard Worker       DCHECK(next_user->InputRecordAt(next_index).GetInstruction() == this);
2599*795d594fSAndroid Build Coastguard Worker       next_user->SetRawInputRecordAt(next_index, HUserRecord<HInstruction*>(this, before_use_node));
2600*795d594fSAndroid Build Coastguard Worker     }
2601*795d594fSAndroid Build Coastguard Worker   }
2602*795d594fSAndroid Build Coastguard Worker 
FixUpUserRecordsAfterEnvUseInsertion(HUseList<HEnvironment * >::iterator env_fixup_end)2603*795d594fSAndroid Build Coastguard Worker   void FixUpUserRecordsAfterEnvUseInsertion(HUseList<HEnvironment*>::iterator env_fixup_end) {
2604*795d594fSAndroid Build Coastguard Worker     auto before_env_use_node = env_uses_.before_begin();
2605*795d594fSAndroid Build Coastguard Worker     for (auto env_use_node = env_uses_.begin(); env_use_node != env_fixup_end; ++env_use_node) {
2606*795d594fSAndroid Build Coastguard Worker       HEnvironment* user = env_use_node->GetUser();
2607*795d594fSAndroid Build Coastguard Worker       size_t input_index = env_use_node->GetIndex();
2608*795d594fSAndroid Build Coastguard Worker       user->GetVRegs()[input_index] = HUserRecord<HEnvironment*>(this, before_env_use_node);
2609*795d594fSAndroid Build Coastguard Worker       before_env_use_node = env_use_node;
2610*795d594fSAndroid Build Coastguard Worker     }
2611*795d594fSAndroid Build Coastguard Worker   }
2612*795d594fSAndroid Build Coastguard Worker 
FixUpUserRecordsAfterEnvUseRemoval(HUseList<HEnvironment * >::iterator before_env_use_node)2613*795d594fSAndroid Build Coastguard Worker   void FixUpUserRecordsAfterEnvUseRemoval(HUseList<HEnvironment*>::iterator before_env_use_node) {
2614*795d594fSAndroid Build Coastguard Worker     auto next = ++HUseList<HEnvironment*>::iterator(before_env_use_node);
2615*795d594fSAndroid Build Coastguard Worker     if (next != env_uses_.end()) {
2616*795d594fSAndroid Build Coastguard Worker       HEnvironment* next_user = next->GetUser();
2617*795d594fSAndroid Build Coastguard Worker       size_t next_index = next->GetIndex();
2618*795d594fSAndroid Build Coastguard Worker       DCHECK(next_user->GetVRegs()[next_index].GetInstruction() == this);
2619*795d594fSAndroid Build Coastguard Worker       next_user->GetVRegs()[next_index] = HUserRecord<HEnvironment*>(this, before_env_use_node);
2620*795d594fSAndroid Build Coastguard Worker     }
2621*795d594fSAndroid Build Coastguard Worker   }
2622*795d594fSAndroid Build Coastguard Worker 
2623*795d594fSAndroid Build Coastguard Worker   HInstruction* previous_;
2624*795d594fSAndroid Build Coastguard Worker   HInstruction* next_;
2625*795d594fSAndroid Build Coastguard Worker   HBasicBlock* block_;
2626*795d594fSAndroid Build Coastguard Worker   const uint32_t dex_pc_;
2627*795d594fSAndroid Build Coastguard Worker 
2628*795d594fSAndroid Build Coastguard Worker   // An instruction gets an id when it is added to the graph.
2629*795d594fSAndroid Build Coastguard Worker   // It reflects creation order. A negative id means the instruction
2630*795d594fSAndroid Build Coastguard Worker   // has not been added to the graph.
2631*795d594fSAndroid Build Coastguard Worker   int id_;
2632*795d594fSAndroid Build Coastguard Worker 
2633*795d594fSAndroid Build Coastguard Worker   // When doing liveness analysis, instructions that have uses get an SSA index.
2634*795d594fSAndroid Build Coastguard Worker   int ssa_index_;
2635*795d594fSAndroid Build Coastguard Worker 
2636*795d594fSAndroid Build Coastguard Worker   // Packed fields.
2637*795d594fSAndroid Build Coastguard Worker   uint32_t packed_fields_;
2638*795d594fSAndroid Build Coastguard Worker 
2639*795d594fSAndroid Build Coastguard Worker   // List of instructions that have this instruction as input.
2640*795d594fSAndroid Build Coastguard Worker   HUseList<HInstruction*> uses_;
2641*795d594fSAndroid Build Coastguard Worker 
2642*795d594fSAndroid Build Coastguard Worker   // List of environments that contain this instruction.
2643*795d594fSAndroid Build Coastguard Worker   HUseList<HEnvironment*> env_uses_;
2644*795d594fSAndroid Build Coastguard Worker 
2645*795d594fSAndroid Build Coastguard Worker   // The environment associated with this instruction. Not null if the instruction
2646*795d594fSAndroid Build Coastguard Worker   // might jump out of the method.
2647*795d594fSAndroid Build Coastguard Worker   HEnvironment* environment_;
2648*795d594fSAndroid Build Coastguard Worker 
2649*795d594fSAndroid Build Coastguard Worker   // Set by the code generator.
2650*795d594fSAndroid Build Coastguard Worker   LocationSummary* locations_;
2651*795d594fSAndroid Build Coastguard Worker 
2652*795d594fSAndroid Build Coastguard Worker   // Set by the liveness analysis.
2653*795d594fSAndroid Build Coastguard Worker   LiveInterval* live_interval_;
2654*795d594fSAndroid Build Coastguard Worker 
2655*795d594fSAndroid Build Coastguard Worker   // Set by the liveness analysis, this is the position in a linear
2656*795d594fSAndroid Build Coastguard Worker   // order of blocks where this instruction's live interval start.
2657*795d594fSAndroid Build Coastguard Worker   size_t lifetime_position_;
2658*795d594fSAndroid Build Coastguard Worker 
2659*795d594fSAndroid Build Coastguard Worker   SideEffects side_effects_;
2660*795d594fSAndroid Build Coastguard Worker 
2661*795d594fSAndroid Build Coastguard Worker   // The reference handle part of the reference type info.
2662*795d594fSAndroid Build Coastguard Worker   // The IsExact() flag is stored in packed fields.
2663*795d594fSAndroid Build Coastguard Worker   // TODO: for primitive types this should be marked as invalid.
2664*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo::TypeHandle reference_type_handle_;
2665*795d594fSAndroid Build Coastguard Worker 
2666*795d594fSAndroid Build Coastguard Worker   friend class GraphChecker;
2667*795d594fSAndroid Build Coastguard Worker   friend class HBasicBlock;
2668*795d594fSAndroid Build Coastguard Worker   friend class HEnvironment;
2669*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
2670*795d594fSAndroid Build Coastguard Worker   friend class HInstructionList;
2671*795d594fSAndroid Build Coastguard Worker };
2672*795d594fSAndroid Build Coastguard Worker 
2673*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, HInstruction::InstructionKind rhs);
2674*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HInstruction::NoArgsDump rhs);
2675*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HInstruction::ArgsDump rhs);
2676*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HUseList<HInstruction*>& lst);
2677*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const HUseList<HEnvironment*>& lst);
2678*795d594fSAndroid Build Coastguard Worker 
2679*795d594fSAndroid Build Coastguard Worker // Forward declarations for friends
2680*795d594fSAndroid Build Coastguard Worker template <typename InnerIter> struct HSTLInstructionIterator;
2681*795d594fSAndroid Build Coastguard Worker 
2682*795d594fSAndroid Build Coastguard Worker // Iterates over the instructions, while preserving the next instruction
2683*795d594fSAndroid Build Coastguard Worker // in case the current instruction gets removed from the list by the user
2684*795d594fSAndroid Build Coastguard Worker // of this iterator.
2685*795d594fSAndroid Build Coastguard Worker class HInstructionIterator : public ValueObject {
2686*795d594fSAndroid Build Coastguard Worker  public:
HInstructionIterator(const HInstructionList & instructions)2687*795d594fSAndroid Build Coastguard Worker   explicit HInstructionIterator(const HInstructionList& instructions)
2688*795d594fSAndroid Build Coastguard Worker       : instruction_(instructions.first_instruction_) {
2689*795d594fSAndroid Build Coastguard Worker     next_ = Done() ? nullptr : instruction_->GetNext();
2690*795d594fSAndroid Build Coastguard Worker   }
2691*795d594fSAndroid Build Coastguard Worker 
Done()2692*795d594fSAndroid Build Coastguard Worker   bool Done() const { return instruction_ == nullptr; }
Current()2693*795d594fSAndroid Build Coastguard Worker   HInstruction* Current() const { return instruction_; }
Advance()2694*795d594fSAndroid Build Coastguard Worker   void Advance() {
2695*795d594fSAndroid Build Coastguard Worker     instruction_ = next_;
2696*795d594fSAndroid Build Coastguard Worker     next_ = Done() ? nullptr : instruction_->GetNext();
2697*795d594fSAndroid Build Coastguard Worker   }
2698*795d594fSAndroid Build Coastguard Worker 
2699*795d594fSAndroid Build Coastguard Worker  private:
HInstructionIterator()2700*795d594fSAndroid Build Coastguard Worker   HInstructionIterator() : instruction_(nullptr), next_(nullptr) {}
2701*795d594fSAndroid Build Coastguard Worker 
2702*795d594fSAndroid Build Coastguard Worker   HInstruction* instruction_;
2703*795d594fSAndroid Build Coastguard Worker   HInstruction* next_;
2704*795d594fSAndroid Build Coastguard Worker 
2705*795d594fSAndroid Build Coastguard Worker   friend struct HSTLInstructionIterator<HInstructionIterator>;
2706*795d594fSAndroid Build Coastguard Worker };
2707*795d594fSAndroid Build Coastguard Worker 
2708*795d594fSAndroid Build Coastguard Worker // Iterates over the instructions without saving the next instruction,
2709*795d594fSAndroid Build Coastguard Worker // therefore handling changes in the graph potentially made by the user
2710*795d594fSAndroid Build Coastguard Worker // of this iterator.
2711*795d594fSAndroid Build Coastguard Worker class HInstructionIteratorHandleChanges : public ValueObject {
2712*795d594fSAndroid Build Coastguard Worker  public:
2713*795d594fSAndroid Build Coastguard Worker   explicit HInstructionIteratorHandleChanges(const HInstructionList& instructions)
2714*795d594fSAndroid Build Coastguard Worker       : instruction_(instructions.first_instruction_) {
2715*795d594fSAndroid Build Coastguard Worker   }
2716*795d594fSAndroid Build Coastguard Worker 
2717*795d594fSAndroid Build Coastguard Worker   bool Done() const { return instruction_ == nullptr; }
2718*795d594fSAndroid Build Coastguard Worker   HInstruction* Current() const { return instruction_; }
2719*795d594fSAndroid Build Coastguard Worker   void Advance() {
2720*795d594fSAndroid Build Coastguard Worker     instruction_ = instruction_->GetNext();
2721*795d594fSAndroid Build Coastguard Worker   }
2722*795d594fSAndroid Build Coastguard Worker 
2723*795d594fSAndroid Build Coastguard Worker  private:
2724*795d594fSAndroid Build Coastguard Worker   HInstructionIteratorHandleChanges() : instruction_(nullptr) {}
2725*795d594fSAndroid Build Coastguard Worker 
2726*795d594fSAndroid Build Coastguard Worker   HInstruction* instruction_;
2727*795d594fSAndroid Build Coastguard Worker 
2728*795d594fSAndroid Build Coastguard Worker   friend struct HSTLInstructionIterator<HInstructionIteratorHandleChanges>;
2729*795d594fSAndroid Build Coastguard Worker };
2730*795d594fSAndroid Build Coastguard Worker 
2731*795d594fSAndroid Build Coastguard Worker 
2732*795d594fSAndroid Build Coastguard Worker class HBackwardInstructionIterator : public ValueObject {
2733*795d594fSAndroid Build Coastguard Worker  public:
2734*795d594fSAndroid Build Coastguard Worker   explicit HBackwardInstructionIterator(const HInstructionList& instructions)
2735*795d594fSAndroid Build Coastguard Worker       : instruction_(instructions.last_instruction_) {
2736*795d594fSAndroid Build Coastguard Worker     next_ = Done() ? nullptr : instruction_->GetPrevious();
2737*795d594fSAndroid Build Coastguard Worker   }
2738*795d594fSAndroid Build Coastguard Worker 
2739*795d594fSAndroid Build Coastguard Worker   explicit HBackwardInstructionIterator(HInstruction* instruction) : instruction_(instruction) {
2740*795d594fSAndroid Build Coastguard Worker     next_ = Done() ? nullptr : instruction_->GetPrevious();
2741*795d594fSAndroid Build Coastguard Worker   }
2742*795d594fSAndroid Build Coastguard Worker 
2743*795d594fSAndroid Build Coastguard Worker   bool Done() const { return instruction_ == nullptr; }
2744*795d594fSAndroid Build Coastguard Worker   HInstruction* Current() const { return instruction_; }
2745*795d594fSAndroid Build Coastguard Worker   void Advance() {
2746*795d594fSAndroid Build Coastguard Worker     instruction_ = next_;
2747*795d594fSAndroid Build Coastguard Worker     next_ = Done() ? nullptr : instruction_->GetPrevious();
2748*795d594fSAndroid Build Coastguard Worker   }
2749*795d594fSAndroid Build Coastguard Worker 
2750*795d594fSAndroid Build Coastguard Worker  private:
2751*795d594fSAndroid Build Coastguard Worker   HBackwardInstructionIterator() : instruction_(nullptr), next_(nullptr) {}
2752*795d594fSAndroid Build Coastguard Worker 
2753*795d594fSAndroid Build Coastguard Worker   HInstruction* instruction_;
2754*795d594fSAndroid Build Coastguard Worker   HInstruction* next_;
2755*795d594fSAndroid Build Coastguard Worker 
2756*795d594fSAndroid Build Coastguard Worker   friend struct HSTLInstructionIterator<HBackwardInstructionIterator>;
2757*795d594fSAndroid Build Coastguard Worker };
2758*795d594fSAndroid Build Coastguard Worker 
2759*795d594fSAndroid Build Coastguard Worker template <typename InnerIter>
2760*795d594fSAndroid Build Coastguard Worker struct HSTLInstructionIterator : public ValueObject {
2761*795d594fSAndroid Build Coastguard Worker  public:
2762*795d594fSAndroid Build Coastguard Worker   using iterator_category = std::forward_iterator_tag;
2763*795d594fSAndroid Build Coastguard Worker   using value_type = HInstruction*;
2764*795d594fSAndroid Build Coastguard Worker   using difference_type = ptrdiff_t;
2765*795d594fSAndroid Build Coastguard Worker   using pointer = void;
2766*795d594fSAndroid Build Coastguard Worker   using reference = void;
2767*795d594fSAndroid Build Coastguard Worker 
2768*795d594fSAndroid Build Coastguard Worker   static_assert(std::is_same_v<InnerIter, HBackwardInstructionIterator> ||
2769*795d594fSAndroid Build Coastguard Worker                     std::is_same_v<InnerIter, HInstructionIterator> ||
2770*795d594fSAndroid Build Coastguard Worker                     std::is_same_v<InnerIter, HInstructionIteratorHandleChanges>,
2771*795d594fSAndroid Build Coastguard Worker                 "Unknown wrapped iterator!");
2772*795d594fSAndroid Build Coastguard Worker 
2773*795d594fSAndroid Build Coastguard Worker   explicit HSTLInstructionIterator(InnerIter inner) : inner_(inner) {}
2774*795d594fSAndroid Build Coastguard Worker   HInstruction* operator*() const {
2775*795d594fSAndroid Build Coastguard Worker     DCHECK(inner_.Current() != nullptr);
2776*795d594fSAndroid Build Coastguard Worker     return inner_.Current();
2777*795d594fSAndroid Build Coastguard Worker   }
2778*795d594fSAndroid Build Coastguard Worker 
2779*795d594fSAndroid Build Coastguard Worker   HSTLInstructionIterator<InnerIter>& operator++() {
2780*795d594fSAndroid Build Coastguard Worker     DCHECK(*this != HSTLInstructionIterator<InnerIter>::EndIter());
2781*795d594fSAndroid Build Coastguard Worker     inner_.Advance();
2782*795d594fSAndroid Build Coastguard Worker     return *this;
2783*795d594fSAndroid Build Coastguard Worker   }
2784*795d594fSAndroid Build Coastguard Worker 
2785*795d594fSAndroid Build Coastguard Worker   HSTLInstructionIterator<InnerIter> operator++(int) {
2786*795d594fSAndroid Build Coastguard Worker     HSTLInstructionIterator<InnerIter> prev(*this);
2787*795d594fSAndroid Build Coastguard Worker     ++(*this);
2788*795d594fSAndroid Build Coastguard Worker     return prev;
2789*795d594fSAndroid Build Coastguard Worker   }
2790*795d594fSAndroid Build Coastguard Worker 
2791*795d594fSAndroid Build Coastguard Worker   bool operator==(const HSTLInstructionIterator<InnerIter>& other) const {
2792*795d594fSAndroid Build Coastguard Worker     return inner_.Current() == other.inner_.Current();
2793*795d594fSAndroid Build Coastguard Worker   }
2794*795d594fSAndroid Build Coastguard Worker 
2795*795d594fSAndroid Build Coastguard Worker   bool operator!=(const HSTLInstructionIterator<InnerIter>& other) const {
2796*795d594fSAndroid Build Coastguard Worker     return !(*this == other);
2797*795d594fSAndroid Build Coastguard Worker   }
2798*795d594fSAndroid Build Coastguard Worker 
2799*795d594fSAndroid Build Coastguard Worker   static HSTLInstructionIterator<InnerIter> EndIter() {
2800*795d594fSAndroid Build Coastguard Worker     return HSTLInstructionIterator<InnerIter>(InnerIter());
2801*795d594fSAndroid Build Coastguard Worker   }
2802*795d594fSAndroid Build Coastguard Worker 
2803*795d594fSAndroid Build Coastguard Worker  private:
2804*795d594fSAndroid Build Coastguard Worker   InnerIter inner_;
2805*795d594fSAndroid Build Coastguard Worker };
2806*795d594fSAndroid Build Coastguard Worker 
2807*795d594fSAndroid Build Coastguard Worker template <typename InnerIter>
2808*795d594fSAndroid Build Coastguard Worker IterationRange<HSTLInstructionIterator<InnerIter>> MakeSTLInstructionIteratorRange(InnerIter iter) {
2809*795d594fSAndroid Build Coastguard Worker   return MakeIterationRange(HSTLInstructionIterator<InnerIter>(iter),
2810*795d594fSAndroid Build Coastguard Worker                             HSTLInstructionIterator<InnerIter>::EndIter());
2811*795d594fSAndroid Build Coastguard Worker }
2812*795d594fSAndroid Build Coastguard Worker 
2813*795d594fSAndroid Build Coastguard Worker class HVariableInputSizeInstruction : public HInstruction {
2814*795d594fSAndroid Build Coastguard Worker  public:
2815*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
2816*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() override {
2817*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
2818*795d594fSAndroid Build Coastguard Worker   }
2819*795d594fSAndroid Build Coastguard Worker 
2820*795d594fSAndroid Build Coastguard Worker   void AddInput(HInstruction* input);
2821*795d594fSAndroid Build Coastguard Worker   void InsertInputAt(size_t index, HInstruction* input);
2822*795d594fSAndroid Build Coastguard Worker   void RemoveInputAt(size_t index);
2823*795d594fSAndroid Build Coastguard Worker 
2824*795d594fSAndroid Build Coastguard Worker   // Removes all the inputs.
2825*795d594fSAndroid Build Coastguard Worker   // Also removes this instructions from each input's use list
2826*795d594fSAndroid Build Coastguard Worker   // (for non-environment uses only).
2827*795d594fSAndroid Build Coastguard Worker   void RemoveAllInputs();
2828*795d594fSAndroid Build Coastguard Worker 
2829*795d594fSAndroid Build Coastguard Worker  protected:
2830*795d594fSAndroid Build Coastguard Worker   HVariableInputSizeInstruction(InstructionKind inst_kind,
2831*795d594fSAndroid Build Coastguard Worker                                 SideEffects side_effects,
2832*795d594fSAndroid Build Coastguard Worker                                 uint32_t dex_pc,
2833*795d594fSAndroid Build Coastguard Worker                                 ArenaAllocator* allocator,
2834*795d594fSAndroid Build Coastguard Worker                                 size_t number_of_inputs,
2835*795d594fSAndroid Build Coastguard Worker                                 ArenaAllocKind kind)
2836*795d594fSAndroid Build Coastguard Worker       : HInstruction(inst_kind, side_effects, dex_pc),
2837*795d594fSAndroid Build Coastguard Worker         inputs_(number_of_inputs, allocator->Adapter(kind)) {}
2838*795d594fSAndroid Build Coastguard Worker   HVariableInputSizeInstruction(InstructionKind inst_kind,
2839*795d594fSAndroid Build Coastguard Worker                                 DataType::Type type,
2840*795d594fSAndroid Build Coastguard Worker                                 SideEffects side_effects,
2841*795d594fSAndroid Build Coastguard Worker                                 uint32_t dex_pc,
2842*795d594fSAndroid Build Coastguard Worker                                 ArenaAllocator* allocator,
2843*795d594fSAndroid Build Coastguard Worker                                 size_t number_of_inputs,
2844*795d594fSAndroid Build Coastguard Worker                                 ArenaAllocKind kind)
2845*795d594fSAndroid Build Coastguard Worker       : HInstruction(inst_kind, type, side_effects, dex_pc),
2846*795d594fSAndroid Build Coastguard Worker         inputs_(number_of_inputs, allocator->Adapter(kind)) {}
2847*795d594fSAndroid Build Coastguard Worker 
2848*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(VariableInputSizeInstruction);
2849*795d594fSAndroid Build Coastguard Worker 
2850*795d594fSAndroid Build Coastguard Worker   ArenaVector<HUserRecord<HInstruction*>> inputs_;
2851*795d594fSAndroid Build Coastguard Worker };
2852*795d594fSAndroid Build Coastguard Worker 
2853*795d594fSAndroid Build Coastguard Worker template<size_t N>
2854*795d594fSAndroid Build Coastguard Worker class HExpression : public HInstruction {
2855*795d594fSAndroid Build Coastguard Worker  public:
2856*795d594fSAndroid Build Coastguard Worker   HExpression<N>(InstructionKind kind, SideEffects side_effects, uint32_t dex_pc)
2857*795d594fSAndroid Build Coastguard Worker       : HInstruction(kind, side_effects, dex_pc), inputs_() {}
2858*795d594fSAndroid Build Coastguard Worker   HExpression<N>(InstructionKind kind,
2859*795d594fSAndroid Build Coastguard Worker                  DataType::Type type,
2860*795d594fSAndroid Build Coastguard Worker                  SideEffects side_effects,
2861*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc)
2862*795d594fSAndroid Build Coastguard Worker       : HInstruction(kind, type, side_effects, dex_pc), inputs_() {}
2863*795d594fSAndroid Build Coastguard Worker   virtual ~HExpression() {}
2864*795d594fSAndroid Build Coastguard Worker 
2865*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
2866*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
2867*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(inputs_);
2868*795d594fSAndroid Build Coastguard Worker   }
2869*795d594fSAndroid Build Coastguard Worker 
2870*795d594fSAndroid Build Coastguard Worker  protected:
2871*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Expression<N>);
2872*795d594fSAndroid Build Coastguard Worker 
2873*795d594fSAndroid Build Coastguard Worker  private:
2874*795d594fSAndroid Build Coastguard Worker   std::array<HUserRecord<HInstruction*>, N> inputs_;
2875*795d594fSAndroid Build Coastguard Worker 
2876*795d594fSAndroid Build Coastguard Worker   friend class SsaBuilder;
2877*795d594fSAndroid Build Coastguard Worker };
2878*795d594fSAndroid Build Coastguard Worker 
2879*795d594fSAndroid Build Coastguard Worker // HExpression specialization for N=0.
2880*795d594fSAndroid Build Coastguard Worker template<>
2881*795d594fSAndroid Build Coastguard Worker class HExpression<0> : public HInstruction {
2882*795d594fSAndroid Build Coastguard Worker  public:
2883*795d594fSAndroid Build Coastguard Worker   using HInstruction::HInstruction;
2884*795d594fSAndroid Build Coastguard Worker 
2885*795d594fSAndroid Build Coastguard Worker   virtual ~HExpression() {}
2886*795d594fSAndroid Build Coastguard Worker 
2887*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
2888*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
2889*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>();
2890*795d594fSAndroid Build Coastguard Worker   }
2891*795d594fSAndroid Build Coastguard Worker 
2892*795d594fSAndroid Build Coastguard Worker  protected:
2893*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Expression<0>);
2894*795d594fSAndroid Build Coastguard Worker 
2895*795d594fSAndroid Build Coastguard Worker  private:
2896*795d594fSAndroid Build Coastguard Worker   friend class SsaBuilder;
2897*795d594fSAndroid Build Coastguard Worker };
2898*795d594fSAndroid Build Coastguard Worker 
2899*795d594fSAndroid Build Coastguard Worker class HMethodEntryHook : public HExpression<0> {
2900*795d594fSAndroid Build Coastguard Worker  public:
2901*795d594fSAndroid Build Coastguard Worker   explicit HMethodEntryHook(uint32_t dex_pc)
2902*795d594fSAndroid Build Coastguard Worker       : HExpression(kMethodEntryHook, SideEffects::All(), dex_pc) {}
2903*795d594fSAndroid Build Coastguard Worker 
2904*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
2905*795d594fSAndroid Build Coastguard Worker     return true;
2906*795d594fSAndroid Build Coastguard Worker   }
2907*795d594fSAndroid Build Coastguard Worker 
2908*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
2909*795d594fSAndroid Build Coastguard Worker 
2910*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(MethodEntryHook);
2911*795d594fSAndroid Build Coastguard Worker 
2912*795d594fSAndroid Build Coastguard Worker  protected:
2913*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(MethodEntryHook);
2914*795d594fSAndroid Build Coastguard Worker };
2915*795d594fSAndroid Build Coastguard Worker 
2916*795d594fSAndroid Build Coastguard Worker class HMethodExitHook : public HExpression<1> {
2917*795d594fSAndroid Build Coastguard Worker  public:
2918*795d594fSAndroid Build Coastguard Worker   HMethodExitHook(HInstruction* value, uint32_t dex_pc)
2919*795d594fSAndroid Build Coastguard Worker       : HExpression(kMethodExitHook, SideEffects::All(), dex_pc) {
2920*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, value);
2921*795d594fSAndroid Build Coastguard Worker   }
2922*795d594fSAndroid Build Coastguard Worker 
2923*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
2924*795d594fSAndroid Build Coastguard Worker     return true;
2925*795d594fSAndroid Build Coastguard Worker   }
2926*795d594fSAndroid Build Coastguard Worker 
2927*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
2928*795d594fSAndroid Build Coastguard Worker 
2929*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(MethodExitHook);
2930*795d594fSAndroid Build Coastguard Worker 
2931*795d594fSAndroid Build Coastguard Worker  protected:
2932*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(MethodExitHook);
2933*795d594fSAndroid Build Coastguard Worker };
2934*795d594fSAndroid Build Coastguard Worker 
2935*795d594fSAndroid Build Coastguard Worker // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
2936*795d594fSAndroid Build Coastguard Worker // instruction that branches to the exit block.
2937*795d594fSAndroid Build Coastguard Worker class HReturnVoid final : public HExpression<0> {
2938*795d594fSAndroid Build Coastguard Worker  public:
2939*795d594fSAndroid Build Coastguard Worker   explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
2940*795d594fSAndroid Build Coastguard Worker       : HExpression(kReturnVoid, SideEffects::None(), dex_pc) {
2941*795d594fSAndroid Build Coastguard Worker   }
2942*795d594fSAndroid Build Coastguard Worker 
2943*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
2944*795d594fSAndroid Build Coastguard Worker 
2945*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ReturnVoid);
2946*795d594fSAndroid Build Coastguard Worker 
2947*795d594fSAndroid Build Coastguard Worker  protected:
2948*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ReturnVoid);
2949*795d594fSAndroid Build Coastguard Worker };
2950*795d594fSAndroid Build Coastguard Worker 
2951*795d594fSAndroid Build Coastguard Worker // Represents dex's RETURN opcodes. A HReturn is a control flow
2952*795d594fSAndroid Build Coastguard Worker // instruction that branches to the exit block.
2953*795d594fSAndroid Build Coastguard Worker class HReturn final : public HExpression<1> {
2954*795d594fSAndroid Build Coastguard Worker  public:
2955*795d594fSAndroid Build Coastguard Worker   explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
2956*795d594fSAndroid Build Coastguard Worker       : HExpression(kReturn, SideEffects::None(), dex_pc) {
2957*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, value);
2958*795d594fSAndroid Build Coastguard Worker   }
2959*795d594fSAndroid Build Coastguard Worker 
2960*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
2961*795d594fSAndroid Build Coastguard Worker 
2962*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Return);
2963*795d594fSAndroid Build Coastguard Worker 
2964*795d594fSAndroid Build Coastguard Worker  protected:
2965*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Return);
2966*795d594fSAndroid Build Coastguard Worker };
2967*795d594fSAndroid Build Coastguard Worker 
2968*795d594fSAndroid Build Coastguard Worker class HPhi final : public HVariableInputSizeInstruction {
2969*795d594fSAndroid Build Coastguard Worker  public:
2970*795d594fSAndroid Build Coastguard Worker   HPhi(ArenaAllocator* allocator,
2971*795d594fSAndroid Build Coastguard Worker        uint32_t reg_number,
2972*795d594fSAndroid Build Coastguard Worker        size_t number_of_inputs,
2973*795d594fSAndroid Build Coastguard Worker        DataType::Type type,
2974*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
2975*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(
2976*795d594fSAndroid Build Coastguard Worker             kPhi,
2977*795d594fSAndroid Build Coastguard Worker             ToPhiType(type),
2978*795d594fSAndroid Build Coastguard Worker             SideEffects::None(),
2979*795d594fSAndroid Build Coastguard Worker             dex_pc,
2980*795d594fSAndroid Build Coastguard Worker             allocator,
2981*795d594fSAndroid Build Coastguard Worker             number_of_inputs,
2982*795d594fSAndroid Build Coastguard Worker             kArenaAllocPhiInputs),
2983*795d594fSAndroid Build Coastguard Worker         reg_number_(reg_number) {
2984*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(GetType(), DataType::Type::kVoid);
2985*795d594fSAndroid Build Coastguard Worker     // Phis are constructed live and marked dead if conflicting or unused.
2986*795d594fSAndroid Build Coastguard Worker     // Individual steps of SsaBuilder should assume that if a phi has been
2987*795d594fSAndroid Build Coastguard Worker     // marked dead, it can be ignored and will be removed by SsaPhiElimination.
2988*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsLive>(true);
2989*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagCanBeNull>(true);
2990*795d594fSAndroid Build Coastguard Worker   }
2991*795d594fSAndroid Build Coastguard Worker 
2992*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
2993*795d594fSAndroid Build Coastguard Worker 
2994*795d594fSAndroid Build Coastguard Worker   // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
2995*795d594fSAndroid Build Coastguard Worker   static DataType::Type ToPhiType(DataType::Type type) {
2996*795d594fSAndroid Build Coastguard Worker     return DataType::Kind(type);
2997*795d594fSAndroid Build Coastguard Worker   }
2998*795d594fSAndroid Build Coastguard Worker 
2999*795d594fSAndroid Build Coastguard Worker   bool IsCatchPhi() const { return GetBlock()->IsCatchBlock(); }
3000*795d594fSAndroid Build Coastguard Worker 
3001*795d594fSAndroid Build Coastguard Worker   void SetType(DataType::Type new_type) {
3002*795d594fSAndroid Build Coastguard Worker     // Make sure that only valid type changes occur. The following are allowed:
3003*795d594fSAndroid Build Coastguard Worker     //  (1) int  -> float/ref (primitive type propagation),
3004*795d594fSAndroid Build Coastguard Worker     //  (2) long -> double (primitive type propagation).
3005*795d594fSAndroid Build Coastguard Worker     DCHECK(GetType() == new_type ||
3006*795d594fSAndroid Build Coastguard Worker            (GetType() == DataType::Type::kInt32 && new_type == DataType::Type::kFloat32) ||
3007*795d594fSAndroid Build Coastguard Worker            (GetType() == DataType::Type::kInt32 && new_type == DataType::Type::kReference) ||
3008*795d594fSAndroid Build Coastguard Worker            (GetType() == DataType::Type::kInt64 && new_type == DataType::Type::kFloat64));
3009*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(new_type);
3010*795d594fSAndroid Build Coastguard Worker   }
3011*795d594fSAndroid Build Coastguard Worker 
3012*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return GetPackedFlag<kFlagCanBeNull>(); }
3013*795d594fSAndroid Build Coastguard Worker   void SetCanBeNull(bool can_be_null) { SetPackedFlag<kFlagCanBeNull>(can_be_null); }
3014*795d594fSAndroid Build Coastguard Worker 
3015*795d594fSAndroid Build Coastguard Worker   uint32_t GetRegNumber() const { return reg_number_; }
3016*795d594fSAndroid Build Coastguard Worker 
3017*795d594fSAndroid Build Coastguard Worker   void SetDead() { SetPackedFlag<kFlagIsLive>(false); }
3018*795d594fSAndroid Build Coastguard Worker   void SetLive() { SetPackedFlag<kFlagIsLive>(true); }
3019*795d594fSAndroid Build Coastguard Worker   bool IsDead() const { return !IsLive(); }
3020*795d594fSAndroid Build Coastguard Worker   bool IsLive() const { return GetPackedFlag<kFlagIsLive>(); }
3021*795d594fSAndroid Build Coastguard Worker 
3022*795d594fSAndroid Build Coastguard Worker   bool IsVRegEquivalentOf(const HInstruction* other) const {
3023*795d594fSAndroid Build Coastguard Worker     return other != nullptr
3024*795d594fSAndroid Build Coastguard Worker         && other->IsPhi()
3025*795d594fSAndroid Build Coastguard Worker         && other->GetBlock() == GetBlock()
3026*795d594fSAndroid Build Coastguard Worker         && other->AsPhi()->GetRegNumber() == GetRegNumber();
3027*795d594fSAndroid Build Coastguard Worker   }
3028*795d594fSAndroid Build Coastguard Worker 
3029*795d594fSAndroid Build Coastguard Worker   bool HasEquivalentPhi() const {
3030*795d594fSAndroid Build Coastguard Worker     if (GetPrevious() != nullptr && GetPrevious()->AsPhi()->GetRegNumber() == GetRegNumber()) {
3031*795d594fSAndroid Build Coastguard Worker       return true;
3032*795d594fSAndroid Build Coastguard Worker     }
3033*795d594fSAndroid Build Coastguard Worker     if (GetNext() != nullptr && GetNext()->AsPhi()->GetRegNumber() == GetRegNumber()) {
3034*795d594fSAndroid Build Coastguard Worker       return true;
3035*795d594fSAndroid Build Coastguard Worker     }
3036*795d594fSAndroid Build Coastguard Worker     return false;
3037*795d594fSAndroid Build Coastguard Worker   }
3038*795d594fSAndroid Build Coastguard Worker 
3039*795d594fSAndroid Build Coastguard Worker   // Returns the next equivalent phi (starting from the current one) or null if there is none.
3040*795d594fSAndroid Build Coastguard Worker   // An equivalent phi is a phi having the same dex register and type.
3041*795d594fSAndroid Build Coastguard Worker   // It assumes that phis with the same dex register are adjacent.
3042*795d594fSAndroid Build Coastguard Worker   HPhi* GetNextEquivalentPhiWithSameType() {
3043*795d594fSAndroid Build Coastguard Worker     HInstruction* next = GetNext();
3044*795d594fSAndroid Build Coastguard Worker     while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
3045*795d594fSAndroid Build Coastguard Worker       if (next->GetType() == GetType()) {
3046*795d594fSAndroid Build Coastguard Worker         return next->AsPhi();
3047*795d594fSAndroid Build Coastguard Worker       }
3048*795d594fSAndroid Build Coastguard Worker       next = next->GetNext();
3049*795d594fSAndroid Build Coastguard Worker     }
3050*795d594fSAndroid Build Coastguard Worker     return nullptr;
3051*795d594fSAndroid Build Coastguard Worker   }
3052*795d594fSAndroid Build Coastguard Worker 
3053*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Phi);
3054*795d594fSAndroid Build Coastguard Worker 
3055*795d594fSAndroid Build Coastguard Worker  protected:
3056*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Phi);
3057*795d594fSAndroid Build Coastguard Worker 
3058*795d594fSAndroid Build Coastguard Worker  private:
3059*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsLive = HInstruction::kNumberOfGenericPackedBits;
3060*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagCanBeNull = kFlagIsLive + 1;
3061*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfPhiPackedBits = kFlagCanBeNull + 1;
3062*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfPhiPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
3063*795d594fSAndroid Build Coastguard Worker 
3064*795d594fSAndroid Build Coastguard Worker   const uint32_t reg_number_;
3065*795d594fSAndroid Build Coastguard Worker };
3066*795d594fSAndroid Build Coastguard Worker 
3067*795d594fSAndroid Build Coastguard Worker // The exit instruction is the only instruction of the exit block.
3068*795d594fSAndroid Build Coastguard Worker // Instructions aborting the method (HThrow and HReturn) must branch to the
3069*795d594fSAndroid Build Coastguard Worker // exit block.
3070*795d594fSAndroid Build Coastguard Worker class HExit final : public HExpression<0> {
3071*795d594fSAndroid Build Coastguard Worker  public:
3072*795d594fSAndroid Build Coastguard Worker   explicit HExit(uint32_t dex_pc = kNoDexPc)
3073*795d594fSAndroid Build Coastguard Worker       : HExpression(kExit, SideEffects::None(), dex_pc) {
3074*795d594fSAndroid Build Coastguard Worker   }
3075*795d594fSAndroid Build Coastguard Worker 
3076*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
3077*795d594fSAndroid Build Coastguard Worker 
3078*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Exit);
3079*795d594fSAndroid Build Coastguard Worker 
3080*795d594fSAndroid Build Coastguard Worker  protected:
3081*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Exit);
3082*795d594fSAndroid Build Coastguard Worker };
3083*795d594fSAndroid Build Coastguard Worker 
3084*795d594fSAndroid Build Coastguard Worker // Jumps from one block to another.
3085*795d594fSAndroid Build Coastguard Worker class HGoto final : public HExpression<0> {
3086*795d594fSAndroid Build Coastguard Worker  public:
3087*795d594fSAndroid Build Coastguard Worker   explicit HGoto(uint32_t dex_pc = kNoDexPc)
3088*795d594fSAndroid Build Coastguard Worker       : HExpression(kGoto, SideEffects::None(), dex_pc) {
3089*795d594fSAndroid Build Coastguard Worker   }
3090*795d594fSAndroid Build Coastguard Worker 
3091*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3092*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
3093*795d594fSAndroid Build Coastguard Worker 
3094*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetSuccessor() const {
3095*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetSingleSuccessor();
3096*795d594fSAndroid Build Coastguard Worker   }
3097*795d594fSAndroid Build Coastguard Worker 
3098*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Goto);
3099*795d594fSAndroid Build Coastguard Worker 
3100*795d594fSAndroid Build Coastguard Worker  protected:
3101*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Goto);
3102*795d594fSAndroid Build Coastguard Worker };
3103*795d594fSAndroid Build Coastguard Worker 
3104*795d594fSAndroid Build Coastguard Worker class HConstant : public HExpression<0> {
3105*795d594fSAndroid Build Coastguard Worker  public:
3106*795d594fSAndroid Build Coastguard Worker   explicit HConstant(InstructionKind kind, DataType::Type type)
3107*795d594fSAndroid Build Coastguard Worker       : HExpression(kind, type, SideEffects::None(), kNoDexPc) {
3108*795d594fSAndroid Build Coastguard Worker   }
3109*795d594fSAndroid Build Coastguard Worker 
3110*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
3111*795d594fSAndroid Build Coastguard Worker 
3112*795d594fSAndroid Build Coastguard Worker   // Is this constant -1 in the arithmetic sense?
3113*795d594fSAndroid Build Coastguard Worker   virtual bool IsMinusOne() const { return false; }
3114*795d594fSAndroid Build Coastguard Worker   // Is this constant 0 in the arithmetic sense?
3115*795d594fSAndroid Build Coastguard Worker   virtual bool IsArithmeticZero() const { return false; }
3116*795d594fSAndroid Build Coastguard Worker   // Is this constant a 0-bit pattern?
3117*795d594fSAndroid Build Coastguard Worker   virtual bool IsZeroBitPattern() const { return false; }
3118*795d594fSAndroid Build Coastguard Worker   // Is this constant 1 in the arithmetic sense?
3119*795d594fSAndroid Build Coastguard Worker   virtual bool IsOne() const { return false; }
3120*795d594fSAndroid Build Coastguard Worker 
3121*795d594fSAndroid Build Coastguard Worker   virtual uint64_t GetValueAsUint64() const = 0;
3122*795d594fSAndroid Build Coastguard Worker 
3123*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(Constant);
3124*795d594fSAndroid Build Coastguard Worker 
3125*795d594fSAndroid Build Coastguard Worker  protected:
3126*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Constant);
3127*795d594fSAndroid Build Coastguard Worker };
3128*795d594fSAndroid Build Coastguard Worker 
3129*795d594fSAndroid Build Coastguard Worker class HNullConstant final : public HConstant {
3130*795d594fSAndroid Build Coastguard Worker  public:
3131*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
3132*795d594fSAndroid Build Coastguard Worker     return true;
3133*795d594fSAndroid Build Coastguard Worker   }
3134*795d594fSAndroid Build Coastguard Worker 
3135*795d594fSAndroid Build Coastguard Worker   uint64_t GetValueAsUint64() const override { return 0; }
3136*795d594fSAndroid Build Coastguard Worker 
3137*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return 0; }
3138*795d594fSAndroid Build Coastguard Worker 
3139*795d594fSAndroid Build Coastguard Worker   // The null constant representation is a 0-bit pattern.
3140*795d594fSAndroid Build Coastguard Worker   bool IsZeroBitPattern() const override { return true; }
3141*795d594fSAndroid Build Coastguard Worker 
3142*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(NullConstant);
3143*795d594fSAndroid Build Coastguard Worker 
3144*795d594fSAndroid Build Coastguard Worker  protected:
3145*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(NullConstant);
3146*795d594fSAndroid Build Coastguard Worker 
3147*795d594fSAndroid Build Coastguard Worker  private:
3148*795d594fSAndroid Build Coastguard Worker   explicit HNullConstant()
3149*795d594fSAndroid Build Coastguard Worker       : HConstant(kNullConstant, DataType::Type::kReference) {
3150*795d594fSAndroid Build Coastguard Worker   }
3151*795d594fSAndroid Build Coastguard Worker 
3152*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
3153*795d594fSAndroid Build Coastguard Worker };
3154*795d594fSAndroid Build Coastguard Worker 
3155*795d594fSAndroid Build Coastguard Worker // Constants of the type int. Those can be from Dex instructions, or
3156*795d594fSAndroid Build Coastguard Worker // synthesized (for example with the if-eqz instruction).
3157*795d594fSAndroid Build Coastguard Worker class HIntConstant final : public HConstant {
3158*795d594fSAndroid Build Coastguard Worker  public:
3159*795d594fSAndroid Build Coastguard Worker   int32_t GetValue() const { return value_; }
3160*795d594fSAndroid Build Coastguard Worker 
3161*795d594fSAndroid Build Coastguard Worker   uint64_t GetValueAsUint64() const override {
3162*795d594fSAndroid Build Coastguard Worker     return static_cast<uint64_t>(static_cast<uint32_t>(value_));
3163*795d594fSAndroid Build Coastguard Worker   }
3164*795d594fSAndroid Build Coastguard Worker 
3165*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3166*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsIntConstant()) << other->DebugName();
3167*795d594fSAndroid Build Coastguard Worker     return other->AsIntConstant()->value_ == value_;
3168*795d594fSAndroid Build Coastguard Worker   }
3169*795d594fSAndroid Build Coastguard Worker 
3170*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return GetValue(); }
3171*795d594fSAndroid Build Coastguard Worker 
3172*795d594fSAndroid Build Coastguard Worker   bool IsMinusOne() const override { return GetValue() == -1; }
3173*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticZero() const override { return GetValue() == 0; }
3174*795d594fSAndroid Build Coastguard Worker   bool IsZeroBitPattern() const override { return GetValue() == 0; }
3175*795d594fSAndroid Build Coastguard Worker   bool IsOne() const override { return GetValue() == 1; }
3176*795d594fSAndroid Build Coastguard Worker 
3177*795d594fSAndroid Build Coastguard Worker   // Integer constants are used to encode Boolean values as well,
3178*795d594fSAndroid Build Coastguard Worker   // where 1 means true and 0 means false.
3179*795d594fSAndroid Build Coastguard Worker   bool IsTrue() const { return GetValue() == 1; }
3180*795d594fSAndroid Build Coastguard Worker   bool IsFalse() const { return GetValue() == 0; }
3181*795d594fSAndroid Build Coastguard Worker 
3182*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(IntConstant);
3183*795d594fSAndroid Build Coastguard Worker 
3184*795d594fSAndroid Build Coastguard Worker  protected:
3185*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(IntConstant);
3186*795d594fSAndroid Build Coastguard Worker 
3187*795d594fSAndroid Build Coastguard Worker  private:
3188*795d594fSAndroid Build Coastguard Worker   explicit HIntConstant(int32_t value)
3189*795d594fSAndroid Build Coastguard Worker       : HConstant(kIntConstant, DataType::Type::kInt32), value_(value) {
3190*795d594fSAndroid Build Coastguard Worker   }
3191*795d594fSAndroid Build Coastguard Worker   explicit HIntConstant(bool value)
3192*795d594fSAndroid Build Coastguard Worker       : HConstant(kIntConstant, DataType::Type::kInt32),
3193*795d594fSAndroid Build Coastguard Worker         value_(value ? 1 : 0) {
3194*795d594fSAndroid Build Coastguard Worker   }
3195*795d594fSAndroid Build Coastguard Worker 
3196*795d594fSAndroid Build Coastguard Worker   const int32_t value_;
3197*795d594fSAndroid Build Coastguard Worker 
3198*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
3199*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
3200*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
3201*795d594fSAndroid Build Coastguard Worker };
3202*795d594fSAndroid Build Coastguard Worker 
3203*795d594fSAndroid Build Coastguard Worker class HLongConstant final : public HConstant {
3204*795d594fSAndroid Build Coastguard Worker  public:
3205*795d594fSAndroid Build Coastguard Worker   int64_t GetValue() const { return value_; }
3206*795d594fSAndroid Build Coastguard Worker 
3207*795d594fSAndroid Build Coastguard Worker   uint64_t GetValueAsUint64() const override { return value_; }
3208*795d594fSAndroid Build Coastguard Worker 
3209*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3210*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsLongConstant()) << other->DebugName();
3211*795d594fSAndroid Build Coastguard Worker     return other->AsLongConstant()->value_ == value_;
3212*795d594fSAndroid Build Coastguard Worker   }
3213*795d594fSAndroid Build Coastguard Worker 
3214*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return static_cast<size_t>(GetValue()); }
3215*795d594fSAndroid Build Coastguard Worker 
3216*795d594fSAndroid Build Coastguard Worker   bool IsMinusOne() const override { return GetValue() == -1; }
3217*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticZero() const override { return GetValue() == 0; }
3218*795d594fSAndroid Build Coastguard Worker   bool IsZeroBitPattern() const override { return GetValue() == 0; }
3219*795d594fSAndroid Build Coastguard Worker   bool IsOne() const override { return GetValue() == 1; }
3220*795d594fSAndroid Build Coastguard Worker 
3221*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LongConstant);
3222*795d594fSAndroid Build Coastguard Worker 
3223*795d594fSAndroid Build Coastguard Worker  protected:
3224*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LongConstant);
3225*795d594fSAndroid Build Coastguard Worker 
3226*795d594fSAndroid Build Coastguard Worker  private:
3227*795d594fSAndroid Build Coastguard Worker   explicit HLongConstant(int64_t value)
3228*795d594fSAndroid Build Coastguard Worker       : HConstant(kLongConstant, DataType::Type::kInt64),
3229*795d594fSAndroid Build Coastguard Worker         value_(value) {
3230*795d594fSAndroid Build Coastguard Worker   }
3231*795d594fSAndroid Build Coastguard Worker 
3232*795d594fSAndroid Build Coastguard Worker   const int64_t value_;
3233*795d594fSAndroid Build Coastguard Worker 
3234*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
3235*795d594fSAndroid Build Coastguard Worker };
3236*795d594fSAndroid Build Coastguard Worker 
3237*795d594fSAndroid Build Coastguard Worker class HFloatConstant final : public HConstant {
3238*795d594fSAndroid Build Coastguard Worker  public:
3239*795d594fSAndroid Build Coastguard Worker   float GetValue() const { return value_; }
3240*795d594fSAndroid Build Coastguard Worker 
3241*795d594fSAndroid Build Coastguard Worker   uint64_t GetValueAsUint64() const override {
3242*795d594fSAndroid Build Coastguard Worker     return static_cast<uint64_t>(bit_cast<uint32_t, float>(value_));
3243*795d594fSAndroid Build Coastguard Worker   }
3244*795d594fSAndroid Build Coastguard Worker 
3245*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3246*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsFloatConstant()) << other->DebugName();
3247*795d594fSAndroid Build Coastguard Worker     return other->AsFloatConstant()->GetValueAsUint64() == GetValueAsUint64();
3248*795d594fSAndroid Build Coastguard Worker   }
3249*795d594fSAndroid Build Coastguard Worker 
3250*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return static_cast<size_t>(GetValue()); }
3251*795d594fSAndroid Build Coastguard Worker 
3252*795d594fSAndroid Build Coastguard Worker   bool IsMinusOne() const override {
3253*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
3254*795d594fSAndroid Build Coastguard Worker   }
3255*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticZero() const override {
3256*795d594fSAndroid Build Coastguard Worker     return std::fpclassify(value_) == FP_ZERO;
3257*795d594fSAndroid Build Coastguard Worker   }
3258*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticPositiveZero() const {
3259*795d594fSAndroid Build Coastguard Worker     return IsArithmeticZero() && !std::signbit(value_);
3260*795d594fSAndroid Build Coastguard Worker   }
3261*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticNegativeZero() const {
3262*795d594fSAndroid Build Coastguard Worker     return IsArithmeticZero() && std::signbit(value_);
3263*795d594fSAndroid Build Coastguard Worker   }
3264*795d594fSAndroid Build Coastguard Worker   bool IsZeroBitPattern() const override {
3265*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(0.0f);
3266*795d594fSAndroid Build Coastguard Worker   }
3267*795d594fSAndroid Build Coastguard Worker   bool IsOne() const override {
3268*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
3269*795d594fSAndroid Build Coastguard Worker   }
3270*795d594fSAndroid Build Coastguard Worker   bool IsNaN() const {
3271*795d594fSAndroid Build Coastguard Worker     return std::isnan(value_);
3272*795d594fSAndroid Build Coastguard Worker   }
3273*795d594fSAndroid Build Coastguard Worker 
3274*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(FloatConstant);
3275*795d594fSAndroid Build Coastguard Worker 
3276*795d594fSAndroid Build Coastguard Worker  protected:
3277*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(FloatConstant);
3278*795d594fSAndroid Build Coastguard Worker 
3279*795d594fSAndroid Build Coastguard Worker  private:
3280*795d594fSAndroid Build Coastguard Worker   explicit HFloatConstant(float value)
3281*795d594fSAndroid Build Coastguard Worker       : HConstant(kFloatConstant, DataType::Type::kFloat32),
3282*795d594fSAndroid Build Coastguard Worker         value_(value) {
3283*795d594fSAndroid Build Coastguard Worker   }
3284*795d594fSAndroid Build Coastguard Worker   explicit HFloatConstant(int32_t value)
3285*795d594fSAndroid Build Coastguard Worker       : HConstant(kFloatConstant, DataType::Type::kFloat32),
3286*795d594fSAndroid Build Coastguard Worker         value_(bit_cast<float, int32_t>(value)) {
3287*795d594fSAndroid Build Coastguard Worker   }
3288*795d594fSAndroid Build Coastguard Worker 
3289*795d594fSAndroid Build Coastguard Worker   const float value_;
3290*795d594fSAndroid Build Coastguard Worker 
3291*795d594fSAndroid Build Coastguard Worker   // Only the SsaBuilder and HGraph can create floating-point constants.
3292*795d594fSAndroid Build Coastguard Worker   friend class SsaBuilder;
3293*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
3294*795d594fSAndroid Build Coastguard Worker };
3295*795d594fSAndroid Build Coastguard Worker 
3296*795d594fSAndroid Build Coastguard Worker class HDoubleConstant final : public HConstant {
3297*795d594fSAndroid Build Coastguard Worker  public:
3298*795d594fSAndroid Build Coastguard Worker   double GetValue() const { return value_; }
3299*795d594fSAndroid Build Coastguard Worker 
3300*795d594fSAndroid Build Coastguard Worker   uint64_t GetValueAsUint64() const override { return bit_cast<uint64_t, double>(value_); }
3301*795d594fSAndroid Build Coastguard Worker 
3302*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3303*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsDoubleConstant()) << other->DebugName();
3304*795d594fSAndroid Build Coastguard Worker     return other->AsDoubleConstant()->GetValueAsUint64() == GetValueAsUint64();
3305*795d594fSAndroid Build Coastguard Worker   }
3306*795d594fSAndroid Build Coastguard Worker 
3307*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return static_cast<size_t>(GetValue()); }
3308*795d594fSAndroid Build Coastguard Worker 
3309*795d594fSAndroid Build Coastguard Worker   bool IsMinusOne() const override {
3310*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
3311*795d594fSAndroid Build Coastguard Worker   }
3312*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticZero() const override {
3313*795d594fSAndroid Build Coastguard Worker     return std::fpclassify(value_) == FP_ZERO;
3314*795d594fSAndroid Build Coastguard Worker   }
3315*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticPositiveZero() const {
3316*795d594fSAndroid Build Coastguard Worker     return IsArithmeticZero() && !std::signbit(value_);
3317*795d594fSAndroid Build Coastguard Worker   }
3318*795d594fSAndroid Build Coastguard Worker   bool IsArithmeticNegativeZero() const {
3319*795d594fSAndroid Build Coastguard Worker     return IsArithmeticZero() && std::signbit(value_);
3320*795d594fSAndroid Build Coastguard Worker   }
3321*795d594fSAndroid Build Coastguard Worker   bool IsZeroBitPattern() const override {
3322*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((0.0));
3323*795d594fSAndroid Build Coastguard Worker   }
3324*795d594fSAndroid Build Coastguard Worker   bool IsOne() const override {
3325*795d594fSAndroid Build Coastguard Worker     return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
3326*795d594fSAndroid Build Coastguard Worker   }
3327*795d594fSAndroid Build Coastguard Worker   bool IsNaN() const {
3328*795d594fSAndroid Build Coastguard Worker     return std::isnan(value_);
3329*795d594fSAndroid Build Coastguard Worker   }
3330*795d594fSAndroid Build Coastguard Worker 
3331*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(DoubleConstant);
3332*795d594fSAndroid Build Coastguard Worker 
3333*795d594fSAndroid Build Coastguard Worker  protected:
3334*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(DoubleConstant);
3335*795d594fSAndroid Build Coastguard Worker 
3336*795d594fSAndroid Build Coastguard Worker  private:
3337*795d594fSAndroid Build Coastguard Worker   explicit HDoubleConstant(double value)
3338*795d594fSAndroid Build Coastguard Worker       : HConstant(kDoubleConstant, DataType::Type::kFloat64),
3339*795d594fSAndroid Build Coastguard Worker         value_(value) {
3340*795d594fSAndroid Build Coastguard Worker   }
3341*795d594fSAndroid Build Coastguard Worker   explicit HDoubleConstant(int64_t value)
3342*795d594fSAndroid Build Coastguard Worker       : HConstant(kDoubleConstant, DataType::Type::kFloat64),
3343*795d594fSAndroid Build Coastguard Worker         value_(bit_cast<double, int64_t>(value)) {
3344*795d594fSAndroid Build Coastguard Worker   }
3345*795d594fSAndroid Build Coastguard Worker 
3346*795d594fSAndroid Build Coastguard Worker   const double value_;
3347*795d594fSAndroid Build Coastguard Worker 
3348*795d594fSAndroid Build Coastguard Worker   // Only the SsaBuilder and HGraph can create floating-point constants.
3349*795d594fSAndroid Build Coastguard Worker   friend class SsaBuilder;
3350*795d594fSAndroid Build Coastguard Worker   friend class HGraph;
3351*795d594fSAndroid Build Coastguard Worker };
3352*795d594fSAndroid Build Coastguard Worker 
3353*795d594fSAndroid Build Coastguard Worker // Conditional branch. A block ending with an HIf instruction must have
3354*795d594fSAndroid Build Coastguard Worker // two successors.
3355*795d594fSAndroid Build Coastguard Worker class HIf final : public HExpression<1> {
3356*795d594fSAndroid Build Coastguard Worker  public:
3357*795d594fSAndroid Build Coastguard Worker   explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
3358*795d594fSAndroid Build Coastguard Worker       : HExpression(kIf, SideEffects::None(), dex_pc),
3359*795d594fSAndroid Build Coastguard Worker         true_count_(std::numeric_limits<uint16_t>::max()),
3360*795d594fSAndroid Build Coastguard Worker         false_count_(std::numeric_limits<uint16_t>::max()) {
3361*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
3362*795d594fSAndroid Build Coastguard Worker   }
3363*795d594fSAndroid Build Coastguard Worker 
3364*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3365*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
3366*795d594fSAndroid Build Coastguard Worker 
3367*795d594fSAndroid Build Coastguard Worker   HBasicBlock* IfTrueSuccessor() const {
3368*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetSuccessors()[0];
3369*795d594fSAndroid Build Coastguard Worker   }
3370*795d594fSAndroid Build Coastguard Worker 
3371*795d594fSAndroid Build Coastguard Worker   HBasicBlock* IfFalseSuccessor() const {
3372*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetSuccessors()[1];
3373*795d594fSAndroid Build Coastguard Worker   }
3374*795d594fSAndroid Build Coastguard Worker 
3375*795d594fSAndroid Build Coastguard Worker   void SetTrueCount(uint16_t count) { true_count_ = count; }
3376*795d594fSAndroid Build Coastguard Worker   uint16_t GetTrueCount() const { return true_count_; }
3377*795d594fSAndroid Build Coastguard Worker 
3378*795d594fSAndroid Build Coastguard Worker   void SetFalseCount(uint16_t count) { false_count_ = count; }
3379*795d594fSAndroid Build Coastguard Worker   uint16_t GetFalseCount() const { return false_count_; }
3380*795d594fSAndroid Build Coastguard Worker 
3381*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(If);
3382*795d594fSAndroid Build Coastguard Worker 
3383*795d594fSAndroid Build Coastguard Worker  protected:
3384*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(If);
3385*795d594fSAndroid Build Coastguard Worker 
3386*795d594fSAndroid Build Coastguard Worker  private:
3387*795d594fSAndroid Build Coastguard Worker   uint16_t true_count_;
3388*795d594fSAndroid Build Coastguard Worker   uint16_t false_count_;
3389*795d594fSAndroid Build Coastguard Worker };
3390*795d594fSAndroid Build Coastguard Worker 
3391*795d594fSAndroid Build Coastguard Worker 
3392*795d594fSAndroid Build Coastguard Worker // Abstract instruction which marks the beginning and/or end of a try block and
3393*795d594fSAndroid Build Coastguard Worker // links it to the respective exception handlers. Behaves the same as a Goto in
3394*795d594fSAndroid Build Coastguard Worker // non-exceptional control flow.
3395*795d594fSAndroid Build Coastguard Worker // Normal-flow successor is stored at index zero, exception handlers under
3396*795d594fSAndroid Build Coastguard Worker // higher indices in no particular order.
3397*795d594fSAndroid Build Coastguard Worker class HTryBoundary final : public HExpression<0> {
3398*795d594fSAndroid Build Coastguard Worker  public:
3399*795d594fSAndroid Build Coastguard Worker   enum class BoundaryKind {
3400*795d594fSAndroid Build Coastguard Worker     kEntry,
3401*795d594fSAndroid Build Coastguard Worker     kExit,
3402*795d594fSAndroid Build Coastguard Worker     kLast = kExit
3403*795d594fSAndroid Build Coastguard Worker   };
3404*795d594fSAndroid Build Coastguard Worker 
3405*795d594fSAndroid Build Coastguard Worker   // SideEffects::CanTriggerGC prevents instructions with SideEffects::DependOnGC to be alive
3406*795d594fSAndroid Build Coastguard Worker   // across the catch block entering edges as GC might happen during throwing an exception.
3407*795d594fSAndroid Build Coastguard Worker   // TryBoundary with BoundaryKind::kExit is conservatively used for that as there is no
3408*795d594fSAndroid Build Coastguard Worker   // HInstruction which a catch block must start from.
3409*795d594fSAndroid Build Coastguard Worker   explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
3410*795d594fSAndroid Build Coastguard Worker       : HExpression(kTryBoundary,
3411*795d594fSAndroid Build Coastguard Worker                     (kind == BoundaryKind::kExit) ? SideEffects::CanTriggerGC()
3412*795d594fSAndroid Build Coastguard Worker                                                   : SideEffects::None(),
3413*795d594fSAndroid Build Coastguard Worker                     dex_pc) {
3414*795d594fSAndroid Build Coastguard Worker     SetPackedField<BoundaryKindField>(kind);
3415*795d594fSAndroid Build Coastguard Worker   }
3416*795d594fSAndroid Build Coastguard Worker 
3417*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
3418*795d594fSAndroid Build Coastguard Worker 
3419*795d594fSAndroid Build Coastguard Worker   // Returns the block's non-exceptional successor (index zero).
3420*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors()[0]; }
3421*795d594fSAndroid Build Coastguard Worker 
3422*795d594fSAndroid Build Coastguard Worker   ArrayRef<HBasicBlock* const> GetExceptionHandlers() const {
3423*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HBasicBlock* const>(GetBlock()->GetSuccessors()).SubArray(1u);
3424*795d594fSAndroid Build Coastguard Worker   }
3425*795d594fSAndroid Build Coastguard Worker 
3426*795d594fSAndroid Build Coastguard Worker   // Returns whether `handler` is among its exception handlers (non-zero index
3427*795d594fSAndroid Build Coastguard Worker   // successors).
3428*795d594fSAndroid Build Coastguard Worker   bool HasExceptionHandler(const HBasicBlock& handler) const {
3429*795d594fSAndroid Build Coastguard Worker     DCHECK(handler.IsCatchBlock());
3430*795d594fSAndroid Build Coastguard Worker     return GetBlock()->HasSuccessor(&handler, 1u /* Skip first successor. */);
3431*795d594fSAndroid Build Coastguard Worker   }
3432*795d594fSAndroid Build Coastguard Worker 
3433*795d594fSAndroid Build Coastguard Worker   // If not present already, adds `handler` to its block's list of exception
3434*795d594fSAndroid Build Coastguard Worker   // handlers.
3435*795d594fSAndroid Build Coastguard Worker   void AddExceptionHandler(HBasicBlock* handler) {
3436*795d594fSAndroid Build Coastguard Worker     if (!HasExceptionHandler(*handler)) {
3437*795d594fSAndroid Build Coastguard Worker       GetBlock()->AddSuccessor(handler);
3438*795d594fSAndroid Build Coastguard Worker     }
3439*795d594fSAndroid Build Coastguard Worker   }
3440*795d594fSAndroid Build Coastguard Worker 
3441*795d594fSAndroid Build Coastguard Worker   BoundaryKind GetBoundaryKind() const { return GetPackedField<BoundaryKindField>(); }
3442*795d594fSAndroid Build Coastguard Worker   bool IsEntry() const { return GetBoundaryKind() == BoundaryKind::kEntry; }
3443*795d594fSAndroid Build Coastguard Worker 
3444*795d594fSAndroid Build Coastguard Worker   bool HasSameExceptionHandlersAs(const HTryBoundary& other) const;
3445*795d594fSAndroid Build Coastguard Worker 
3446*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(TryBoundary);
3447*795d594fSAndroid Build Coastguard Worker 
3448*795d594fSAndroid Build Coastguard Worker  protected:
3449*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(TryBoundary);
3450*795d594fSAndroid Build Coastguard Worker 
3451*795d594fSAndroid Build Coastguard Worker  private:
3452*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldBoundaryKind = kNumberOfGenericPackedBits;
3453*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldBoundaryKindSize =
3454*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(BoundaryKind::kLast));
3455*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfTryBoundaryPackedBits =
3456*795d594fSAndroid Build Coastguard Worker       kFieldBoundaryKind + kFieldBoundaryKindSize;
3457*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfTryBoundaryPackedBits <= kMaxNumberOfPackedBits,
3458*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
3459*795d594fSAndroid Build Coastguard Worker   using BoundaryKindField = BitField<BoundaryKind, kFieldBoundaryKind, kFieldBoundaryKindSize>;
3460*795d594fSAndroid Build Coastguard Worker };
3461*795d594fSAndroid Build Coastguard Worker 
3462*795d594fSAndroid Build Coastguard Worker // Deoptimize to interpreter, upon checking a condition.
3463*795d594fSAndroid Build Coastguard Worker class HDeoptimize final : public HVariableInputSizeInstruction {
3464*795d594fSAndroid Build Coastguard Worker  public:
3465*795d594fSAndroid Build Coastguard Worker   // Use this constructor when the `HDeoptimize` acts as a barrier, where no code can move
3466*795d594fSAndroid Build Coastguard Worker   // across.
3467*795d594fSAndroid Build Coastguard Worker   HDeoptimize(ArenaAllocator* allocator,
3468*795d594fSAndroid Build Coastguard Worker               HInstruction* cond,
3469*795d594fSAndroid Build Coastguard Worker               DeoptimizationKind kind,
3470*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc)
3471*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(
3472*795d594fSAndroid Build Coastguard Worker             kDeoptimize,
3473*795d594fSAndroid Build Coastguard Worker             SideEffects::All(),
3474*795d594fSAndroid Build Coastguard Worker             dex_pc,
3475*795d594fSAndroid Build Coastguard Worker             allocator,
3476*795d594fSAndroid Build Coastguard Worker             /* number_of_inputs= */ 1,
3477*795d594fSAndroid Build Coastguard Worker             kArenaAllocMisc) {
3478*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFieldCanBeMoved>(false);
3479*795d594fSAndroid Build Coastguard Worker     SetPackedField<DeoptimizeKindField>(kind);
3480*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cond);
3481*795d594fSAndroid Build Coastguard Worker   }
3482*795d594fSAndroid Build Coastguard Worker 
3483*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3484*795d594fSAndroid Build Coastguard Worker 
3485*795d594fSAndroid Build Coastguard Worker   // Use this constructor when the `HDeoptimize` guards an instruction, and any user
3486*795d594fSAndroid Build Coastguard Worker   // that relies on the deoptimization to pass should have its input be the `HDeoptimize`
3487*795d594fSAndroid Build Coastguard Worker   // instead of `guard`.
3488*795d594fSAndroid Build Coastguard Worker   // We set CanTriggerGC to prevent any intermediate address to be live
3489*795d594fSAndroid Build Coastguard Worker   // at the point of the `HDeoptimize`.
3490*795d594fSAndroid Build Coastguard Worker   HDeoptimize(ArenaAllocator* allocator,
3491*795d594fSAndroid Build Coastguard Worker               HInstruction* cond,
3492*795d594fSAndroid Build Coastguard Worker               HInstruction* guard,
3493*795d594fSAndroid Build Coastguard Worker               DeoptimizationKind kind,
3494*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc)
3495*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(
3496*795d594fSAndroid Build Coastguard Worker             kDeoptimize,
3497*795d594fSAndroid Build Coastguard Worker             guard->GetType(),
3498*795d594fSAndroid Build Coastguard Worker             SideEffects::CanTriggerGC(),
3499*795d594fSAndroid Build Coastguard Worker             dex_pc,
3500*795d594fSAndroid Build Coastguard Worker             allocator,
3501*795d594fSAndroid Build Coastguard Worker             /* number_of_inputs= */ 2,
3502*795d594fSAndroid Build Coastguard Worker             kArenaAllocMisc) {
3503*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFieldCanBeMoved>(true);
3504*795d594fSAndroid Build Coastguard Worker     SetPackedField<DeoptimizeKindField>(kind);
3505*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cond);
3506*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, guard);
3507*795d594fSAndroid Build Coastguard Worker   }
3508*795d594fSAndroid Build Coastguard Worker 
3509*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return GetPackedFlag<kFieldCanBeMoved>(); }
3510*795d594fSAndroid Build Coastguard Worker 
3511*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3512*795d594fSAndroid Build Coastguard Worker     return (other->CanBeMoved() == CanBeMoved()) &&
3513*795d594fSAndroid Build Coastguard Worker            (other->AsDeoptimize()->GetDeoptimizationKind() == GetDeoptimizationKind());
3514*795d594fSAndroid Build Coastguard Worker   }
3515*795d594fSAndroid Build Coastguard Worker 
3516*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
3517*795d594fSAndroid Build Coastguard Worker 
3518*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
3519*795d594fSAndroid Build Coastguard Worker 
3520*795d594fSAndroid Build Coastguard Worker   DeoptimizationKind GetDeoptimizationKind() const { return GetPackedField<DeoptimizeKindField>(); }
3521*795d594fSAndroid Build Coastguard Worker 
3522*795d594fSAndroid Build Coastguard Worker   bool GuardsAnInput() const {
3523*795d594fSAndroid Build Coastguard Worker     return InputCount() == 2;
3524*795d594fSAndroid Build Coastguard Worker   }
3525*795d594fSAndroid Build Coastguard Worker 
3526*795d594fSAndroid Build Coastguard Worker   HInstruction* GuardedInput() const {
3527*795d594fSAndroid Build Coastguard Worker     DCHECK(GuardsAnInput());
3528*795d594fSAndroid Build Coastguard Worker     return InputAt(1);
3529*795d594fSAndroid Build Coastguard Worker   }
3530*795d594fSAndroid Build Coastguard Worker 
3531*795d594fSAndroid Build Coastguard Worker   void RemoveGuard() {
3532*795d594fSAndroid Build Coastguard Worker     RemoveInputAt(1);
3533*795d594fSAndroid Build Coastguard Worker   }
3534*795d594fSAndroid Build Coastguard Worker 
3535*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Deoptimize);
3536*795d594fSAndroid Build Coastguard Worker 
3537*795d594fSAndroid Build Coastguard Worker  protected:
3538*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Deoptimize);
3539*795d594fSAndroid Build Coastguard Worker 
3540*795d594fSAndroid Build Coastguard Worker  private:
3541*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldCanBeMoved = kNumberOfGenericPackedBits;
3542*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldDeoptimizeKind = kNumberOfGenericPackedBits + 1;
3543*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldDeoptimizeKindSize =
3544*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DeoptimizationKind::kLast));
3545*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfDeoptimizePackedBits =
3546*795d594fSAndroid Build Coastguard Worker       kFieldDeoptimizeKind + kFieldDeoptimizeKindSize;
3547*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfDeoptimizePackedBits <= kMaxNumberOfPackedBits,
3548*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
3549*795d594fSAndroid Build Coastguard Worker   using DeoptimizeKindField =
3550*795d594fSAndroid Build Coastguard Worker       BitField<DeoptimizationKind, kFieldDeoptimizeKind, kFieldDeoptimizeKindSize>;
3551*795d594fSAndroid Build Coastguard Worker };
3552*795d594fSAndroid Build Coastguard Worker 
3553*795d594fSAndroid Build Coastguard Worker // Represents a should_deoptimize flag. Currently used for CHA-based devirtualization.
3554*795d594fSAndroid Build Coastguard Worker // The compiled code checks this flag value in a guard before devirtualized call and
3555*795d594fSAndroid Build Coastguard Worker // if it's true, starts to do deoptimization.
3556*795d594fSAndroid Build Coastguard Worker // It has a 4-byte slot on stack.
3557*795d594fSAndroid Build Coastguard Worker // TODO: allocate a register for this flag.
3558*795d594fSAndroid Build Coastguard Worker class HShouldDeoptimizeFlag final : public HVariableInputSizeInstruction {
3559*795d594fSAndroid Build Coastguard Worker  public:
3560*795d594fSAndroid Build Coastguard Worker   // CHA guards are only optimized in a separate pass and it has no side effects
3561*795d594fSAndroid Build Coastguard Worker   // with regard to other passes.
3562*795d594fSAndroid Build Coastguard Worker   HShouldDeoptimizeFlag(ArenaAllocator* allocator, uint32_t dex_pc)
3563*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(kShouldDeoptimizeFlag,
3564*795d594fSAndroid Build Coastguard Worker                                       DataType::Type::kInt32,
3565*795d594fSAndroid Build Coastguard Worker                                       SideEffects::None(),
3566*795d594fSAndroid Build Coastguard Worker                                       dex_pc,
3567*795d594fSAndroid Build Coastguard Worker                                       allocator,
3568*795d594fSAndroid Build Coastguard Worker                                       0,
3569*795d594fSAndroid Build Coastguard Worker                                       kArenaAllocCHA) {
3570*795d594fSAndroid Build Coastguard Worker   }
3571*795d594fSAndroid Build Coastguard Worker 
3572*795d594fSAndroid Build Coastguard Worker   // We do all CHA guard elimination/motion in a single pass, after which there is no
3573*795d594fSAndroid Build Coastguard Worker   // further guard elimination/motion since a guard might have been used for justification
3574*795d594fSAndroid Build Coastguard Worker   // of the elimination of another guard. Therefore, we pretend this guard cannot be moved
3575*795d594fSAndroid Build Coastguard Worker   // to avoid other optimizations trying to move it.
3576*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return false; }
3577*795d594fSAndroid Build Coastguard Worker 
3578*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ShouldDeoptimizeFlag);
3579*795d594fSAndroid Build Coastguard Worker 
3580*795d594fSAndroid Build Coastguard Worker  protected:
3581*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ShouldDeoptimizeFlag);
3582*795d594fSAndroid Build Coastguard Worker };
3583*795d594fSAndroid Build Coastguard Worker 
3584*795d594fSAndroid Build Coastguard Worker // Represents the ArtMethod that was passed as a first argument to
3585*795d594fSAndroid Build Coastguard Worker // the method. It is used by instructions that depend on it, like
3586*795d594fSAndroid Build Coastguard Worker // instructions that work with the dex cache.
3587*795d594fSAndroid Build Coastguard Worker class HCurrentMethod final : public HExpression<0> {
3588*795d594fSAndroid Build Coastguard Worker  public:
3589*795d594fSAndroid Build Coastguard Worker   explicit HCurrentMethod(DataType::Type type, uint32_t dex_pc = kNoDexPc)
3590*795d594fSAndroid Build Coastguard Worker       : HExpression(kCurrentMethod, type, SideEffects::None(), dex_pc) {
3591*795d594fSAndroid Build Coastguard Worker   }
3592*795d594fSAndroid Build Coastguard Worker 
3593*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(CurrentMethod);
3594*795d594fSAndroid Build Coastguard Worker 
3595*795d594fSAndroid Build Coastguard Worker  protected:
3596*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(CurrentMethod);
3597*795d594fSAndroid Build Coastguard Worker };
3598*795d594fSAndroid Build Coastguard Worker 
3599*795d594fSAndroid Build Coastguard Worker // Fetches an ArtMethod from the virtual table or the interface method table
3600*795d594fSAndroid Build Coastguard Worker // of a class.
3601*795d594fSAndroid Build Coastguard Worker class HClassTableGet final : public HExpression<1> {
3602*795d594fSAndroid Build Coastguard Worker  public:
3603*795d594fSAndroid Build Coastguard Worker   enum class TableKind {
3604*795d594fSAndroid Build Coastguard Worker     kVTable,
3605*795d594fSAndroid Build Coastguard Worker     kIMTable,
3606*795d594fSAndroid Build Coastguard Worker     kLast = kIMTable
3607*795d594fSAndroid Build Coastguard Worker   };
3608*795d594fSAndroid Build Coastguard Worker   HClassTableGet(HInstruction* cls,
3609*795d594fSAndroid Build Coastguard Worker                  DataType::Type type,
3610*795d594fSAndroid Build Coastguard Worker                  TableKind kind,
3611*795d594fSAndroid Build Coastguard Worker                  size_t index,
3612*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc)
3613*795d594fSAndroid Build Coastguard Worker       : HExpression(kClassTableGet, type, SideEffects::None(), dex_pc),
3614*795d594fSAndroid Build Coastguard Worker         index_(index) {
3615*795d594fSAndroid Build Coastguard Worker     SetPackedField<TableKindField>(kind);
3616*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cls);
3617*795d594fSAndroid Build Coastguard Worker   }
3618*795d594fSAndroid Build Coastguard Worker 
3619*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3620*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
3621*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3622*795d594fSAndroid Build Coastguard Worker     return other->AsClassTableGet()->GetIndex() == index_ &&
3623*795d594fSAndroid Build Coastguard Worker         other->AsClassTableGet()->GetPackedFields() == GetPackedFields();
3624*795d594fSAndroid Build Coastguard Worker   }
3625*795d594fSAndroid Build Coastguard Worker 
3626*795d594fSAndroid Build Coastguard Worker   TableKind GetTableKind() const { return GetPackedField<TableKindField>(); }
3627*795d594fSAndroid Build Coastguard Worker   size_t GetIndex() const { return index_; }
3628*795d594fSAndroid Build Coastguard Worker 
3629*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ClassTableGet);
3630*795d594fSAndroid Build Coastguard Worker 
3631*795d594fSAndroid Build Coastguard Worker  protected:
3632*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ClassTableGet);
3633*795d594fSAndroid Build Coastguard Worker 
3634*795d594fSAndroid Build Coastguard Worker  private:
3635*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldTableKind = kNumberOfGenericPackedBits;
3636*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldTableKindSize =
3637*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(TableKind::kLast));
3638*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfClassTableGetPackedBits = kFieldTableKind + kFieldTableKindSize;
3639*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfClassTableGetPackedBits <= kMaxNumberOfPackedBits,
3640*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
3641*795d594fSAndroid Build Coastguard Worker   using TableKindField = BitField<TableKind, kFieldTableKind, kFieldTableKindSize>;
3642*795d594fSAndroid Build Coastguard Worker 
3643*795d594fSAndroid Build Coastguard Worker   // The index of the ArtMethod in the table.
3644*795d594fSAndroid Build Coastguard Worker   const size_t index_;
3645*795d594fSAndroid Build Coastguard Worker };
3646*795d594fSAndroid Build Coastguard Worker 
3647*795d594fSAndroid Build Coastguard Worker // PackedSwitch (jump table). A block ending with a PackedSwitch instruction will
3648*795d594fSAndroid Build Coastguard Worker // have one successor for each entry in the switch table, and the final successor
3649*795d594fSAndroid Build Coastguard Worker // will be the block containing the next Dex opcode.
3650*795d594fSAndroid Build Coastguard Worker class HPackedSwitch final : public HExpression<1> {
3651*795d594fSAndroid Build Coastguard Worker  public:
3652*795d594fSAndroid Build Coastguard Worker   HPackedSwitch(int32_t start_value,
3653*795d594fSAndroid Build Coastguard Worker                 uint32_t num_entries,
3654*795d594fSAndroid Build Coastguard Worker                 HInstruction* input,
3655*795d594fSAndroid Build Coastguard Worker                 uint32_t dex_pc = kNoDexPc)
3656*795d594fSAndroid Build Coastguard Worker     : HExpression(kPackedSwitch, SideEffects::None(), dex_pc),
3657*795d594fSAndroid Build Coastguard Worker       start_value_(start_value),
3658*795d594fSAndroid Build Coastguard Worker       num_entries_(num_entries) {
3659*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
3660*795d594fSAndroid Build Coastguard Worker   }
3661*795d594fSAndroid Build Coastguard Worker 
3662*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3663*795d594fSAndroid Build Coastguard Worker 
3664*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
3665*795d594fSAndroid Build Coastguard Worker 
3666*795d594fSAndroid Build Coastguard Worker   int32_t GetStartValue() const { return start_value_; }
3667*795d594fSAndroid Build Coastguard Worker 
3668*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumEntries() const { return num_entries_; }
3669*795d594fSAndroid Build Coastguard Worker 
3670*795d594fSAndroid Build Coastguard Worker   HBasicBlock* GetDefaultBlock() const {
3671*795d594fSAndroid Build Coastguard Worker     // Last entry is the default block.
3672*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetSuccessors()[num_entries_];
3673*795d594fSAndroid Build Coastguard Worker   }
3674*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(PackedSwitch);
3675*795d594fSAndroid Build Coastguard Worker 
3676*795d594fSAndroid Build Coastguard Worker  protected:
3677*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(PackedSwitch);
3678*795d594fSAndroid Build Coastguard Worker 
3679*795d594fSAndroid Build Coastguard Worker  private:
3680*795d594fSAndroid Build Coastguard Worker   const int32_t start_value_;
3681*795d594fSAndroid Build Coastguard Worker   const uint32_t num_entries_;
3682*795d594fSAndroid Build Coastguard Worker };
3683*795d594fSAndroid Build Coastguard Worker 
3684*795d594fSAndroid Build Coastguard Worker class HUnaryOperation : public HExpression<1> {
3685*795d594fSAndroid Build Coastguard Worker  public:
3686*795d594fSAndroid Build Coastguard Worker   HUnaryOperation(InstructionKind kind,
3687*795d594fSAndroid Build Coastguard Worker                   DataType::Type result_type,
3688*795d594fSAndroid Build Coastguard Worker                   HInstruction* input,
3689*795d594fSAndroid Build Coastguard Worker                   uint32_t dex_pc = kNoDexPc)
3690*795d594fSAndroid Build Coastguard Worker       : HExpression(kind, result_type, SideEffects::None(), dex_pc) {
3691*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
3692*795d594fSAndroid Build Coastguard Worker   }
3693*795d594fSAndroid Build Coastguard Worker 
3694*795d594fSAndroid Build Coastguard Worker   // All of the UnaryOperation instructions are clonable.
3695*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3696*795d594fSAndroid Build Coastguard Worker 
3697*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInput() const { return InputAt(0); }
3698*795d594fSAndroid Build Coastguard Worker   DataType::Type GetResultType() const { return GetType(); }
3699*795d594fSAndroid Build Coastguard Worker 
3700*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
3701*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
3702*795d594fSAndroid Build Coastguard Worker     return true;
3703*795d594fSAndroid Build Coastguard Worker   }
3704*795d594fSAndroid Build Coastguard Worker 
3705*795d594fSAndroid Build Coastguard Worker   // Try to statically evaluate `this` and return a HConstant
3706*795d594fSAndroid Build Coastguard Worker   // containing the result of this evaluation.  If `this` cannot
3707*795d594fSAndroid Build Coastguard Worker   // be evaluated as a constant, return null.
3708*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation() const;
3709*795d594fSAndroid Build Coastguard Worker 
3710*795d594fSAndroid Build Coastguard Worker   // Same but for `input` instead of GetInput().
3711*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation(HInstruction* input) const;
3712*795d594fSAndroid Build Coastguard Worker 
3713*795d594fSAndroid Build Coastguard Worker   // Apply this operation to `x`.
3714*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HIntConstant* x) const {
3715*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for int values";
3716*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3717*795d594fSAndroid Build Coastguard Worker   }
3718*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HLongConstant* x) const {
3719*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for long values";
3720*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3721*795d594fSAndroid Build Coastguard Worker   }
3722*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HFloatConstant* x) const {
3723*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for float values";
3724*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3725*795d594fSAndroid Build Coastguard Worker   }
3726*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x) const {
3727*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for double values";
3728*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3729*795d594fSAndroid Build Coastguard Worker   }
3730*795d594fSAndroid Build Coastguard Worker 
3731*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(UnaryOperation);
3732*795d594fSAndroid Build Coastguard Worker 
3733*795d594fSAndroid Build Coastguard Worker  protected:
3734*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UnaryOperation);
3735*795d594fSAndroid Build Coastguard Worker };
3736*795d594fSAndroid Build Coastguard Worker 
3737*795d594fSAndroid Build Coastguard Worker class HBinaryOperation : public HExpression<2> {
3738*795d594fSAndroid Build Coastguard Worker  public:
3739*795d594fSAndroid Build Coastguard Worker   HBinaryOperation(InstructionKind kind,
3740*795d594fSAndroid Build Coastguard Worker                    DataType::Type result_type,
3741*795d594fSAndroid Build Coastguard Worker                    HInstruction* left,
3742*795d594fSAndroid Build Coastguard Worker                    HInstruction* right,
3743*795d594fSAndroid Build Coastguard Worker                    SideEffects side_effects = SideEffects::None(),
3744*795d594fSAndroid Build Coastguard Worker                    uint32_t dex_pc = kNoDexPc)
3745*795d594fSAndroid Build Coastguard Worker       : HExpression(kind, result_type, side_effects, dex_pc) {
3746*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, left);
3747*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, right);
3748*795d594fSAndroid Build Coastguard Worker   }
3749*795d594fSAndroid Build Coastguard Worker 
3750*795d594fSAndroid Build Coastguard Worker   // All of the BinaryOperation instructions are clonable.
3751*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
3752*795d594fSAndroid Build Coastguard Worker 
3753*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLeft() const { return InputAt(0); }
3754*795d594fSAndroid Build Coastguard Worker   HInstruction* GetRight() const { return InputAt(1); }
3755*795d594fSAndroid Build Coastguard Worker   DataType::Type GetResultType() const { return GetType(); }
3756*795d594fSAndroid Build Coastguard Worker 
3757*795d594fSAndroid Build Coastguard Worker   virtual bool IsCommutative() const { return false; }
3758*795d594fSAndroid Build Coastguard Worker 
3759*795d594fSAndroid Build Coastguard Worker   // Put constant on the right.
3760*795d594fSAndroid Build Coastguard Worker   // Returns whether order is changed.
3761*795d594fSAndroid Build Coastguard Worker   bool OrderInputsWithConstantOnTheRight() {
3762*795d594fSAndroid Build Coastguard Worker     HInstruction* left = InputAt(0);
3763*795d594fSAndroid Build Coastguard Worker     HInstruction* right = InputAt(1);
3764*795d594fSAndroid Build Coastguard Worker     if (left->IsConstant() && !right->IsConstant()) {
3765*795d594fSAndroid Build Coastguard Worker       ReplaceInput(right, 0);
3766*795d594fSAndroid Build Coastguard Worker       ReplaceInput(left, 1);
3767*795d594fSAndroid Build Coastguard Worker       return true;
3768*795d594fSAndroid Build Coastguard Worker     }
3769*795d594fSAndroid Build Coastguard Worker     return false;
3770*795d594fSAndroid Build Coastguard Worker   }
3771*795d594fSAndroid Build Coastguard Worker 
3772*795d594fSAndroid Build Coastguard Worker   // Order inputs by instruction id, but favor constant on the right side.
3773*795d594fSAndroid Build Coastguard Worker   // This helps GVN for commutative ops.
3774*795d594fSAndroid Build Coastguard Worker   void OrderInputs() {
3775*795d594fSAndroid Build Coastguard Worker     DCHECK(IsCommutative());
3776*795d594fSAndroid Build Coastguard Worker     HInstruction* left = InputAt(0);
3777*795d594fSAndroid Build Coastguard Worker     HInstruction* right = InputAt(1);
3778*795d594fSAndroid Build Coastguard Worker     if (left == right || (!left->IsConstant() && right->IsConstant())) {
3779*795d594fSAndroid Build Coastguard Worker       return;
3780*795d594fSAndroid Build Coastguard Worker     }
3781*795d594fSAndroid Build Coastguard Worker     if (OrderInputsWithConstantOnTheRight()) {
3782*795d594fSAndroid Build Coastguard Worker       return;
3783*795d594fSAndroid Build Coastguard Worker     }
3784*795d594fSAndroid Build Coastguard Worker     // Order according to instruction id.
3785*795d594fSAndroid Build Coastguard Worker     if (left->GetId() > right->GetId()) {
3786*795d594fSAndroid Build Coastguard Worker       ReplaceInput(right, 0);
3787*795d594fSAndroid Build Coastguard Worker       ReplaceInput(left, 1);
3788*795d594fSAndroid Build Coastguard Worker     }
3789*795d594fSAndroid Build Coastguard Worker   }
3790*795d594fSAndroid Build Coastguard Worker 
3791*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
3792*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
3793*795d594fSAndroid Build Coastguard Worker     return true;
3794*795d594fSAndroid Build Coastguard Worker   }
3795*795d594fSAndroid Build Coastguard Worker 
3796*795d594fSAndroid Build Coastguard Worker   // Try to statically evaluate `this` and return a HConstant
3797*795d594fSAndroid Build Coastguard Worker   // containing the result of this evaluation.  If `this` cannot
3798*795d594fSAndroid Build Coastguard Worker   // be evaluated as a constant, return null.
3799*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation() const;
3800*795d594fSAndroid Build Coastguard Worker 
3801*795d594fSAndroid Build Coastguard Worker   // Same but for `left` and `right` instead of GetLeft() and GetRight().
3802*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation(HInstruction* left, HInstruction* right) const;
3803*795d594fSAndroid Build Coastguard Worker 
3804*795d594fSAndroid Build Coastguard Worker   // Apply this operation to `x` and `y`.
3805*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
3806*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HNullConstant* y) const {
3807*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for the (null, null) case.";
3808*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3809*795d594fSAndroid Build Coastguard Worker   }
3810*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HIntConstant* x,
3811*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HIntConstant* y) const {
3812*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for the (int, int) case.";
3813*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3814*795d594fSAndroid Build Coastguard Worker   }
3815*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HLongConstant* x,
3816*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HLongConstant* y) const {
3817*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for the (long, long) case.";
3818*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3819*795d594fSAndroid Build Coastguard Worker   }
3820*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HLongConstant* x,
3821*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HIntConstant* y) const {
3822*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for the (long, int) case.";
3823*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3824*795d594fSAndroid Build Coastguard Worker   }
3825*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
3826*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HFloatConstant* y) const {
3827*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for float values";
3828*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3829*795d594fSAndroid Build Coastguard Worker   }
3830*795d594fSAndroid Build Coastguard Worker   virtual HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
3831*795d594fSAndroid Build Coastguard Worker                               [[maybe_unused]] HDoubleConstant* y) const {
3832*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << DebugName() << " is not defined for double values";
3833*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
3834*795d594fSAndroid Build Coastguard Worker   }
3835*795d594fSAndroid Build Coastguard Worker 
3836*795d594fSAndroid Build Coastguard Worker   // Returns an input that can legally be used as the right input and is
3837*795d594fSAndroid Build Coastguard Worker   // constant, or null.
3838*795d594fSAndroid Build Coastguard Worker   HConstant* GetConstantRight() const;
3839*795d594fSAndroid Build Coastguard Worker 
3840*795d594fSAndroid Build Coastguard Worker   // If `GetConstantRight()` returns one of the input, this returns the other
3841*795d594fSAndroid Build Coastguard Worker   // one. Otherwise it returns null.
3842*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLeastConstantLeft() const;
3843*795d594fSAndroid Build Coastguard Worker 
3844*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation);
3845*795d594fSAndroid Build Coastguard Worker 
3846*795d594fSAndroid Build Coastguard Worker  protected:
3847*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BinaryOperation);
3848*795d594fSAndroid Build Coastguard Worker };
3849*795d594fSAndroid Build Coastguard Worker 
3850*795d594fSAndroid Build Coastguard Worker // The comparison bias applies for floating point operations and indicates how NaN
3851*795d594fSAndroid Build Coastguard Worker // comparisons are treated:
3852*795d594fSAndroid Build Coastguard Worker enum class ComparisonBias {  // private marker to avoid generate-operator-out.py from processing.
3853*795d594fSAndroid Build Coastguard Worker   kNoBias,  // bias is not applicable (i.e. for long operation)
3854*795d594fSAndroid Build Coastguard Worker   kGtBias,  // return 1 for NaN comparisons
3855*795d594fSAndroid Build Coastguard Worker   kLtBias,  // return -1 for NaN comparisons
3856*795d594fSAndroid Build Coastguard Worker   kLast = kLtBias
3857*795d594fSAndroid Build Coastguard Worker };
3858*795d594fSAndroid Build Coastguard Worker 
3859*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, ComparisonBias rhs);
3860*795d594fSAndroid Build Coastguard Worker 
3861*795d594fSAndroid Build Coastguard Worker class HCondition : public HBinaryOperation {
3862*795d594fSAndroid Build Coastguard Worker  public:
3863*795d594fSAndroid Build Coastguard Worker   HCondition(InstructionKind kind,
3864*795d594fSAndroid Build Coastguard Worker              HInstruction* first,
3865*795d594fSAndroid Build Coastguard Worker              HInstruction* second,
3866*795d594fSAndroid Build Coastguard Worker              uint32_t dex_pc = kNoDexPc)
3867*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kind,
3868*795d594fSAndroid Build Coastguard Worker                          DataType::Type::kBool,
3869*795d594fSAndroid Build Coastguard Worker                          first,
3870*795d594fSAndroid Build Coastguard Worker                          second,
3871*795d594fSAndroid Build Coastguard Worker                          SideEffects::None(),
3872*795d594fSAndroid Build Coastguard Worker                          dex_pc) {
3873*795d594fSAndroid Build Coastguard Worker     SetPackedField<ComparisonBiasField>(ComparisonBias::kNoBias);
3874*795d594fSAndroid Build Coastguard Worker   }
3875*795d594fSAndroid Build Coastguard Worker 
3876*795d594fSAndroid Build Coastguard Worker   static HCondition* Create(HGraph* graph,
3877*795d594fSAndroid Build Coastguard Worker                             IfCondition cond,
3878*795d594fSAndroid Build Coastguard Worker                             HInstruction* lhs,
3879*795d594fSAndroid Build Coastguard Worker                             HInstruction* rhs,
3880*795d594fSAndroid Build Coastguard Worker                             uint32_t dex_pc = kNoDexPc);
3881*795d594fSAndroid Build Coastguard Worker 
3882*795d594fSAndroid Build Coastguard Worker   // For code generation purposes, returns whether this instruction is just before
3883*795d594fSAndroid Build Coastguard Worker   // `instruction`, and disregard moves in between.
3884*795d594fSAndroid Build Coastguard Worker   bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
3885*795d594fSAndroid Build Coastguard Worker 
3886*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(Condition);
3887*795d594fSAndroid Build Coastguard Worker 
3888*795d594fSAndroid Build Coastguard Worker   virtual IfCondition GetCondition() const = 0;
3889*795d594fSAndroid Build Coastguard Worker 
3890*795d594fSAndroid Build Coastguard Worker   virtual IfCondition GetOppositeCondition() const = 0;
3891*795d594fSAndroid Build Coastguard Worker 
3892*795d594fSAndroid Build Coastguard Worker   bool IsGtBias() const { return GetBias() == ComparisonBias::kGtBias; }
3893*795d594fSAndroid Build Coastguard Worker   bool IsLtBias() const { return GetBias() == ComparisonBias::kLtBias; }
3894*795d594fSAndroid Build Coastguard Worker 
3895*795d594fSAndroid Build Coastguard Worker   ComparisonBias GetBias() const { return GetPackedField<ComparisonBiasField>(); }
3896*795d594fSAndroid Build Coastguard Worker   void SetBias(ComparisonBias bias) { SetPackedField<ComparisonBiasField>(bias); }
3897*795d594fSAndroid Build Coastguard Worker 
3898*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
3899*795d594fSAndroid Build Coastguard Worker     return GetPackedFields() == other->AsCondition()->GetPackedFields();
3900*795d594fSAndroid Build Coastguard Worker   }
3901*795d594fSAndroid Build Coastguard Worker 
3902*795d594fSAndroid Build Coastguard Worker   bool IsFPConditionTrueIfNaN() const {
3903*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3904*795d594fSAndroid Build Coastguard Worker     IfCondition if_cond = GetCondition();
3905*795d594fSAndroid Build Coastguard Worker     if (if_cond == kCondNE) {
3906*795d594fSAndroid Build Coastguard Worker       return true;
3907*795d594fSAndroid Build Coastguard Worker     } else if (if_cond == kCondEQ) {
3908*795d594fSAndroid Build Coastguard Worker       return false;
3909*795d594fSAndroid Build Coastguard Worker     }
3910*795d594fSAndroid Build Coastguard Worker     return ((if_cond == kCondGT) || (if_cond == kCondGE)) && IsGtBias();
3911*795d594fSAndroid Build Coastguard Worker   }
3912*795d594fSAndroid Build Coastguard Worker 
3913*795d594fSAndroid Build Coastguard Worker   bool IsFPConditionFalseIfNaN() const {
3914*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3915*795d594fSAndroid Build Coastguard Worker     IfCondition if_cond = GetCondition();
3916*795d594fSAndroid Build Coastguard Worker     if (if_cond == kCondEQ) {
3917*795d594fSAndroid Build Coastguard Worker       return true;
3918*795d594fSAndroid Build Coastguard Worker     } else if (if_cond == kCondNE) {
3919*795d594fSAndroid Build Coastguard Worker       return false;
3920*795d594fSAndroid Build Coastguard Worker     }
3921*795d594fSAndroid Build Coastguard Worker     return ((if_cond == kCondLT) || (if_cond == kCondLE)) && IsGtBias();
3922*795d594fSAndroid Build Coastguard Worker   }
3923*795d594fSAndroid Build Coastguard Worker 
3924*795d594fSAndroid Build Coastguard Worker  protected:
3925*795d594fSAndroid Build Coastguard Worker   // Needed if we merge a HCompare into a HCondition.
3926*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonBias = kNumberOfGenericPackedBits;
3927*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonBiasSize =
3928*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
3929*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfConditionPackedBits =
3930*795d594fSAndroid Build Coastguard Worker       kFieldComparisonBias + kFieldComparisonBiasSize;
3931*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfConditionPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
3932*795d594fSAndroid Build Coastguard Worker   using ComparisonBiasField =
3933*795d594fSAndroid Build Coastguard Worker       BitField<ComparisonBias, kFieldComparisonBias, kFieldComparisonBiasSize>;
3934*795d594fSAndroid Build Coastguard Worker 
3935*795d594fSAndroid Build Coastguard Worker   template <typename T>
3936*795d594fSAndroid Build Coastguard Worker   int32_t Compare(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
3937*795d594fSAndroid Build Coastguard Worker 
3938*795d594fSAndroid Build Coastguard Worker   template <typename T>
3939*795d594fSAndroid Build Coastguard Worker   int32_t CompareFP(T x, T y) const {
3940*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
3941*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
3942*795d594fSAndroid Build Coastguard Worker     // Handle the bias.
3943*795d594fSAndroid Build Coastguard Worker     return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compare(x, y);
3944*795d594fSAndroid Build Coastguard Worker   }
3945*795d594fSAndroid Build Coastguard Worker 
3946*795d594fSAndroid Build Coastguard Worker   // Return an integer constant containing the result of a condition evaluated at compile time.
3947*795d594fSAndroid Build Coastguard Worker   HIntConstant* MakeConstantCondition(bool value) const {
3948*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(value);
3949*795d594fSAndroid Build Coastguard Worker   }
3950*795d594fSAndroid Build Coastguard Worker 
3951*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Condition);
3952*795d594fSAndroid Build Coastguard Worker };
3953*795d594fSAndroid Build Coastguard Worker 
3954*795d594fSAndroid Build Coastguard Worker // Instruction to check if two inputs are equal to each other.
3955*795d594fSAndroid Build Coastguard Worker class HEqual final : public HCondition {
3956*795d594fSAndroid Build Coastguard Worker  public:
3957*795d594fSAndroid Build Coastguard Worker   HEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
3958*795d594fSAndroid Build Coastguard Worker       : HCondition(kEqual, first, second, dex_pc) {
3959*795d594fSAndroid Build Coastguard Worker   }
3960*795d594fSAndroid Build Coastguard Worker 
3961*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
3962*795d594fSAndroid Build Coastguard Worker 
3963*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
3964*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HNullConstant* y) const override {
3965*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(true);
3966*795d594fSAndroid Build Coastguard Worker   }
3967*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
3968*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
3969*795d594fSAndroid Build Coastguard Worker   }
3970*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
3971*795d594fSAndroid Build Coastguard Worker   // been merged into this HEqual instruction; evaluate it as
3972*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) == 0`.
3973*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
3974*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
3975*795d594fSAndroid Build Coastguard Worker   }
3976*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
3977*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
3978*795d594fSAndroid Build Coastguard Worker   }
3979*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
3980*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
3981*795d594fSAndroid Build Coastguard Worker   }
3982*795d594fSAndroid Build Coastguard Worker 
3983*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Equal);
3984*795d594fSAndroid Build Coastguard Worker 
3985*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
3986*795d594fSAndroid Build Coastguard Worker     return kCondEQ;
3987*795d594fSAndroid Build Coastguard Worker   }
3988*795d594fSAndroid Build Coastguard Worker 
3989*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
3990*795d594fSAndroid Build Coastguard Worker     return kCondNE;
3991*795d594fSAndroid Build Coastguard Worker   }
3992*795d594fSAndroid Build Coastguard Worker 
3993*795d594fSAndroid Build Coastguard Worker  protected:
3994*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Equal);
3995*795d594fSAndroid Build Coastguard Worker 
3996*795d594fSAndroid Build Coastguard Worker  private:
3997*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x == y; }
3998*795d594fSAndroid Build Coastguard Worker };
3999*795d594fSAndroid Build Coastguard Worker 
4000*795d594fSAndroid Build Coastguard Worker class HNotEqual final : public HCondition {
4001*795d594fSAndroid Build Coastguard Worker  public:
4002*795d594fSAndroid Build Coastguard Worker   HNotEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4003*795d594fSAndroid Build Coastguard Worker       : HCondition(kNotEqual, first, second, dex_pc) {
4004*795d594fSAndroid Build Coastguard Worker   }
4005*795d594fSAndroid Build Coastguard Worker 
4006*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
4007*795d594fSAndroid Build Coastguard Worker 
4008*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HNullConstant* x,
4009*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HNullConstant* y) const override {
4010*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(false);
4011*795d594fSAndroid Build Coastguard Worker   }
4012*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4013*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4014*795d594fSAndroid Build Coastguard Worker   }
4015*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
4016*795d594fSAndroid Build Coastguard Worker   // been merged into this HNotEqual instruction; evaluate it as
4017*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) != 0`.
4018*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4019*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
4020*795d594fSAndroid Build Coastguard Worker   }
4021*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4022*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4023*795d594fSAndroid Build Coastguard Worker   }
4024*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4025*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4026*795d594fSAndroid Build Coastguard Worker   }
4027*795d594fSAndroid Build Coastguard Worker 
4028*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(NotEqual);
4029*795d594fSAndroid Build Coastguard Worker 
4030*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4031*795d594fSAndroid Build Coastguard Worker     return kCondNE;
4032*795d594fSAndroid Build Coastguard Worker   }
4033*795d594fSAndroid Build Coastguard Worker 
4034*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4035*795d594fSAndroid Build Coastguard Worker     return kCondEQ;
4036*795d594fSAndroid Build Coastguard Worker   }
4037*795d594fSAndroid Build Coastguard Worker 
4038*795d594fSAndroid Build Coastguard Worker  protected:
4039*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(NotEqual);
4040*795d594fSAndroid Build Coastguard Worker 
4041*795d594fSAndroid Build Coastguard Worker  private:
4042*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x != y; }
4043*795d594fSAndroid Build Coastguard Worker };
4044*795d594fSAndroid Build Coastguard Worker 
4045*795d594fSAndroid Build Coastguard Worker class HLessThan final : public HCondition {
4046*795d594fSAndroid Build Coastguard Worker  public:
4047*795d594fSAndroid Build Coastguard Worker   HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4048*795d594fSAndroid Build Coastguard Worker       : HCondition(kLessThan, first, second, dex_pc) {
4049*795d594fSAndroid Build Coastguard Worker   }
4050*795d594fSAndroid Build Coastguard Worker 
4051*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4052*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4053*795d594fSAndroid Build Coastguard Worker   }
4054*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
4055*795d594fSAndroid Build Coastguard Worker   // been merged into this HLessThan instruction; evaluate it as
4056*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) < 0`.
4057*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4058*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
4059*795d594fSAndroid Build Coastguard Worker   }
4060*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4061*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4062*795d594fSAndroid Build Coastguard Worker   }
4063*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4064*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4065*795d594fSAndroid Build Coastguard Worker   }
4066*795d594fSAndroid Build Coastguard Worker 
4067*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LessThan);
4068*795d594fSAndroid Build Coastguard Worker 
4069*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4070*795d594fSAndroid Build Coastguard Worker     return kCondLT;
4071*795d594fSAndroid Build Coastguard Worker   }
4072*795d594fSAndroid Build Coastguard Worker 
4073*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4074*795d594fSAndroid Build Coastguard Worker     return kCondGE;
4075*795d594fSAndroid Build Coastguard Worker   }
4076*795d594fSAndroid Build Coastguard Worker 
4077*795d594fSAndroid Build Coastguard Worker  protected:
4078*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LessThan);
4079*795d594fSAndroid Build Coastguard Worker 
4080*795d594fSAndroid Build Coastguard Worker  private:
4081*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x < y; }
4082*795d594fSAndroid Build Coastguard Worker };
4083*795d594fSAndroid Build Coastguard Worker 
4084*795d594fSAndroid Build Coastguard Worker class HLessThanOrEqual final : public HCondition {
4085*795d594fSAndroid Build Coastguard Worker  public:
4086*795d594fSAndroid Build Coastguard Worker   HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4087*795d594fSAndroid Build Coastguard Worker       : HCondition(kLessThanOrEqual, first, second, dex_pc) {
4088*795d594fSAndroid Build Coastguard Worker   }
4089*795d594fSAndroid Build Coastguard Worker 
4090*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4091*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4092*795d594fSAndroid Build Coastguard Worker   }
4093*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
4094*795d594fSAndroid Build Coastguard Worker   // been merged into this HLessThanOrEqual instruction; evaluate it as
4095*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) <= 0`.
4096*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4097*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
4098*795d594fSAndroid Build Coastguard Worker   }
4099*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4100*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4101*795d594fSAndroid Build Coastguard Worker   }
4102*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4103*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4104*795d594fSAndroid Build Coastguard Worker   }
4105*795d594fSAndroid Build Coastguard Worker 
4106*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LessThanOrEqual);
4107*795d594fSAndroid Build Coastguard Worker 
4108*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4109*795d594fSAndroid Build Coastguard Worker     return kCondLE;
4110*795d594fSAndroid Build Coastguard Worker   }
4111*795d594fSAndroid Build Coastguard Worker 
4112*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4113*795d594fSAndroid Build Coastguard Worker     return kCondGT;
4114*795d594fSAndroid Build Coastguard Worker   }
4115*795d594fSAndroid Build Coastguard Worker 
4116*795d594fSAndroid Build Coastguard Worker  protected:
4117*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LessThanOrEqual);
4118*795d594fSAndroid Build Coastguard Worker 
4119*795d594fSAndroid Build Coastguard Worker  private:
4120*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x <= y; }
4121*795d594fSAndroid Build Coastguard Worker };
4122*795d594fSAndroid Build Coastguard Worker 
4123*795d594fSAndroid Build Coastguard Worker class HGreaterThan final : public HCondition {
4124*795d594fSAndroid Build Coastguard Worker  public:
4125*795d594fSAndroid Build Coastguard Worker   HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4126*795d594fSAndroid Build Coastguard Worker       : HCondition(kGreaterThan, first, second, dex_pc) {
4127*795d594fSAndroid Build Coastguard Worker   }
4128*795d594fSAndroid Build Coastguard Worker 
4129*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4130*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4131*795d594fSAndroid Build Coastguard Worker   }
4132*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
4133*795d594fSAndroid Build Coastguard Worker   // been merged into this HGreaterThan instruction; evaluate it as
4134*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) > 0`.
4135*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4136*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
4137*795d594fSAndroid Build Coastguard Worker   }
4138*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4139*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4140*795d594fSAndroid Build Coastguard Worker   }
4141*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4142*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4143*795d594fSAndroid Build Coastguard Worker   }
4144*795d594fSAndroid Build Coastguard Worker 
4145*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(GreaterThan);
4146*795d594fSAndroid Build Coastguard Worker 
4147*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4148*795d594fSAndroid Build Coastguard Worker     return kCondGT;
4149*795d594fSAndroid Build Coastguard Worker   }
4150*795d594fSAndroid Build Coastguard Worker 
4151*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4152*795d594fSAndroid Build Coastguard Worker     return kCondLE;
4153*795d594fSAndroid Build Coastguard Worker   }
4154*795d594fSAndroid Build Coastguard Worker 
4155*795d594fSAndroid Build Coastguard Worker  protected:
4156*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(GreaterThan);
4157*795d594fSAndroid Build Coastguard Worker 
4158*795d594fSAndroid Build Coastguard Worker  private:
4159*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x > y; }
4160*795d594fSAndroid Build Coastguard Worker };
4161*795d594fSAndroid Build Coastguard Worker 
4162*795d594fSAndroid Build Coastguard Worker class HGreaterThanOrEqual final : public HCondition {
4163*795d594fSAndroid Build Coastguard Worker  public:
4164*795d594fSAndroid Build Coastguard Worker   HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4165*795d594fSAndroid Build Coastguard Worker       : HCondition(kGreaterThanOrEqual, first, second, dex_pc) {
4166*795d594fSAndroid Build Coastguard Worker   }
4167*795d594fSAndroid Build Coastguard Worker 
4168*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4169*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4170*795d594fSAndroid Build Coastguard Worker   }
4171*795d594fSAndroid Build Coastguard Worker   // In the following Evaluate methods, a HCompare instruction has
4172*795d594fSAndroid Build Coastguard Worker   // been merged into this HGreaterThanOrEqual instruction; evaluate it as
4173*795d594fSAndroid Build Coastguard Worker   // `Compare(x, y) >= 0`.
4174*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4175*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(Compare(x->GetValue(), y->GetValue()), 0));
4176*795d594fSAndroid Build Coastguard Worker   }
4177*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4178*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4179*795d594fSAndroid Build Coastguard Worker   }
4180*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4181*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(CompareFP(x->GetValue(), y->GetValue()), 0));
4182*795d594fSAndroid Build Coastguard Worker   }
4183*795d594fSAndroid Build Coastguard Worker 
4184*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(GreaterThanOrEqual);
4185*795d594fSAndroid Build Coastguard Worker 
4186*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4187*795d594fSAndroid Build Coastguard Worker     return kCondGE;
4188*795d594fSAndroid Build Coastguard Worker   }
4189*795d594fSAndroid Build Coastguard Worker 
4190*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4191*795d594fSAndroid Build Coastguard Worker     return kCondLT;
4192*795d594fSAndroid Build Coastguard Worker   }
4193*795d594fSAndroid Build Coastguard Worker 
4194*795d594fSAndroid Build Coastguard Worker  protected:
4195*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(GreaterThanOrEqual);
4196*795d594fSAndroid Build Coastguard Worker 
4197*795d594fSAndroid Build Coastguard Worker  private:
4198*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) { return x >= y; }
4199*795d594fSAndroid Build Coastguard Worker };
4200*795d594fSAndroid Build Coastguard Worker 
4201*795d594fSAndroid Build Coastguard Worker class HBelow final : public HCondition {
4202*795d594fSAndroid Build Coastguard Worker  public:
4203*795d594fSAndroid Build Coastguard Worker   HBelow(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4204*795d594fSAndroid Build Coastguard Worker       : HCondition(kBelow, first, second, dex_pc) {
4205*795d594fSAndroid Build Coastguard Worker   }
4206*795d594fSAndroid Build Coastguard Worker 
4207*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4208*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4209*795d594fSAndroid Build Coastguard Worker   }
4210*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4211*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4212*795d594fSAndroid Build Coastguard Worker   }
4213*795d594fSAndroid Build Coastguard Worker 
4214*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Below);
4215*795d594fSAndroid Build Coastguard Worker 
4216*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4217*795d594fSAndroid Build Coastguard Worker     return kCondB;
4218*795d594fSAndroid Build Coastguard Worker   }
4219*795d594fSAndroid Build Coastguard Worker 
4220*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4221*795d594fSAndroid Build Coastguard Worker     return kCondAE;
4222*795d594fSAndroid Build Coastguard Worker   }
4223*795d594fSAndroid Build Coastguard Worker 
4224*795d594fSAndroid Build Coastguard Worker  protected:
4225*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Below);
4226*795d594fSAndroid Build Coastguard Worker 
4227*795d594fSAndroid Build Coastguard Worker  private:
4228*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) {
4229*795d594fSAndroid Build Coastguard Worker     return MakeUnsigned(x) < MakeUnsigned(y);
4230*795d594fSAndroid Build Coastguard Worker   }
4231*795d594fSAndroid Build Coastguard Worker };
4232*795d594fSAndroid Build Coastguard Worker 
4233*795d594fSAndroid Build Coastguard Worker class HBelowOrEqual final : public HCondition {
4234*795d594fSAndroid Build Coastguard Worker  public:
4235*795d594fSAndroid Build Coastguard Worker   HBelowOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4236*795d594fSAndroid Build Coastguard Worker       : HCondition(kBelowOrEqual, first, second, dex_pc) {
4237*795d594fSAndroid Build Coastguard Worker   }
4238*795d594fSAndroid Build Coastguard Worker 
4239*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4240*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4241*795d594fSAndroid Build Coastguard Worker   }
4242*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4243*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4244*795d594fSAndroid Build Coastguard Worker   }
4245*795d594fSAndroid Build Coastguard Worker 
4246*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(BelowOrEqual);
4247*795d594fSAndroid Build Coastguard Worker 
4248*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4249*795d594fSAndroid Build Coastguard Worker     return kCondBE;
4250*795d594fSAndroid Build Coastguard Worker   }
4251*795d594fSAndroid Build Coastguard Worker 
4252*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4253*795d594fSAndroid Build Coastguard Worker     return kCondA;
4254*795d594fSAndroid Build Coastguard Worker   }
4255*795d594fSAndroid Build Coastguard Worker 
4256*795d594fSAndroid Build Coastguard Worker  protected:
4257*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BelowOrEqual);
4258*795d594fSAndroid Build Coastguard Worker 
4259*795d594fSAndroid Build Coastguard Worker  private:
4260*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) {
4261*795d594fSAndroid Build Coastguard Worker     return MakeUnsigned(x) <= MakeUnsigned(y);
4262*795d594fSAndroid Build Coastguard Worker   }
4263*795d594fSAndroid Build Coastguard Worker };
4264*795d594fSAndroid Build Coastguard Worker 
4265*795d594fSAndroid Build Coastguard Worker class HAbove final : public HCondition {
4266*795d594fSAndroid Build Coastguard Worker  public:
4267*795d594fSAndroid Build Coastguard Worker   HAbove(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4268*795d594fSAndroid Build Coastguard Worker       : HCondition(kAbove, first, second, dex_pc) {
4269*795d594fSAndroid Build Coastguard Worker   }
4270*795d594fSAndroid Build Coastguard Worker 
4271*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4272*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4273*795d594fSAndroid Build Coastguard Worker   }
4274*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4275*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4276*795d594fSAndroid Build Coastguard Worker   }
4277*795d594fSAndroid Build Coastguard Worker 
4278*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Above);
4279*795d594fSAndroid Build Coastguard Worker 
4280*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4281*795d594fSAndroid Build Coastguard Worker     return kCondA;
4282*795d594fSAndroid Build Coastguard Worker   }
4283*795d594fSAndroid Build Coastguard Worker 
4284*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4285*795d594fSAndroid Build Coastguard Worker     return kCondBE;
4286*795d594fSAndroid Build Coastguard Worker   }
4287*795d594fSAndroid Build Coastguard Worker 
4288*795d594fSAndroid Build Coastguard Worker  protected:
4289*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Above);
4290*795d594fSAndroid Build Coastguard Worker 
4291*795d594fSAndroid Build Coastguard Worker  private:
4292*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) {
4293*795d594fSAndroid Build Coastguard Worker     return MakeUnsigned(x) > MakeUnsigned(y);
4294*795d594fSAndroid Build Coastguard Worker   }
4295*795d594fSAndroid Build Coastguard Worker };
4296*795d594fSAndroid Build Coastguard Worker 
4297*795d594fSAndroid Build Coastguard Worker class HAboveOrEqual final : public HCondition {
4298*795d594fSAndroid Build Coastguard Worker  public:
4299*795d594fSAndroid Build Coastguard Worker   HAboveOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
4300*795d594fSAndroid Build Coastguard Worker       : HCondition(kAboveOrEqual, first, second, dex_pc) {
4301*795d594fSAndroid Build Coastguard Worker   }
4302*795d594fSAndroid Build Coastguard Worker 
4303*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4304*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4305*795d594fSAndroid Build Coastguard Worker   }
4306*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4307*795d594fSAndroid Build Coastguard Worker     return MakeConstantCondition(Compute(x->GetValue(), y->GetValue()));
4308*795d594fSAndroid Build Coastguard Worker   }
4309*795d594fSAndroid Build Coastguard Worker 
4310*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(AboveOrEqual);
4311*795d594fSAndroid Build Coastguard Worker 
4312*795d594fSAndroid Build Coastguard Worker   IfCondition GetCondition() const override {
4313*795d594fSAndroid Build Coastguard Worker     return kCondAE;
4314*795d594fSAndroid Build Coastguard Worker   }
4315*795d594fSAndroid Build Coastguard Worker 
4316*795d594fSAndroid Build Coastguard Worker   IfCondition GetOppositeCondition() const override {
4317*795d594fSAndroid Build Coastguard Worker     return kCondB;
4318*795d594fSAndroid Build Coastguard Worker   }
4319*795d594fSAndroid Build Coastguard Worker 
4320*795d594fSAndroid Build Coastguard Worker  protected:
4321*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(AboveOrEqual);
4322*795d594fSAndroid Build Coastguard Worker 
4323*795d594fSAndroid Build Coastguard Worker  private:
4324*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x, T y) {
4325*795d594fSAndroid Build Coastguard Worker     return MakeUnsigned(x) >= MakeUnsigned(y);
4326*795d594fSAndroid Build Coastguard Worker   }
4327*795d594fSAndroid Build Coastguard Worker };
4328*795d594fSAndroid Build Coastguard Worker 
4329*795d594fSAndroid Build Coastguard Worker // Instruction to check how two inputs compare to each other.
4330*795d594fSAndroid Build Coastguard Worker // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
4331*795d594fSAndroid Build Coastguard Worker class HCompare final : public HBinaryOperation {
4332*795d594fSAndroid Build Coastguard Worker  public:
4333*795d594fSAndroid Build Coastguard Worker   // Note that `comparison_type` is the type of comparison performed
4334*795d594fSAndroid Build Coastguard Worker   // between the comparison's inputs, not the type of the instantiated
4335*795d594fSAndroid Build Coastguard Worker   // HCompare instruction (which is always DataType::Type::kInt).
4336*795d594fSAndroid Build Coastguard Worker   HCompare(DataType::Type comparison_type,
4337*795d594fSAndroid Build Coastguard Worker            HInstruction* first,
4338*795d594fSAndroid Build Coastguard Worker            HInstruction* second,
4339*795d594fSAndroid Build Coastguard Worker            ComparisonBias bias,
4340*795d594fSAndroid Build Coastguard Worker            uint32_t dex_pc)
4341*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kCompare,
4342*795d594fSAndroid Build Coastguard Worker                          DataType::Type::kInt32,
4343*795d594fSAndroid Build Coastguard Worker                          first,
4344*795d594fSAndroid Build Coastguard Worker                          second,
4345*795d594fSAndroid Build Coastguard Worker                          SideEffectsForArchRuntimeCalls(comparison_type),
4346*795d594fSAndroid Build Coastguard Worker                          dex_pc) {
4347*795d594fSAndroid Build Coastguard Worker     SetPackedField<ComparisonBiasField>(bias);
4348*795d594fSAndroid Build Coastguard Worker     SetPackedField<ComparisonTypeField>(comparison_type);
4349*795d594fSAndroid Build Coastguard Worker   }
4350*795d594fSAndroid Build Coastguard Worker 
4351*795d594fSAndroid Build Coastguard Worker   template <typename T>
4352*795d594fSAndroid Build Coastguard Worker   int32_t Compute(T x, T y) const { return x > y ? 1 : (x < y ? -1 : 0); }
4353*795d594fSAndroid Build Coastguard Worker 
4354*795d594fSAndroid Build Coastguard Worker   template <typename T>
4355*795d594fSAndroid Build Coastguard Worker   int32_t ComputeFP(T x, T y) const {
4356*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
4357*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(GetBias(), ComparisonBias::kNoBias);
4358*795d594fSAndroid Build Coastguard Worker     // Handle the bias.
4359*795d594fSAndroid Build Coastguard Worker     return std::isunordered(x, y) ? (IsGtBias() ? 1 : -1) : Compute(x, y);
4360*795d594fSAndroid Build Coastguard Worker   }
4361*795d594fSAndroid Build Coastguard Worker 
4362*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
4363*795d594fSAndroid Build Coastguard Worker     // Note that there is no "cmp-int" Dex instruction so we shouldn't
4364*795d594fSAndroid Build Coastguard Worker     // reach this code path when processing a freshly built HIR
4365*795d594fSAndroid Build Coastguard Worker     // graph. However HCompare integer instructions can be synthesized
4366*795d594fSAndroid Build Coastguard Worker     // by the instruction simplifier to implement IntegerCompare and
4367*795d594fSAndroid Build Coastguard Worker     // IntegerSignum intrinsics, so we have to handle this case.
4368*795d594fSAndroid Build Coastguard Worker     const int32_t value = DataType::IsUnsignedType(GetComparisonType()) ?
4369*795d594fSAndroid Build Coastguard Worker         Compute(x->GetValueAsUint64(), y->GetValueAsUint64()) :
4370*795d594fSAndroid Build Coastguard Worker         Compute(x->GetValue(), y->GetValue());
4371*795d594fSAndroid Build Coastguard Worker     return MakeConstantComparison(value);
4372*795d594fSAndroid Build Coastguard Worker   }
4373*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
4374*795d594fSAndroid Build Coastguard Worker     const int32_t value = DataType::IsUnsignedType(GetComparisonType()) ?
4375*795d594fSAndroid Build Coastguard Worker         Compute(x->GetValueAsUint64(), y->GetValueAsUint64()) :
4376*795d594fSAndroid Build Coastguard Worker         Compute(x->GetValue(), y->GetValue());
4377*795d594fSAndroid Build Coastguard Worker     return MakeConstantComparison(value);
4378*795d594fSAndroid Build Coastguard Worker   }
4379*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
4380*795d594fSAndroid Build Coastguard Worker     return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()));
4381*795d594fSAndroid Build Coastguard Worker   }
4382*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
4383*795d594fSAndroid Build Coastguard Worker     return MakeConstantComparison(ComputeFP(x->GetValue(), y->GetValue()));
4384*795d594fSAndroid Build Coastguard Worker   }
4385*795d594fSAndroid Build Coastguard Worker 
4386*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
4387*795d594fSAndroid Build Coastguard Worker     return GetPackedFields() == other->AsCompare()->GetPackedFields();
4388*795d594fSAndroid Build Coastguard Worker   }
4389*795d594fSAndroid Build Coastguard Worker 
4390*795d594fSAndroid Build Coastguard Worker   ComparisonBias GetBias() const { return GetPackedField<ComparisonBiasField>(); }
4391*795d594fSAndroid Build Coastguard Worker 
4392*795d594fSAndroid Build Coastguard Worker   DataType::Type GetComparisonType() const { return GetPackedField<ComparisonTypeField>(); }
4393*795d594fSAndroid Build Coastguard Worker 
4394*795d594fSAndroid Build Coastguard Worker   void SetComparisonType(DataType::Type newType) { SetPackedField<ComparisonTypeField>(newType); }
4395*795d594fSAndroid Build Coastguard Worker 
4396*795d594fSAndroid Build Coastguard Worker   // Does this compare instruction have a "gt bias" (vs an "lt bias")?
4397*795d594fSAndroid Build Coastguard Worker   // Only meaningful for floating-point comparisons.
4398*795d594fSAndroid Build Coastguard Worker   bool IsGtBias() const {
4399*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(InputAt(0)->GetType())) << InputAt(0)->GetType();
4400*795d594fSAndroid Build Coastguard Worker     return GetBias() == ComparisonBias::kGtBias;
4401*795d594fSAndroid Build Coastguard Worker   }
4402*795d594fSAndroid Build Coastguard Worker 
4403*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls([[maybe_unused]] DataType::Type type) {
4404*795d594fSAndroid Build Coastguard Worker     // Comparisons do not require a runtime call in any back end.
4405*795d594fSAndroid Build Coastguard Worker     return SideEffects::None();
4406*795d594fSAndroid Build Coastguard Worker   }
4407*795d594fSAndroid Build Coastguard Worker 
4408*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Compare);
4409*795d594fSAndroid Build Coastguard Worker 
4410*795d594fSAndroid Build Coastguard Worker  protected:
4411*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonBias = kNumberOfGenericPackedBits;
4412*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonBiasSize =
4413*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(ComparisonBias::kLast));
4414*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonType = kFieldComparisonBias + kFieldComparisonBiasSize;
4415*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComparisonTypeSize =
4416*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
4417*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfComparePackedBits =
4418*795d594fSAndroid Build Coastguard Worker       kFieldComparisonType + kFieldComparisonTypeSize;
4419*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfComparePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
4420*795d594fSAndroid Build Coastguard Worker   using ComparisonBiasField =
4421*795d594fSAndroid Build Coastguard Worker       BitField<ComparisonBias, kFieldComparisonBias, kFieldComparisonBiasSize>;
4422*795d594fSAndroid Build Coastguard Worker   using ComparisonTypeField =
4423*795d594fSAndroid Build Coastguard Worker       BitField<DataType::Type, kFieldComparisonType, kFieldComparisonTypeSize>;
4424*795d594fSAndroid Build Coastguard Worker 
4425*795d594fSAndroid Build Coastguard Worker   // Return an integer constant containing the result of a comparison evaluated at compile time.
4426*795d594fSAndroid Build Coastguard Worker   HIntConstant* MakeConstantComparison(int32_t value) const {
4427*795d594fSAndroid Build Coastguard Worker     DCHECK(value == -1 || value == 0 || value == 1) << value;
4428*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(value);
4429*795d594fSAndroid Build Coastguard Worker   }
4430*795d594fSAndroid Build Coastguard Worker 
4431*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Compare);
4432*795d594fSAndroid Build Coastguard Worker };
4433*795d594fSAndroid Build Coastguard Worker 
4434*795d594fSAndroid Build Coastguard Worker class HNewInstance final : public HExpression<1> {
4435*795d594fSAndroid Build Coastguard Worker  public:
4436*795d594fSAndroid Build Coastguard Worker   HNewInstance(HInstruction* cls,
4437*795d594fSAndroid Build Coastguard Worker                uint32_t dex_pc,
4438*795d594fSAndroid Build Coastguard Worker                dex::TypeIndex type_index,
4439*795d594fSAndroid Build Coastguard Worker                const DexFile& dex_file,
4440*795d594fSAndroid Build Coastguard Worker                bool finalizable,
4441*795d594fSAndroid Build Coastguard Worker                QuickEntrypointEnum entrypoint)
4442*795d594fSAndroid Build Coastguard Worker       : HExpression(kNewInstance,
4443*795d594fSAndroid Build Coastguard Worker                     DataType::Type::kReference,
4444*795d594fSAndroid Build Coastguard Worker                     SideEffects::CanTriggerGC(),
4445*795d594fSAndroid Build Coastguard Worker                     dex_pc),
4446*795d594fSAndroid Build Coastguard Worker         type_index_(type_index),
4447*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file),
4448*795d594fSAndroid Build Coastguard Worker         entrypoint_(entrypoint) {
4449*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagFinalizable>(finalizable);
4450*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagPartialMaterialization>(false);
4451*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cls);
4452*795d594fSAndroid Build Coastguard Worker   }
4453*795d594fSAndroid Build Coastguard Worker 
4454*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
4455*795d594fSAndroid Build Coastguard Worker 
4456*795d594fSAndroid Build Coastguard Worker   void SetPartialMaterialization() {
4457*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagPartialMaterialization>(true);
4458*795d594fSAndroid Build Coastguard Worker   }
4459*795d594fSAndroid Build Coastguard Worker 
4460*795d594fSAndroid Build Coastguard Worker   dex::TypeIndex GetTypeIndex() const { return type_index_; }
4461*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
4462*795d594fSAndroid Build Coastguard Worker 
4463*795d594fSAndroid Build Coastguard Worker   // Calls runtime so needs an environment.
4464*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
4465*795d594fSAndroid Build Coastguard Worker 
4466*795d594fSAndroid Build Coastguard Worker   // Can throw errors when out-of-memory or if it's not instantiable/accessible.
4467*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
4468*795d594fSAndroid Build Coastguard Worker   bool OnlyThrowsAsyncExceptions() const override {
4469*795d594fSAndroid Build Coastguard Worker     return !IsFinalizable() && !NeedsChecks();
4470*795d594fSAndroid Build Coastguard Worker   }
4471*795d594fSAndroid Build Coastguard Worker 
4472*795d594fSAndroid Build Coastguard Worker   bool NeedsChecks() const {
4473*795d594fSAndroid Build Coastguard Worker     return entrypoint_ == kQuickAllocObjectWithChecks;
4474*795d594fSAndroid Build Coastguard Worker   }
4475*795d594fSAndroid Build Coastguard Worker 
4476*795d594fSAndroid Build Coastguard Worker   bool IsFinalizable() const { return GetPackedFlag<kFlagFinalizable>(); }
4477*795d594fSAndroid Build Coastguard Worker 
4478*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
4479*795d594fSAndroid Build Coastguard Worker 
4480*795d594fSAndroid Build Coastguard Worker   bool IsPartialMaterialization() const {
4481*795d594fSAndroid Build Coastguard Worker     return GetPackedFlag<kFlagPartialMaterialization>();
4482*795d594fSAndroid Build Coastguard Worker   }
4483*795d594fSAndroid Build Coastguard Worker 
4484*795d594fSAndroid Build Coastguard Worker   QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
4485*795d594fSAndroid Build Coastguard Worker 
4486*795d594fSAndroid Build Coastguard Worker   void SetEntrypoint(QuickEntrypointEnum entrypoint) {
4487*795d594fSAndroid Build Coastguard Worker     entrypoint_ = entrypoint;
4488*795d594fSAndroid Build Coastguard Worker   }
4489*795d594fSAndroid Build Coastguard Worker 
4490*795d594fSAndroid Build Coastguard Worker   HLoadClass* GetLoadClass() const {
4491*795d594fSAndroid Build Coastguard Worker     HInstruction* input = InputAt(0);
4492*795d594fSAndroid Build Coastguard Worker     if (input->IsClinitCheck()) {
4493*795d594fSAndroid Build Coastguard Worker       input = input->InputAt(0);
4494*795d594fSAndroid Build Coastguard Worker     }
4495*795d594fSAndroid Build Coastguard Worker     DCHECK(input->IsLoadClass());
4496*795d594fSAndroid Build Coastguard Worker     return input->AsLoadClass();
4497*795d594fSAndroid Build Coastguard Worker   }
4498*795d594fSAndroid Build Coastguard Worker 
4499*795d594fSAndroid Build Coastguard Worker   bool IsStringAlloc() const;
4500*795d594fSAndroid Build Coastguard Worker 
4501*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(NewInstance);
4502*795d594fSAndroid Build Coastguard Worker 
4503*795d594fSAndroid Build Coastguard Worker  protected:
4504*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(NewInstance);
4505*795d594fSAndroid Build Coastguard Worker 
4506*795d594fSAndroid Build Coastguard Worker  private:
4507*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagFinalizable = kNumberOfGenericPackedBits;
4508*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagPartialMaterialization = kFlagFinalizable + 1;
4509*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfNewInstancePackedBits = kFlagPartialMaterialization + 1;
4510*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfNewInstancePackedBits <= kMaxNumberOfPackedBits,
4511*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
4512*795d594fSAndroid Build Coastguard Worker 
4513*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex type_index_;
4514*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
4515*795d594fSAndroid Build Coastguard Worker   QuickEntrypointEnum entrypoint_;
4516*795d594fSAndroid Build Coastguard Worker };
4517*795d594fSAndroid Build Coastguard Worker 
4518*795d594fSAndroid Build Coastguard Worker enum IntrinsicNeedsEnvironment {
4519*795d594fSAndroid Build Coastguard Worker   kNoEnvironment,        // Intrinsic does not require an environment.
4520*795d594fSAndroid Build Coastguard Worker   kNeedsEnvironment      // Intrinsic requires an environment.
4521*795d594fSAndroid Build Coastguard Worker };
4522*795d594fSAndroid Build Coastguard Worker 
4523*795d594fSAndroid Build Coastguard Worker enum IntrinsicSideEffects {
4524*795d594fSAndroid Build Coastguard Worker   kNoSideEffects,     // Intrinsic does not have any heap memory side effects.
4525*795d594fSAndroid Build Coastguard Worker   kReadSideEffects,   // Intrinsic may read heap memory.
4526*795d594fSAndroid Build Coastguard Worker   kWriteSideEffects,  // Intrinsic may write heap memory.
4527*795d594fSAndroid Build Coastguard Worker   kAllSideEffects     // Intrinsic may read or write heap memory, or trigger GC.
4528*795d594fSAndroid Build Coastguard Worker };
4529*795d594fSAndroid Build Coastguard Worker 
4530*795d594fSAndroid Build Coastguard Worker enum IntrinsicExceptions {
4531*795d594fSAndroid Build Coastguard Worker   kNoThrow,  // Intrinsic does not throw any exceptions.
4532*795d594fSAndroid Build Coastguard Worker   kCanThrow  // Intrinsic may throw exceptions.
4533*795d594fSAndroid Build Coastguard Worker };
4534*795d594fSAndroid Build Coastguard Worker 
4535*795d594fSAndroid Build Coastguard Worker // Determines how to load an ArtMethod*.
4536*795d594fSAndroid Build Coastguard Worker enum class MethodLoadKind {
4537*795d594fSAndroid Build Coastguard Worker   // Use a String init ArtMethod* loaded from Thread entrypoints.
4538*795d594fSAndroid Build Coastguard Worker   kStringInit,
4539*795d594fSAndroid Build Coastguard Worker 
4540*795d594fSAndroid Build Coastguard Worker   // Use the method's own ArtMethod* loaded by the register allocator.
4541*795d594fSAndroid Build Coastguard Worker   kRecursive,
4542*795d594fSAndroid Build Coastguard Worker 
4543*795d594fSAndroid Build Coastguard Worker   // Use PC-relative boot image ArtMethod* address that will be known at link time.
4544*795d594fSAndroid Build Coastguard Worker   // Used for boot image methods referenced by boot image code.
4545*795d594fSAndroid Build Coastguard Worker   kBootImageLinkTimePcRelative,
4546*795d594fSAndroid Build Coastguard Worker 
4547*795d594fSAndroid Build Coastguard Worker   // Load from a boot image entry in the .data.img.rel.ro using a PC-relative load.
4548*795d594fSAndroid Build Coastguard Worker   // Used for app->boot calls with relocatable image.
4549*795d594fSAndroid Build Coastguard Worker   kBootImageRelRo,
4550*795d594fSAndroid Build Coastguard Worker 
4551*795d594fSAndroid Build Coastguard Worker   // Load from an app image entry in the .data.img.rel.ro using a PC-relative load.
4552*795d594fSAndroid Build Coastguard Worker   // Used for app image methods referenced by apps in AOT-compiled code.
4553*795d594fSAndroid Build Coastguard Worker   kAppImageRelRo,
4554*795d594fSAndroid Build Coastguard Worker 
4555*795d594fSAndroid Build Coastguard Worker   // Load from an entry in the .bss section using a PC-relative load.
4556*795d594fSAndroid Build Coastguard Worker   // Used for methods outside boot image referenced by AOT-compiled app and boot image code.
4557*795d594fSAndroid Build Coastguard Worker   kBssEntry,
4558*795d594fSAndroid Build Coastguard Worker 
4559*795d594fSAndroid Build Coastguard Worker   // Use ArtMethod* at a known address, embed the direct address in the code.
4560*795d594fSAndroid Build Coastguard Worker   // Used for for JIT-compiled calls.
4561*795d594fSAndroid Build Coastguard Worker   kJitDirectAddress,
4562*795d594fSAndroid Build Coastguard Worker 
4563*795d594fSAndroid Build Coastguard Worker   // Make a runtime call to resolve and call the method. This is the last-resort-kind
4564*795d594fSAndroid Build Coastguard Worker   // used when other kinds are unimplemented on a particular architecture.
4565*795d594fSAndroid Build Coastguard Worker   kRuntimeCall,
4566*795d594fSAndroid Build Coastguard Worker };
4567*795d594fSAndroid Build Coastguard Worker 
4568*795d594fSAndroid Build Coastguard Worker // Determines the location of the code pointer of an invoke.
4569*795d594fSAndroid Build Coastguard Worker enum class CodePtrLocation {
4570*795d594fSAndroid Build Coastguard Worker   // Recursive call, use local PC-relative call instruction.
4571*795d594fSAndroid Build Coastguard Worker   kCallSelf,
4572*795d594fSAndroid Build Coastguard Worker 
4573*795d594fSAndroid Build Coastguard Worker   // Use native pointer from the Artmethod*.
4574*795d594fSAndroid Build Coastguard Worker   // Used for @CriticalNative to avoid going through the compiled stub. This call goes through
4575*795d594fSAndroid Build Coastguard Worker   // a special resolution stub if the class is not initialized or no native code is registered.
4576*795d594fSAndroid Build Coastguard Worker   kCallCriticalNative,
4577*795d594fSAndroid Build Coastguard Worker 
4578*795d594fSAndroid Build Coastguard Worker   // Use code pointer from the ArtMethod*.
4579*795d594fSAndroid Build Coastguard Worker   // Used when we don't know the target code. This is also the last-resort-kind used when
4580*795d594fSAndroid Build Coastguard Worker   // other kinds are unimplemented or impractical (i.e. slow) on a particular architecture.
4581*795d594fSAndroid Build Coastguard Worker   kCallArtMethod,
4582*795d594fSAndroid Build Coastguard Worker };
4583*795d594fSAndroid Build Coastguard Worker 
4584*795d594fSAndroid Build Coastguard Worker static inline bool IsPcRelativeMethodLoadKind(MethodLoadKind load_kind) {
4585*795d594fSAndroid Build Coastguard Worker   return load_kind == MethodLoadKind::kBootImageLinkTimePcRelative ||
4586*795d594fSAndroid Build Coastguard Worker          load_kind == MethodLoadKind::kBootImageRelRo ||
4587*795d594fSAndroid Build Coastguard Worker          load_kind == MethodLoadKind::kAppImageRelRo ||
4588*795d594fSAndroid Build Coastguard Worker          load_kind == MethodLoadKind::kBssEntry;
4589*795d594fSAndroid Build Coastguard Worker }
4590*795d594fSAndroid Build Coastguard Worker 
4591*795d594fSAndroid Build Coastguard Worker class HInvoke : public HVariableInputSizeInstruction {
4592*795d594fSAndroid Build Coastguard Worker  public:
4593*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override;
4594*795d594fSAndroid Build Coastguard Worker 
4595*795d594fSAndroid Build Coastguard Worker   void SetArgumentAt(size_t index, HInstruction* argument) {
4596*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(index, argument);
4597*795d594fSAndroid Build Coastguard Worker   }
4598*795d594fSAndroid Build Coastguard Worker 
4599*795d594fSAndroid Build Coastguard Worker   // Return the number of arguments.  This number can be lower than
4600*795d594fSAndroid Build Coastguard Worker   // the number of inputs returned by InputCount(), as some invoke
4601*795d594fSAndroid Build Coastguard Worker   // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
4602*795d594fSAndroid Build Coastguard Worker   // inputs at the end of their list of inputs.
4603*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
4604*795d594fSAndroid Build Coastguard Worker 
4605*795d594fSAndroid Build Coastguard Worker   // Return the number of outgoing vregs.
4606*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfOutVRegs() const { return number_of_out_vregs_; }
4607*795d594fSAndroid Build Coastguard Worker 
4608*795d594fSAndroid Build Coastguard Worker   InvokeType GetInvokeType() const {
4609*795d594fSAndroid Build Coastguard Worker     return GetPackedField<InvokeTypeField>();
4610*795d594fSAndroid Build Coastguard Worker   }
4611*795d594fSAndroid Build Coastguard Worker 
4612*795d594fSAndroid Build Coastguard Worker   Intrinsics GetIntrinsic() const {
4613*795d594fSAndroid Build Coastguard Worker     return intrinsic_;
4614*795d594fSAndroid Build Coastguard Worker   }
4615*795d594fSAndroid Build Coastguard Worker 
4616*795d594fSAndroid Build Coastguard Worker   void SetIntrinsic(Intrinsics intrinsic,
4617*795d594fSAndroid Build Coastguard Worker                     IntrinsicNeedsEnvironment needs_env,
4618*795d594fSAndroid Build Coastguard Worker                     IntrinsicSideEffects side_effects,
4619*795d594fSAndroid Build Coastguard Worker                     IntrinsicExceptions exceptions);
4620*795d594fSAndroid Build Coastguard Worker 
4621*795d594fSAndroid Build Coastguard Worker   bool IsFromInlinedInvoke() const {
4622*795d594fSAndroid Build Coastguard Worker     return GetEnvironment()->IsFromInlinedInvoke();
4623*795d594fSAndroid Build Coastguard Worker   }
4624*795d594fSAndroid Build Coastguard Worker 
4625*795d594fSAndroid Build Coastguard Worker   void SetCanThrow(bool can_throw) { SetPackedFlag<kFlagCanThrow>(can_throw); }
4626*795d594fSAndroid Build Coastguard Worker 
4627*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return GetPackedFlag<kFlagCanThrow>(); }
4628*795d594fSAndroid Build Coastguard Worker 
4629*795d594fSAndroid Build Coastguard Worker   void SetAlwaysThrows(bool always_throws) { SetPackedFlag<kFlagAlwaysThrows>(always_throws); }
4630*795d594fSAndroid Build Coastguard Worker 
4631*795d594fSAndroid Build Coastguard Worker   bool AlwaysThrows() const override final { return GetPackedFlag<kFlagAlwaysThrows>(); }
4632*795d594fSAndroid Build Coastguard Worker 
4633*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return IsIntrinsic() && !DoesAnyWrite(); }
4634*795d594fSAndroid Build Coastguard Worker 
4635*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override;
4636*795d594fSAndroid Build Coastguard Worker 
4637*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
4638*795d594fSAndroid Build Coastguard Worker     return intrinsic_ != Intrinsics::kNone && intrinsic_ == other->AsInvoke()->intrinsic_;
4639*795d594fSAndroid Build Coastguard Worker   }
4640*795d594fSAndroid Build Coastguard Worker 
4641*795d594fSAndroid Build Coastguard Worker   uint32_t* GetIntrinsicOptimizations() {
4642*795d594fSAndroid Build Coastguard Worker     return &intrinsic_optimizations_;
4643*795d594fSAndroid Build Coastguard Worker   }
4644*795d594fSAndroid Build Coastguard Worker 
4645*795d594fSAndroid Build Coastguard Worker   const uint32_t* GetIntrinsicOptimizations() const {
4646*795d594fSAndroid Build Coastguard Worker     return &intrinsic_optimizations_;
4647*795d594fSAndroid Build Coastguard Worker   }
4648*795d594fSAndroid Build Coastguard Worker 
4649*795d594fSAndroid Build Coastguard Worker   bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
4650*795d594fSAndroid Build Coastguard Worker 
4651*795d594fSAndroid Build Coastguard Worker   ArtMethod* GetResolvedMethod() const { return resolved_method_; }
4652*795d594fSAndroid Build Coastguard Worker   void SetResolvedMethod(ArtMethod* method, bool enable_intrinsic_opt);
4653*795d594fSAndroid Build Coastguard Worker 
4654*795d594fSAndroid Build Coastguard Worker   MethodReference GetMethodReference() const { return method_reference_; }
4655*795d594fSAndroid Build Coastguard Worker 
4656*795d594fSAndroid Build Coastguard Worker   const MethodReference GetResolvedMethodReference() const {
4657*795d594fSAndroid Build Coastguard Worker     return resolved_method_reference_;
4658*795d594fSAndroid Build Coastguard Worker   }
4659*795d594fSAndroid Build Coastguard Worker 
4660*795d594fSAndroid Build Coastguard Worker   DECLARE_ABSTRACT_INSTRUCTION(Invoke);
4661*795d594fSAndroid Build Coastguard Worker 
4662*795d594fSAndroid Build Coastguard Worker  protected:
4663*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldInvokeType = kNumberOfGenericPackedBits;
4664*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldInvokeTypeSize =
4665*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(kMaxInvokeType));
4666*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagCanThrow = kFieldInvokeType + kFieldInvokeTypeSize;
4667*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagAlwaysThrows = kFlagCanThrow + 1;
4668*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfInvokePackedBits = kFlagAlwaysThrows + 1;
4669*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfInvokePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
4670*795d594fSAndroid Build Coastguard Worker   using InvokeTypeField = BitField<InvokeType, kFieldInvokeType, kFieldInvokeTypeSize>;
4671*795d594fSAndroid Build Coastguard Worker 
4672*795d594fSAndroid Build Coastguard Worker   HInvoke(InstructionKind kind,
4673*795d594fSAndroid Build Coastguard Worker           ArenaAllocator* allocator,
4674*795d594fSAndroid Build Coastguard Worker           uint32_t number_of_arguments,
4675*795d594fSAndroid Build Coastguard Worker           uint32_t number_of_out_vregs,
4676*795d594fSAndroid Build Coastguard Worker           uint32_t number_of_other_inputs,
4677*795d594fSAndroid Build Coastguard Worker           DataType::Type return_type,
4678*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc,
4679*795d594fSAndroid Build Coastguard Worker           MethodReference method_reference,
4680*795d594fSAndroid Build Coastguard Worker           ArtMethod* resolved_method,
4681*795d594fSAndroid Build Coastguard Worker           MethodReference resolved_method_reference,
4682*795d594fSAndroid Build Coastguard Worker           InvokeType invoke_type,
4683*795d594fSAndroid Build Coastguard Worker           bool enable_intrinsic_opt)
4684*795d594fSAndroid Build Coastguard Worker     : HVariableInputSizeInstruction(
4685*795d594fSAndroid Build Coastguard Worker           kind,
4686*795d594fSAndroid Build Coastguard Worker           return_type,
4687*795d594fSAndroid Build Coastguard Worker           SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
4688*795d594fSAndroid Build Coastguard Worker           dex_pc,
4689*795d594fSAndroid Build Coastguard Worker           allocator,
4690*795d594fSAndroid Build Coastguard Worker           number_of_arguments + number_of_other_inputs,
4691*795d594fSAndroid Build Coastguard Worker           kArenaAllocInvokeInputs),
4692*795d594fSAndroid Build Coastguard Worker       method_reference_(method_reference),
4693*795d594fSAndroid Build Coastguard Worker       resolved_method_reference_(resolved_method_reference),
4694*795d594fSAndroid Build Coastguard Worker       number_of_arguments_(dchecked_integral_cast<uint16_t>(number_of_arguments)),
4695*795d594fSAndroid Build Coastguard Worker       number_of_out_vregs_(dchecked_integral_cast<uint16_t>(number_of_out_vregs)),
4696*795d594fSAndroid Build Coastguard Worker       intrinsic_(Intrinsics::kNone),
4697*795d594fSAndroid Build Coastguard Worker       intrinsic_optimizations_(0) {
4698*795d594fSAndroid Build Coastguard Worker     SetPackedField<InvokeTypeField>(invoke_type);
4699*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagCanThrow>(true);
4700*795d594fSAndroid Build Coastguard Worker     SetResolvedMethod(resolved_method, enable_intrinsic_opt);
4701*795d594fSAndroid Build Coastguard Worker   }
4702*795d594fSAndroid Build Coastguard Worker 
4703*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Invoke);
4704*795d594fSAndroid Build Coastguard Worker 
4705*795d594fSAndroid Build Coastguard Worker   ArtMethod* resolved_method_;
4706*795d594fSAndroid Build Coastguard Worker   const MethodReference method_reference_;
4707*795d594fSAndroid Build Coastguard Worker   // Cached values of the resolved method, to avoid needing the mutator lock.
4708*795d594fSAndroid Build Coastguard Worker   const MethodReference resolved_method_reference_;
4709*795d594fSAndroid Build Coastguard Worker 
4710*795d594fSAndroid Build Coastguard Worker   uint16_t number_of_arguments_;
4711*795d594fSAndroid Build Coastguard Worker   uint16_t number_of_out_vregs_;
4712*795d594fSAndroid Build Coastguard Worker 
4713*795d594fSAndroid Build Coastguard Worker   Intrinsics intrinsic_;
4714*795d594fSAndroid Build Coastguard Worker 
4715*795d594fSAndroid Build Coastguard Worker   // A magic word holding optimizations for intrinsics. See intrinsics.h.
4716*795d594fSAndroid Build Coastguard Worker   uint32_t intrinsic_optimizations_;
4717*795d594fSAndroid Build Coastguard Worker };
4718*795d594fSAndroid Build Coastguard Worker 
4719*795d594fSAndroid Build Coastguard Worker class HInvokeUnresolved final : public HInvoke {
4720*795d594fSAndroid Build Coastguard Worker  public:
4721*795d594fSAndroid Build Coastguard Worker   HInvokeUnresolved(ArenaAllocator* allocator,
4722*795d594fSAndroid Build Coastguard Worker                     uint32_t number_of_arguments,
4723*795d594fSAndroid Build Coastguard Worker                     uint32_t number_of_out_vregs,
4724*795d594fSAndroid Build Coastguard Worker                     DataType::Type return_type,
4725*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc,
4726*795d594fSAndroid Build Coastguard Worker                     MethodReference method_reference,
4727*795d594fSAndroid Build Coastguard Worker                     InvokeType invoke_type)
4728*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokeUnresolved,
4729*795d594fSAndroid Build Coastguard Worker                 allocator,
4730*795d594fSAndroid Build Coastguard Worker                 number_of_arguments,
4731*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
4732*795d594fSAndroid Build Coastguard Worker                 /* number_of_other_inputs= */ 0u,
4733*795d594fSAndroid Build Coastguard Worker                 return_type,
4734*795d594fSAndroid Build Coastguard Worker                 dex_pc,
4735*795d594fSAndroid Build Coastguard Worker                 method_reference,
4736*795d594fSAndroid Build Coastguard Worker                 nullptr,
4737*795d594fSAndroid Build Coastguard Worker                 MethodReference(nullptr, 0u),
4738*795d594fSAndroid Build Coastguard Worker                 invoke_type,
4739*795d594fSAndroid Build Coastguard Worker                 /* enable_intrinsic_opt= */ false) {
4740*795d594fSAndroid Build Coastguard Worker   }
4741*795d594fSAndroid Build Coastguard Worker 
4742*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
4743*795d594fSAndroid Build Coastguard Worker 
4744*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokeUnresolved);
4745*795d594fSAndroid Build Coastguard Worker 
4746*795d594fSAndroid Build Coastguard Worker  protected:
4747*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokeUnresolved);
4748*795d594fSAndroid Build Coastguard Worker };
4749*795d594fSAndroid Build Coastguard Worker 
4750*795d594fSAndroid Build Coastguard Worker class HInvokePolymorphic final : public HInvoke {
4751*795d594fSAndroid Build Coastguard Worker  public:
4752*795d594fSAndroid Build Coastguard Worker   HInvokePolymorphic(ArenaAllocator* allocator,
4753*795d594fSAndroid Build Coastguard Worker                      uint32_t number_of_arguments,
4754*795d594fSAndroid Build Coastguard Worker                      uint32_t number_of_out_vregs,
4755*795d594fSAndroid Build Coastguard Worker                      uint32_t number_of_other_inputs,
4756*795d594fSAndroid Build Coastguard Worker                      DataType::Type return_type,
4757*795d594fSAndroid Build Coastguard Worker                      uint32_t dex_pc,
4758*795d594fSAndroid Build Coastguard Worker                      MethodReference method_reference,
4759*795d594fSAndroid Build Coastguard Worker                      // resolved_method is the ArtMethod object corresponding to the polymorphic
4760*795d594fSAndroid Build Coastguard Worker                      // method (e.g. VarHandle.get), resolved using the class linker. It is needed
4761*795d594fSAndroid Build Coastguard Worker                      // to pass intrinsic information to the HInvokePolymorphic node.
4762*795d594fSAndroid Build Coastguard Worker                      ArtMethod* resolved_method,
4763*795d594fSAndroid Build Coastguard Worker                      MethodReference resolved_method_reference,
4764*795d594fSAndroid Build Coastguard Worker                      dex::ProtoIndex proto_idx)
4765*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokePolymorphic,
4766*795d594fSAndroid Build Coastguard Worker                 allocator,
4767*795d594fSAndroid Build Coastguard Worker                 number_of_arguments,
4768*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
4769*795d594fSAndroid Build Coastguard Worker                 number_of_other_inputs,
4770*795d594fSAndroid Build Coastguard Worker                 return_type,
4771*795d594fSAndroid Build Coastguard Worker                 dex_pc,
4772*795d594fSAndroid Build Coastguard Worker                 method_reference,
4773*795d594fSAndroid Build Coastguard Worker                 resolved_method,
4774*795d594fSAndroid Build Coastguard Worker                 resolved_method_reference,
4775*795d594fSAndroid Build Coastguard Worker                 kPolymorphic,
4776*795d594fSAndroid Build Coastguard Worker                 /* enable_intrinsic_opt= */ true),
4777*795d594fSAndroid Build Coastguard Worker         proto_idx_(proto_idx) {}
4778*795d594fSAndroid Build Coastguard Worker 
4779*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
4780*795d594fSAndroid Build Coastguard Worker 
4781*795d594fSAndroid Build Coastguard Worker   dex::ProtoIndex GetProtoIndex() { return proto_idx_; }
4782*795d594fSAndroid Build Coastguard Worker 
4783*795d594fSAndroid Build Coastguard Worker   bool IsMethodHandleInvokeExact() const {
4784*795d594fSAndroid Build Coastguard Worker     return GetIntrinsic() == Intrinsics::kMethodHandleInvokeExact;
4785*795d594fSAndroid Build Coastguard Worker   }
4786*795d594fSAndroid Build Coastguard Worker 
4787*795d594fSAndroid Build Coastguard Worker   bool CanTargetInstanceMethod() const {
4788*795d594fSAndroid Build Coastguard Worker     DCHECK(IsMethodHandleInvokeExact());
4789*795d594fSAndroid Build Coastguard Worker     return GetNumberOfArguments() >= 2 &&
4790*795d594fSAndroid Build Coastguard Worker         InputAt(1)->GetType() == DataType::Type::kReference;
4791*795d594fSAndroid Build Coastguard Worker   }
4792*795d594fSAndroid Build Coastguard Worker 
4793*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokePolymorphic);
4794*795d594fSAndroid Build Coastguard Worker 
4795*795d594fSAndroid Build Coastguard Worker  protected:
4796*795d594fSAndroid Build Coastguard Worker   dex::ProtoIndex proto_idx_;
4797*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokePolymorphic);
4798*795d594fSAndroid Build Coastguard Worker };
4799*795d594fSAndroid Build Coastguard Worker 
4800*795d594fSAndroid Build Coastguard Worker class HInvokeCustom final : public HInvoke {
4801*795d594fSAndroid Build Coastguard Worker  public:
4802*795d594fSAndroid Build Coastguard Worker   HInvokeCustom(ArenaAllocator* allocator,
4803*795d594fSAndroid Build Coastguard Worker                 uint32_t number_of_arguments,
4804*795d594fSAndroid Build Coastguard Worker                 uint32_t number_of_out_vregs,
4805*795d594fSAndroid Build Coastguard Worker                 uint32_t call_site_index,
4806*795d594fSAndroid Build Coastguard Worker                 DataType::Type return_type,
4807*795d594fSAndroid Build Coastguard Worker                 uint32_t dex_pc,
4808*795d594fSAndroid Build Coastguard Worker                 MethodReference method_reference,
4809*795d594fSAndroid Build Coastguard Worker                 bool enable_intrinsic_opt)
4810*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokeCustom,
4811*795d594fSAndroid Build Coastguard Worker                 allocator,
4812*795d594fSAndroid Build Coastguard Worker                 number_of_arguments,
4813*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
4814*795d594fSAndroid Build Coastguard Worker                 /* number_of_other_inputs= */ 0u,
4815*795d594fSAndroid Build Coastguard Worker                 return_type,
4816*795d594fSAndroid Build Coastguard Worker                 dex_pc,
4817*795d594fSAndroid Build Coastguard Worker                 method_reference,
4818*795d594fSAndroid Build Coastguard Worker                 /* resolved_method= */ nullptr,
4819*795d594fSAndroid Build Coastguard Worker                 MethodReference(nullptr, 0u),
4820*795d594fSAndroid Build Coastguard Worker                 kStatic,
4821*795d594fSAndroid Build Coastguard Worker                 enable_intrinsic_opt),
4822*795d594fSAndroid Build Coastguard Worker       call_site_index_(call_site_index) {
4823*795d594fSAndroid Build Coastguard Worker   }
4824*795d594fSAndroid Build Coastguard Worker 
4825*795d594fSAndroid Build Coastguard Worker   uint32_t GetCallSiteIndex() const { return call_site_index_; }
4826*795d594fSAndroid Build Coastguard Worker 
4827*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
4828*795d594fSAndroid Build Coastguard Worker 
4829*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokeCustom);
4830*795d594fSAndroid Build Coastguard Worker 
4831*795d594fSAndroid Build Coastguard Worker  protected:
4832*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokeCustom);
4833*795d594fSAndroid Build Coastguard Worker 
4834*795d594fSAndroid Build Coastguard Worker  private:
4835*795d594fSAndroid Build Coastguard Worker   uint32_t call_site_index_;
4836*795d594fSAndroid Build Coastguard Worker };
4837*795d594fSAndroid Build Coastguard Worker 
4838*795d594fSAndroid Build Coastguard Worker class HInvokeStaticOrDirect final : public HInvoke {
4839*795d594fSAndroid Build Coastguard Worker  public:
4840*795d594fSAndroid Build Coastguard Worker   // Requirements of this method call regarding the class
4841*795d594fSAndroid Build Coastguard Worker   // initialization (clinit) check of its declaring class.
4842*795d594fSAndroid Build Coastguard Worker   enum class ClinitCheckRequirement {  // private marker to avoid generate-operator-out.py from processing.
4843*795d594fSAndroid Build Coastguard Worker     kNone,      // Class already initialized.
4844*795d594fSAndroid Build Coastguard Worker     kExplicit,  // Static call having explicit clinit check as last input.
4845*795d594fSAndroid Build Coastguard Worker     kImplicit,  // Static call implicitly requiring a clinit check.
4846*795d594fSAndroid Build Coastguard Worker     kLast = kImplicit
4847*795d594fSAndroid Build Coastguard Worker   };
4848*795d594fSAndroid Build Coastguard Worker 
4849*795d594fSAndroid Build Coastguard Worker   struct DispatchInfo {
4850*795d594fSAndroid Build Coastguard Worker     MethodLoadKind method_load_kind;
4851*795d594fSAndroid Build Coastguard Worker     CodePtrLocation code_ptr_location;
4852*795d594fSAndroid Build Coastguard Worker     // The method load data holds
4853*795d594fSAndroid Build Coastguard Worker     //   - thread entrypoint offset for kStringInit method if this is a string init invoke.
4854*795d594fSAndroid Build Coastguard Worker     //     Note that there are multiple string init methods, each having its own offset.
4855*795d594fSAndroid Build Coastguard Worker     //   - the method address for kDirectAddress
4856*795d594fSAndroid Build Coastguard Worker     uint64_t method_load_data;
4857*795d594fSAndroid Build Coastguard Worker   };
4858*795d594fSAndroid Build Coastguard Worker 
4859*795d594fSAndroid Build Coastguard Worker   HInvokeStaticOrDirect(ArenaAllocator* allocator,
4860*795d594fSAndroid Build Coastguard Worker                         uint32_t number_of_arguments,
4861*795d594fSAndroid Build Coastguard Worker                         uint32_t number_of_out_vregs,
4862*795d594fSAndroid Build Coastguard Worker                         DataType::Type return_type,
4863*795d594fSAndroid Build Coastguard Worker                         uint32_t dex_pc,
4864*795d594fSAndroid Build Coastguard Worker                         MethodReference method_reference,
4865*795d594fSAndroid Build Coastguard Worker                         ArtMethod* resolved_method,
4866*795d594fSAndroid Build Coastguard Worker                         DispatchInfo dispatch_info,
4867*795d594fSAndroid Build Coastguard Worker                         InvokeType invoke_type,
4868*795d594fSAndroid Build Coastguard Worker                         MethodReference resolved_method_reference,
4869*795d594fSAndroid Build Coastguard Worker                         ClinitCheckRequirement clinit_check_requirement,
4870*795d594fSAndroid Build Coastguard Worker                         bool enable_intrinsic_opt)
4871*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokeStaticOrDirect,
4872*795d594fSAndroid Build Coastguard Worker                 allocator,
4873*795d594fSAndroid Build Coastguard Worker                 number_of_arguments,
4874*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
4875*795d594fSAndroid Build Coastguard Worker                 // There is potentially one extra argument for the HCurrentMethod input,
4876*795d594fSAndroid Build Coastguard Worker                 // and one other if the clinit check is explicit. These can be removed later.
4877*795d594fSAndroid Build Coastguard Worker                 (NeedsCurrentMethodInput(dispatch_info) ? 1u : 0u) +
4878*795d594fSAndroid Build Coastguard Worker                     (clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u),
4879*795d594fSAndroid Build Coastguard Worker                 return_type,
4880*795d594fSAndroid Build Coastguard Worker                 dex_pc,
4881*795d594fSAndroid Build Coastguard Worker                 method_reference,
4882*795d594fSAndroid Build Coastguard Worker                 resolved_method,
4883*795d594fSAndroid Build Coastguard Worker                 resolved_method_reference,
4884*795d594fSAndroid Build Coastguard Worker                 invoke_type,
4885*795d594fSAndroid Build Coastguard Worker                 enable_intrinsic_opt),
4886*795d594fSAndroid Build Coastguard Worker         dispatch_info_(dispatch_info) {
4887*795d594fSAndroid Build Coastguard Worker     SetPackedField<ClinitCheckRequirementField>(clinit_check_requirement);
4888*795d594fSAndroid Build Coastguard Worker   }
4889*795d594fSAndroid Build Coastguard Worker 
4890*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
4891*795d594fSAndroid Build Coastguard Worker   bool NeedsBss() const override {
4892*795d594fSAndroid Build Coastguard Worker     return GetMethodLoadKind() == MethodLoadKind::kBssEntry;
4893*795d594fSAndroid Build Coastguard Worker   }
4894*795d594fSAndroid Build Coastguard Worker 
4895*795d594fSAndroid Build Coastguard Worker   void SetDispatchInfo(DispatchInfo dispatch_info) {
4896*795d594fSAndroid Build Coastguard Worker     bool had_current_method_input = HasCurrentMethodInput();
4897*795d594fSAndroid Build Coastguard Worker     bool needs_current_method_input = NeedsCurrentMethodInput(dispatch_info);
4898*795d594fSAndroid Build Coastguard Worker 
4899*795d594fSAndroid Build Coastguard Worker     // Using the current method is the default and once we find a better
4900*795d594fSAndroid Build Coastguard Worker     // method load kind, we should not go back to using the current method.
4901*795d594fSAndroid Build Coastguard Worker     DCHECK(had_current_method_input || !needs_current_method_input);
4902*795d594fSAndroid Build Coastguard Worker 
4903*795d594fSAndroid Build Coastguard Worker     if (had_current_method_input && !needs_current_method_input) {
4904*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(InputAt(GetCurrentMethodIndex()), GetBlock()->GetGraph()->GetCurrentMethod());
4905*795d594fSAndroid Build Coastguard Worker       RemoveInputAt(GetCurrentMethodIndex());
4906*795d594fSAndroid Build Coastguard Worker     }
4907*795d594fSAndroid Build Coastguard Worker     dispatch_info_ = dispatch_info;
4908*795d594fSAndroid Build Coastguard Worker   }
4909*795d594fSAndroid Build Coastguard Worker 
4910*795d594fSAndroid Build Coastguard Worker   DispatchInfo GetDispatchInfo() const {
4911*795d594fSAndroid Build Coastguard Worker     return dispatch_info_;
4912*795d594fSAndroid Build Coastguard Worker   }
4913*795d594fSAndroid Build Coastguard Worker 
4914*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
4915*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() override {
4916*795d594fSAndroid Build Coastguard Worker     ArrayRef<HUserRecord<HInstruction*>> input_records = HInvoke::GetInputRecords();
4917*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild && IsStaticWithExplicitClinitCheck()) {
4918*795d594fSAndroid Build Coastguard Worker       DCHECK(!input_records.empty());
4919*795d594fSAndroid Build Coastguard Worker       DCHECK_GT(input_records.size(), GetNumberOfArguments());
4920*795d594fSAndroid Build Coastguard Worker       HInstruction* last_input = input_records.back().GetInstruction();
4921*795d594fSAndroid Build Coastguard Worker       // Note: `last_input` may be null during arguments setup.
4922*795d594fSAndroid Build Coastguard Worker       if (last_input != nullptr) {
4923*795d594fSAndroid Build Coastguard Worker         // `last_input` is the last input of a static invoke marked as having
4924*795d594fSAndroid Build Coastguard Worker         // an explicit clinit check. It must either be:
4925*795d594fSAndroid Build Coastguard Worker         // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
4926*795d594fSAndroid Build Coastguard Worker         // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
4927*795d594fSAndroid Build Coastguard Worker         DCHECK(last_input->IsClinitCheck() || last_input->IsLoadClass()) << last_input->DebugName();
4928*795d594fSAndroid Build Coastguard Worker       }
4929*795d594fSAndroid Build Coastguard Worker     }
4930*795d594fSAndroid Build Coastguard Worker     return input_records;
4931*795d594fSAndroid Build Coastguard Worker   }
4932*795d594fSAndroid Build Coastguard Worker 
4933*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
4934*795d594fSAndroid Build Coastguard Worker     // We do not access the method via object reference, so we cannot do an implicit null check.
4935*795d594fSAndroid Build Coastguard Worker     // TODO: for intrinsics we can generate implicit null checks.
4936*795d594fSAndroid Build Coastguard Worker     return false;
4937*795d594fSAndroid Build Coastguard Worker   }
4938*795d594fSAndroid Build Coastguard Worker 
4939*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override;
4940*795d594fSAndroid Build Coastguard Worker 
4941*795d594fSAndroid Build Coastguard Worker   MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
4942*795d594fSAndroid Build Coastguard Worker   CodePtrLocation GetCodePtrLocation() const {
4943*795d594fSAndroid Build Coastguard Worker     // We do CHA analysis after sharpening. When a method has CHA inlining, it
4944*795d594fSAndroid Build Coastguard Worker     // cannot call itself, as if the CHA optmization is invalid we want to make
4945*795d594fSAndroid Build Coastguard Worker     // sure the method is never executed again. So, while sharpening can return
4946*795d594fSAndroid Build Coastguard Worker     // kCallSelf, we bypass it here if there is a CHA optimization.
4947*795d594fSAndroid Build Coastguard Worker     if (dispatch_info_.code_ptr_location == CodePtrLocation::kCallSelf &&
4948*795d594fSAndroid Build Coastguard Worker         GetBlock()->GetGraph()->HasShouldDeoptimizeFlag()) {
4949*795d594fSAndroid Build Coastguard Worker       return CodePtrLocation::kCallArtMethod;
4950*795d594fSAndroid Build Coastguard Worker     } else {
4951*795d594fSAndroid Build Coastguard Worker       return dispatch_info_.code_ptr_location;
4952*795d594fSAndroid Build Coastguard Worker     }
4953*795d594fSAndroid Build Coastguard Worker   }
4954*795d594fSAndroid Build Coastguard Worker   bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
4955*795d594fSAndroid Build Coastguard Worker   bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
4956*795d594fSAndroid Build Coastguard Worker   bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kJitDirectAddress; }
4957*795d594fSAndroid Build Coastguard Worker   bool HasPcRelativeMethodLoadKind() const {
4958*795d594fSAndroid Build Coastguard Worker     return IsPcRelativeMethodLoadKind(GetMethodLoadKind());
4959*795d594fSAndroid Build Coastguard Worker   }
4960*795d594fSAndroid Build Coastguard Worker 
4961*795d594fSAndroid Build Coastguard Worker   QuickEntrypointEnum GetStringInitEntryPoint() const {
4962*795d594fSAndroid Build Coastguard Worker     DCHECK(IsStringInit());
4963*795d594fSAndroid Build Coastguard Worker     return static_cast<QuickEntrypointEnum>(dispatch_info_.method_load_data);
4964*795d594fSAndroid Build Coastguard Worker   }
4965*795d594fSAndroid Build Coastguard Worker 
4966*795d594fSAndroid Build Coastguard Worker   uint64_t GetMethodAddress() const {
4967*795d594fSAndroid Build Coastguard Worker     DCHECK(HasMethodAddress());
4968*795d594fSAndroid Build Coastguard Worker     return dispatch_info_.method_load_data;
4969*795d594fSAndroid Build Coastguard Worker   }
4970*795d594fSAndroid Build Coastguard Worker 
4971*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFileForPcRelativeDexCache() const;
4972*795d594fSAndroid Build Coastguard Worker 
4973*795d594fSAndroid Build Coastguard Worker   ClinitCheckRequirement GetClinitCheckRequirement() const {
4974*795d594fSAndroid Build Coastguard Worker     return GetPackedField<ClinitCheckRequirementField>();
4975*795d594fSAndroid Build Coastguard Worker   }
4976*795d594fSAndroid Build Coastguard Worker 
4977*795d594fSAndroid Build Coastguard Worker   // Is this instruction a call to a static method?
4978*795d594fSAndroid Build Coastguard Worker   bool IsStatic() const {
4979*795d594fSAndroid Build Coastguard Worker     return GetInvokeType() == kStatic;
4980*795d594fSAndroid Build Coastguard Worker   }
4981*795d594fSAndroid Build Coastguard Worker 
4982*795d594fSAndroid Build Coastguard Worker   // Does this method load kind need the current method as an input?
4983*795d594fSAndroid Build Coastguard Worker   static bool NeedsCurrentMethodInput(DispatchInfo dispatch_info) {
4984*795d594fSAndroid Build Coastguard Worker     return dispatch_info.method_load_kind == MethodLoadKind::kRecursive ||
4985*795d594fSAndroid Build Coastguard Worker            dispatch_info.method_load_kind == MethodLoadKind::kRuntimeCall ||
4986*795d594fSAndroid Build Coastguard Worker            dispatch_info.code_ptr_location == CodePtrLocation::kCallCriticalNative;
4987*795d594fSAndroid Build Coastguard Worker   }
4988*795d594fSAndroid Build Coastguard Worker 
4989*795d594fSAndroid Build Coastguard Worker   // Get the index of the current method input.
4990*795d594fSAndroid Build Coastguard Worker   size_t GetCurrentMethodIndex() const {
4991*795d594fSAndroid Build Coastguard Worker     DCHECK(HasCurrentMethodInput());
4992*795d594fSAndroid Build Coastguard Worker     return GetCurrentMethodIndexUnchecked();
4993*795d594fSAndroid Build Coastguard Worker   }
4994*795d594fSAndroid Build Coastguard Worker   size_t GetCurrentMethodIndexUnchecked() const {
4995*795d594fSAndroid Build Coastguard Worker     return GetNumberOfArguments();
4996*795d594fSAndroid Build Coastguard Worker   }
4997*795d594fSAndroid Build Coastguard Worker 
4998*795d594fSAndroid Build Coastguard Worker   // Check if the method has a current method input.
4999*795d594fSAndroid Build Coastguard Worker   bool HasCurrentMethodInput() const {
5000*795d594fSAndroid Build Coastguard Worker     if (NeedsCurrentMethodInput(GetDispatchInfo())) {
5001*795d594fSAndroid Build Coastguard Worker       DCHECK(InputAt(GetCurrentMethodIndexUnchecked()) == nullptr ||  // During argument setup.
5002*795d594fSAndroid Build Coastguard Worker              InputAt(GetCurrentMethodIndexUnchecked())->IsCurrentMethod());
5003*795d594fSAndroid Build Coastguard Worker       return true;
5004*795d594fSAndroid Build Coastguard Worker     } else {
5005*795d594fSAndroid Build Coastguard Worker       DCHECK(InputCount() == GetCurrentMethodIndexUnchecked() ||
5006*795d594fSAndroid Build Coastguard Worker              InputAt(GetCurrentMethodIndexUnchecked()) == nullptr ||  // During argument setup.
5007*795d594fSAndroid Build Coastguard Worker              !InputAt(GetCurrentMethodIndexUnchecked())->IsCurrentMethod());
5008*795d594fSAndroid Build Coastguard Worker       return false;
5009*795d594fSAndroid Build Coastguard Worker     }
5010*795d594fSAndroid Build Coastguard Worker   }
5011*795d594fSAndroid Build Coastguard Worker 
5012*795d594fSAndroid Build Coastguard Worker   // Get the index of the special input.
5013*795d594fSAndroid Build Coastguard Worker   size_t GetSpecialInputIndex() const {
5014*795d594fSAndroid Build Coastguard Worker     DCHECK(HasSpecialInput());
5015*795d594fSAndroid Build Coastguard Worker     return GetSpecialInputIndexUnchecked();
5016*795d594fSAndroid Build Coastguard Worker   }
5017*795d594fSAndroid Build Coastguard Worker   size_t GetSpecialInputIndexUnchecked() const {
5018*795d594fSAndroid Build Coastguard Worker     return GetNumberOfArguments() + (HasCurrentMethodInput() ? 1u : 0u);
5019*795d594fSAndroid Build Coastguard Worker   }
5020*795d594fSAndroid Build Coastguard Worker 
5021*795d594fSAndroid Build Coastguard Worker   // Check if the method has a special input.
5022*795d594fSAndroid Build Coastguard Worker   bool HasSpecialInput() const {
5023*795d594fSAndroid Build Coastguard Worker     size_t other_inputs =
5024*795d594fSAndroid Build Coastguard Worker         GetSpecialInputIndexUnchecked() + (IsStaticWithExplicitClinitCheck() ? 1u : 0u);
5025*795d594fSAndroid Build Coastguard Worker     size_t input_count = InputCount();
5026*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(input_count - other_inputs, 1u) << other_inputs << " " << input_count;
5027*795d594fSAndroid Build Coastguard Worker     return other_inputs != input_count;
5028*795d594fSAndroid Build Coastguard Worker   }
5029*795d594fSAndroid Build Coastguard Worker 
5030*795d594fSAndroid Build Coastguard Worker   void AddSpecialInput(HInstruction* input) {
5031*795d594fSAndroid Build Coastguard Worker     // We allow only one special input.
5032*795d594fSAndroid Build Coastguard Worker     DCHECK(!HasSpecialInput());
5033*795d594fSAndroid Build Coastguard Worker     InsertInputAt(GetSpecialInputIndexUnchecked(), input);
5034*795d594fSAndroid Build Coastguard Worker   }
5035*795d594fSAndroid Build Coastguard Worker 
5036*795d594fSAndroid Build Coastguard Worker   // Remove the HClinitCheck or the replacement HLoadClass (set as last input by
5037*795d594fSAndroid Build Coastguard Worker   // PrepareForRegisterAllocation::VisitClinitCheck() in lieu of the initial HClinitCheck)
5038*795d594fSAndroid Build Coastguard Worker   // instruction; only relevant for static calls with explicit clinit check.
5039*795d594fSAndroid Build Coastguard Worker   void RemoveExplicitClinitCheck(ClinitCheckRequirement new_requirement) {
5040*795d594fSAndroid Build Coastguard Worker     DCHECK(IsStaticWithExplicitClinitCheck());
5041*795d594fSAndroid Build Coastguard Worker     size_t last_input_index = inputs_.size() - 1u;
5042*795d594fSAndroid Build Coastguard Worker     HInstruction* last_input = inputs_.back().GetInstruction();
5043*795d594fSAndroid Build Coastguard Worker     DCHECK(last_input != nullptr);
5044*795d594fSAndroid Build Coastguard Worker     DCHECK(last_input->IsLoadClass() || last_input->IsClinitCheck()) << last_input->DebugName();
5045*795d594fSAndroid Build Coastguard Worker     RemoveAsUserOfInput(last_input_index);
5046*795d594fSAndroid Build Coastguard Worker     inputs_.pop_back();
5047*795d594fSAndroid Build Coastguard Worker     SetPackedField<ClinitCheckRequirementField>(new_requirement);
5048*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsStaticWithExplicitClinitCheck());
5049*795d594fSAndroid Build Coastguard Worker   }
5050*795d594fSAndroid Build Coastguard Worker 
5051*795d594fSAndroid Build Coastguard Worker   // Is this a call to a static method whose declaring class has an
5052*795d594fSAndroid Build Coastguard Worker   // explicit initialization check in the graph?
5053*795d594fSAndroid Build Coastguard Worker   bool IsStaticWithExplicitClinitCheck() const {
5054*795d594fSAndroid Build Coastguard Worker     return IsStatic() && (GetClinitCheckRequirement() == ClinitCheckRequirement::kExplicit);
5055*795d594fSAndroid Build Coastguard Worker   }
5056*795d594fSAndroid Build Coastguard Worker 
5057*795d594fSAndroid Build Coastguard Worker   // Is this a call to a static method whose declaring class has an
5058*795d594fSAndroid Build Coastguard Worker   // implicit intialization check requirement?
5059*795d594fSAndroid Build Coastguard Worker   bool IsStaticWithImplicitClinitCheck() const {
5060*795d594fSAndroid Build Coastguard Worker     return IsStatic() && (GetClinitCheckRequirement() == ClinitCheckRequirement::kImplicit);
5061*795d594fSAndroid Build Coastguard Worker   }
5062*795d594fSAndroid Build Coastguard Worker 
5063*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokeStaticOrDirect);
5064*795d594fSAndroid Build Coastguard Worker 
5065*795d594fSAndroid Build Coastguard Worker  protected:
5066*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokeStaticOrDirect);
5067*795d594fSAndroid Build Coastguard Worker 
5068*795d594fSAndroid Build Coastguard Worker  private:
5069*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldClinitCheckRequirement = kNumberOfInvokePackedBits;
5070*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldClinitCheckRequirementSize =
5071*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(ClinitCheckRequirement::kLast));
5072*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfInvokeStaticOrDirectPackedBits =
5073*795d594fSAndroid Build Coastguard Worker       kFieldClinitCheckRequirement + kFieldClinitCheckRequirementSize;
5074*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfInvokeStaticOrDirectPackedBits <= kMaxNumberOfPackedBits,
5075*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
5076*795d594fSAndroid Build Coastguard Worker   using ClinitCheckRequirementField = BitField<ClinitCheckRequirement,
5077*795d594fSAndroid Build Coastguard Worker                                                kFieldClinitCheckRequirement,
5078*795d594fSAndroid Build Coastguard Worker                                                kFieldClinitCheckRequirementSize>;
5079*795d594fSAndroid Build Coastguard Worker 
5080*795d594fSAndroid Build Coastguard Worker   DispatchInfo dispatch_info_;
5081*795d594fSAndroid Build Coastguard Worker };
5082*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, MethodLoadKind rhs);
5083*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, CodePtrLocation rhs);
5084*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckRequirement rhs);
5085*795d594fSAndroid Build Coastguard Worker 
5086*795d594fSAndroid Build Coastguard Worker class HInvokeVirtual final : public HInvoke {
5087*795d594fSAndroid Build Coastguard Worker  public:
5088*795d594fSAndroid Build Coastguard Worker   HInvokeVirtual(ArenaAllocator* allocator,
5089*795d594fSAndroid Build Coastguard Worker                  uint32_t number_of_arguments,
5090*795d594fSAndroid Build Coastguard Worker                  uint32_t number_of_out_vregs,
5091*795d594fSAndroid Build Coastguard Worker                  DataType::Type return_type,
5092*795d594fSAndroid Build Coastguard Worker                  uint32_t dex_pc,
5093*795d594fSAndroid Build Coastguard Worker                  MethodReference method_reference,
5094*795d594fSAndroid Build Coastguard Worker                  ArtMethod* resolved_method,
5095*795d594fSAndroid Build Coastguard Worker                  MethodReference resolved_method_reference,
5096*795d594fSAndroid Build Coastguard Worker                  uint32_t vtable_index,
5097*795d594fSAndroid Build Coastguard Worker                  bool enable_intrinsic_opt)
5098*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokeVirtual,
5099*795d594fSAndroid Build Coastguard Worker                 allocator,
5100*795d594fSAndroid Build Coastguard Worker                 number_of_arguments,
5101*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
5102*795d594fSAndroid Build Coastguard Worker                 0u,
5103*795d594fSAndroid Build Coastguard Worker                 return_type,
5104*795d594fSAndroid Build Coastguard Worker                 dex_pc,
5105*795d594fSAndroid Build Coastguard Worker                 method_reference,
5106*795d594fSAndroid Build Coastguard Worker                 resolved_method,
5107*795d594fSAndroid Build Coastguard Worker                 resolved_method_reference,
5108*795d594fSAndroid Build Coastguard Worker                 kVirtual,
5109*795d594fSAndroid Build Coastguard Worker                 enable_intrinsic_opt),
5110*795d594fSAndroid Build Coastguard Worker         vtable_index_(vtable_index) {
5111*795d594fSAndroid Build Coastguard Worker   }
5112*795d594fSAndroid Build Coastguard Worker 
5113*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5114*795d594fSAndroid Build Coastguard Worker 
5115*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn(HInstruction* obj) const override;
5116*795d594fSAndroid Build Coastguard Worker 
5117*795d594fSAndroid Build Coastguard Worker   uint32_t GetVTableIndex() const { return vtable_index_; }
5118*795d594fSAndroid Build Coastguard Worker 
5119*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokeVirtual);
5120*795d594fSAndroid Build Coastguard Worker 
5121*795d594fSAndroid Build Coastguard Worker  protected:
5122*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokeVirtual);
5123*795d594fSAndroid Build Coastguard Worker 
5124*795d594fSAndroid Build Coastguard Worker  private:
5125*795d594fSAndroid Build Coastguard Worker   // Cached value of the resolved method, to avoid needing the mutator lock.
5126*795d594fSAndroid Build Coastguard Worker   const uint32_t vtable_index_;
5127*795d594fSAndroid Build Coastguard Worker };
5128*795d594fSAndroid Build Coastguard Worker 
5129*795d594fSAndroid Build Coastguard Worker class HInvokeInterface final : public HInvoke {
5130*795d594fSAndroid Build Coastguard Worker  public:
5131*795d594fSAndroid Build Coastguard Worker   HInvokeInterface(ArenaAllocator* allocator,
5132*795d594fSAndroid Build Coastguard Worker                    uint32_t number_of_arguments,
5133*795d594fSAndroid Build Coastguard Worker                    uint32_t number_of_out_vregs,
5134*795d594fSAndroid Build Coastguard Worker                    DataType::Type return_type,
5135*795d594fSAndroid Build Coastguard Worker                    uint32_t dex_pc,
5136*795d594fSAndroid Build Coastguard Worker                    MethodReference method_reference,
5137*795d594fSAndroid Build Coastguard Worker                    ArtMethod* resolved_method,
5138*795d594fSAndroid Build Coastguard Worker                    MethodReference resolved_method_reference,
5139*795d594fSAndroid Build Coastguard Worker                    uint32_t imt_index,
5140*795d594fSAndroid Build Coastguard Worker                    MethodLoadKind load_kind,
5141*795d594fSAndroid Build Coastguard Worker                    bool enable_intrinsic_opt)
5142*795d594fSAndroid Build Coastguard Worker       : HInvoke(kInvokeInterface,
5143*795d594fSAndroid Build Coastguard Worker                 allocator,
5144*795d594fSAndroid Build Coastguard Worker                 number_of_arguments + (NeedsCurrentMethod(load_kind) ? 1 : 0),
5145*795d594fSAndroid Build Coastguard Worker                 number_of_out_vregs,
5146*795d594fSAndroid Build Coastguard Worker                 0u,
5147*795d594fSAndroid Build Coastguard Worker                 return_type,
5148*795d594fSAndroid Build Coastguard Worker                 dex_pc,
5149*795d594fSAndroid Build Coastguard Worker                 method_reference,
5150*795d594fSAndroid Build Coastguard Worker                 resolved_method,
5151*795d594fSAndroid Build Coastguard Worker                 resolved_method_reference,
5152*795d594fSAndroid Build Coastguard Worker                 kInterface,
5153*795d594fSAndroid Build Coastguard Worker                 enable_intrinsic_opt),
5154*795d594fSAndroid Build Coastguard Worker         imt_index_(imt_index),
5155*795d594fSAndroid Build Coastguard Worker         hidden_argument_load_kind_(load_kind) {
5156*795d594fSAndroid Build Coastguard Worker   }
5157*795d594fSAndroid Build Coastguard Worker 
5158*795d594fSAndroid Build Coastguard Worker   static bool NeedsCurrentMethod(MethodLoadKind load_kind) {
5159*795d594fSAndroid Build Coastguard Worker     return load_kind == MethodLoadKind::kRecursive;
5160*795d594fSAndroid Build Coastguard Worker   }
5161*795d594fSAndroid Build Coastguard Worker 
5162*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5163*795d594fSAndroid Build Coastguard Worker   bool NeedsBss() const override {
5164*795d594fSAndroid Build Coastguard Worker     return GetHiddenArgumentLoadKind() == MethodLoadKind::kBssEntry;
5165*795d594fSAndroid Build Coastguard Worker   }
5166*795d594fSAndroid Build Coastguard Worker 
5167*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
5168*795d594fSAndroid Build Coastguard Worker     // TODO: Add implicit null checks in intrinsics.
5169*795d594fSAndroid Build Coastguard Worker     return (obj == InputAt(0)) && !IsIntrinsic();
5170*795d594fSAndroid Build Coastguard Worker   }
5171*795d594fSAndroid Build Coastguard Worker 
5172*795d594fSAndroid Build Coastguard Worker   size_t GetSpecialInputIndex() const {
5173*795d594fSAndroid Build Coastguard Worker     return GetNumberOfArguments();
5174*795d594fSAndroid Build Coastguard Worker   }
5175*795d594fSAndroid Build Coastguard Worker 
5176*795d594fSAndroid Build Coastguard Worker   void AddSpecialInput(HInstruction* input) {
5177*795d594fSAndroid Build Coastguard Worker     InsertInputAt(GetSpecialInputIndex(), input);
5178*795d594fSAndroid Build Coastguard Worker   }
5179*795d594fSAndroid Build Coastguard Worker 
5180*795d594fSAndroid Build Coastguard Worker   uint32_t GetImtIndex() const { return imt_index_; }
5181*795d594fSAndroid Build Coastguard Worker   MethodLoadKind GetHiddenArgumentLoadKind() const { return hidden_argument_load_kind_; }
5182*795d594fSAndroid Build Coastguard Worker 
5183*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InvokeInterface);
5184*795d594fSAndroid Build Coastguard Worker 
5185*795d594fSAndroid Build Coastguard Worker  protected:
5186*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InvokeInterface);
5187*795d594fSAndroid Build Coastguard Worker 
5188*795d594fSAndroid Build Coastguard Worker  private:
5189*795d594fSAndroid Build Coastguard Worker   // Cached value of the resolved method, to avoid needing the mutator lock.
5190*795d594fSAndroid Build Coastguard Worker   const uint32_t imt_index_;
5191*795d594fSAndroid Build Coastguard Worker 
5192*795d594fSAndroid Build Coastguard Worker   // How the hidden argument (the interface method) is being loaded.
5193*795d594fSAndroid Build Coastguard Worker   const MethodLoadKind hidden_argument_load_kind_;
5194*795d594fSAndroid Build Coastguard Worker };
5195*795d594fSAndroid Build Coastguard Worker 
5196*795d594fSAndroid Build Coastguard Worker class HNeg final : public HUnaryOperation {
5197*795d594fSAndroid Build Coastguard Worker  public:
5198*795d594fSAndroid Build Coastguard Worker   HNeg(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
5199*795d594fSAndroid Build Coastguard Worker       : HUnaryOperation(kNeg, result_type, input, dex_pc) {
5200*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(result_type, DataType::Kind(input->GetType()));
5201*795d594fSAndroid Build Coastguard Worker   }
5202*795d594fSAndroid Build Coastguard Worker 
5203*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x) { return -x; }
5204*795d594fSAndroid Build Coastguard Worker 
5205*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x) const override {
5206*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
5207*795d594fSAndroid Build Coastguard Worker   }
5208*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x) const override {
5209*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
5210*795d594fSAndroid Build Coastguard Worker   }
5211*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x) const override {
5212*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue()));
5213*795d594fSAndroid Build Coastguard Worker   }
5214*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x) const override {
5215*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue()));
5216*795d594fSAndroid Build Coastguard Worker   }
5217*795d594fSAndroid Build Coastguard Worker 
5218*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Neg);
5219*795d594fSAndroid Build Coastguard Worker 
5220*795d594fSAndroid Build Coastguard Worker  protected:
5221*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Neg);
5222*795d594fSAndroid Build Coastguard Worker };
5223*795d594fSAndroid Build Coastguard Worker 
5224*795d594fSAndroid Build Coastguard Worker class HNewArray final : public HExpression<2> {
5225*795d594fSAndroid Build Coastguard Worker  public:
5226*795d594fSAndroid Build Coastguard Worker   HNewArray(HInstruction* cls, HInstruction* length, uint32_t dex_pc, size_t component_size_shift)
5227*795d594fSAndroid Build Coastguard Worker       : HExpression(kNewArray, DataType::Type::kReference, SideEffects::CanTriggerGC(), dex_pc) {
5228*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cls);
5229*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, length);
5230*795d594fSAndroid Build Coastguard Worker     SetPackedField<ComponentSizeShiftField>(component_size_shift);
5231*795d594fSAndroid Build Coastguard Worker   }
5232*795d594fSAndroid Build Coastguard Worker 
5233*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5234*795d594fSAndroid Build Coastguard Worker 
5235*795d594fSAndroid Build Coastguard Worker   // Calls runtime so needs an environment.
5236*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
5237*795d594fSAndroid Build Coastguard Worker 
5238*795d594fSAndroid Build Coastguard Worker   // May throw NegativeArraySizeException, OutOfMemoryError, etc.
5239*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
5240*795d594fSAndroid Build Coastguard Worker 
5241*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
5242*795d594fSAndroid Build Coastguard Worker 
5243*795d594fSAndroid Build Coastguard Worker   HLoadClass* GetLoadClass() const {
5244*795d594fSAndroid Build Coastguard Worker     DCHECK(InputAt(0)->IsLoadClass());
5245*795d594fSAndroid Build Coastguard Worker     return InputAt(0)->AsLoadClass();
5246*795d594fSAndroid Build Coastguard Worker   }
5247*795d594fSAndroid Build Coastguard Worker 
5248*795d594fSAndroid Build Coastguard Worker   HInstruction* GetLength() const {
5249*795d594fSAndroid Build Coastguard Worker     return InputAt(1);
5250*795d594fSAndroid Build Coastguard Worker   }
5251*795d594fSAndroid Build Coastguard Worker 
5252*795d594fSAndroid Build Coastguard Worker   size_t GetComponentSizeShift() {
5253*795d594fSAndroid Build Coastguard Worker     return GetPackedField<ComponentSizeShiftField>();
5254*795d594fSAndroid Build Coastguard Worker   }
5255*795d594fSAndroid Build Coastguard Worker 
5256*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(NewArray);
5257*795d594fSAndroid Build Coastguard Worker 
5258*795d594fSAndroid Build Coastguard Worker  protected:
5259*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(NewArray);
5260*795d594fSAndroid Build Coastguard Worker 
5261*795d594fSAndroid Build Coastguard Worker  private:
5262*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComponentSizeShift = kNumberOfGenericPackedBits;
5263*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldComponentSizeShiftSize = MinimumBitsToStore(3u);
5264*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfNewArrayPackedBits =
5265*795d594fSAndroid Build Coastguard Worker       kFieldComponentSizeShift + kFieldComponentSizeShiftSize;
5266*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfNewArrayPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
5267*795d594fSAndroid Build Coastguard Worker   using ComponentSizeShiftField =
5268*795d594fSAndroid Build Coastguard Worker       BitField<size_t, kFieldComponentSizeShift, kFieldComponentSizeShiftSize>;
5269*795d594fSAndroid Build Coastguard Worker };
5270*795d594fSAndroid Build Coastguard Worker 
5271*795d594fSAndroid Build Coastguard Worker class HAdd final : public HBinaryOperation {
5272*795d594fSAndroid Build Coastguard Worker  public:
5273*795d594fSAndroid Build Coastguard Worker   HAdd(DataType::Type result_type,
5274*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5275*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5276*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5277*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kAdd, result_type, left, right, SideEffects::None(), dex_pc) {
5278*795d594fSAndroid Build Coastguard Worker   }
5279*795d594fSAndroid Build Coastguard Worker 
5280*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5281*795d594fSAndroid Build Coastguard Worker 
5282*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x + y; }
5283*795d594fSAndroid Build Coastguard Worker 
5284*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5285*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5286*795d594fSAndroid Build Coastguard Worker   }
5287*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5288*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5289*795d594fSAndroid Build Coastguard Worker   }
5290*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
5291*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue(), y->GetValue()));
5292*795d594fSAndroid Build Coastguard Worker   }
5293*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
5294*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue(), y->GetValue()));
5295*795d594fSAndroid Build Coastguard Worker   }
5296*795d594fSAndroid Build Coastguard Worker 
5297*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Add);
5298*795d594fSAndroid Build Coastguard Worker 
5299*795d594fSAndroid Build Coastguard Worker  protected:
5300*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Add);
5301*795d594fSAndroid Build Coastguard Worker };
5302*795d594fSAndroid Build Coastguard Worker 
5303*795d594fSAndroid Build Coastguard Worker class HSub final : public HBinaryOperation {
5304*795d594fSAndroid Build Coastguard Worker  public:
5305*795d594fSAndroid Build Coastguard Worker   HSub(DataType::Type result_type,
5306*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5307*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5308*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5309*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kSub, result_type, left, right, SideEffects::None(), dex_pc) {
5310*795d594fSAndroid Build Coastguard Worker   }
5311*795d594fSAndroid Build Coastguard Worker 
5312*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x - y; }
5313*795d594fSAndroid Build Coastguard Worker 
5314*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5315*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5316*795d594fSAndroid Build Coastguard Worker   }
5317*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5318*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5319*795d594fSAndroid Build Coastguard Worker   }
5320*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
5321*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue(), y->GetValue()));
5322*795d594fSAndroid Build Coastguard Worker   }
5323*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
5324*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue(), y->GetValue()));
5325*795d594fSAndroid Build Coastguard Worker   }
5326*795d594fSAndroid Build Coastguard Worker 
5327*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Sub);
5328*795d594fSAndroid Build Coastguard Worker 
5329*795d594fSAndroid Build Coastguard Worker  protected:
5330*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Sub);
5331*795d594fSAndroid Build Coastguard Worker };
5332*795d594fSAndroid Build Coastguard Worker 
5333*795d594fSAndroid Build Coastguard Worker class HMul final : public HBinaryOperation {
5334*795d594fSAndroid Build Coastguard Worker  public:
5335*795d594fSAndroid Build Coastguard Worker   HMul(DataType::Type result_type,
5336*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5337*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5338*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5339*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kMul, result_type, left, right, SideEffects::None(), dex_pc) {
5340*795d594fSAndroid Build Coastguard Worker   }
5341*795d594fSAndroid Build Coastguard Worker 
5342*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5343*795d594fSAndroid Build Coastguard Worker 
5344*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x * y; }
5345*795d594fSAndroid Build Coastguard Worker 
5346*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5347*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5348*795d594fSAndroid Build Coastguard Worker   }
5349*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5350*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5351*795d594fSAndroid Build Coastguard Worker   }
5352*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
5353*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(Compute(x->GetValue(), y->GetValue()));
5354*795d594fSAndroid Build Coastguard Worker   }
5355*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
5356*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(Compute(x->GetValue(), y->GetValue()));
5357*795d594fSAndroid Build Coastguard Worker   }
5358*795d594fSAndroid Build Coastguard Worker 
5359*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Mul);
5360*795d594fSAndroid Build Coastguard Worker 
5361*795d594fSAndroid Build Coastguard Worker  protected:
5362*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Mul);
5363*795d594fSAndroid Build Coastguard Worker };
5364*795d594fSAndroid Build Coastguard Worker 
5365*795d594fSAndroid Build Coastguard Worker class HDiv final : public HBinaryOperation {
5366*795d594fSAndroid Build Coastguard Worker  public:
5367*795d594fSAndroid Build Coastguard Worker   HDiv(DataType::Type result_type,
5368*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5369*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5370*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc)
5371*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kDiv, result_type, left, right, SideEffects::None(), dex_pc) {
5372*795d594fSAndroid Build Coastguard Worker   }
5373*795d594fSAndroid Build Coastguard Worker 
5374*795d594fSAndroid Build Coastguard Worker   template <typename T>
5375*795d594fSAndroid Build Coastguard Worker   T ComputeIntegral(T x, T y) const {
5376*795d594fSAndroid Build Coastguard Worker     DCHECK(!DataType::IsFloatingPointType(GetType())) << GetType();
5377*795d594fSAndroid Build Coastguard Worker     // Our graph structure ensures we never have 0 for `y` during
5378*795d594fSAndroid Build Coastguard Worker     // constant folding.
5379*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(y, 0);
5380*795d594fSAndroid Build Coastguard Worker     // Special case -1 to avoid getting a SIGFPE on x86(_64).
5381*795d594fSAndroid Build Coastguard Worker     return (y == -1) ? -x : x / y;
5382*795d594fSAndroid Build Coastguard Worker   }
5383*795d594fSAndroid Build Coastguard Worker 
5384*795d594fSAndroid Build Coastguard Worker   template <typename T>
5385*795d594fSAndroid Build Coastguard Worker   T ComputeFP(T x, T y) const {
5386*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(GetType())) << GetType();
5387*795d594fSAndroid Build Coastguard Worker     return x / y;
5388*795d594fSAndroid Build Coastguard Worker   }
5389*795d594fSAndroid Build Coastguard Worker 
5390*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5391*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5392*795d594fSAndroid Build Coastguard Worker   }
5393*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5394*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5395*795d594fSAndroid Build Coastguard Worker   }
5396*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
5397*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(ComputeFP(x->GetValue(), y->GetValue()));
5398*795d594fSAndroid Build Coastguard Worker   }
5399*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
5400*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(ComputeFP(x->GetValue(), y->GetValue()));
5401*795d594fSAndroid Build Coastguard Worker   }
5402*795d594fSAndroid Build Coastguard Worker 
5403*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Div);
5404*795d594fSAndroid Build Coastguard Worker 
5405*795d594fSAndroid Build Coastguard Worker  protected:
5406*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Div);
5407*795d594fSAndroid Build Coastguard Worker };
5408*795d594fSAndroid Build Coastguard Worker 
5409*795d594fSAndroid Build Coastguard Worker class HRem final : public HBinaryOperation {
5410*795d594fSAndroid Build Coastguard Worker  public:
5411*795d594fSAndroid Build Coastguard Worker   HRem(DataType::Type result_type,
5412*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5413*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5414*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc)
5415*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kRem, result_type, left, right, SideEffects::None(), dex_pc) {
5416*795d594fSAndroid Build Coastguard Worker   }
5417*795d594fSAndroid Build Coastguard Worker 
5418*795d594fSAndroid Build Coastguard Worker   template <typename T>
5419*795d594fSAndroid Build Coastguard Worker   T ComputeIntegral(T x, T y) const {
5420*795d594fSAndroid Build Coastguard Worker     DCHECK(!DataType::IsFloatingPointType(GetType())) << GetType();
5421*795d594fSAndroid Build Coastguard Worker     // Our graph structure ensures we never have 0 for `y` during
5422*795d594fSAndroid Build Coastguard Worker     // constant folding.
5423*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(y, 0);
5424*795d594fSAndroid Build Coastguard Worker     // Special case -1 to avoid getting a SIGFPE on x86(_64).
5425*795d594fSAndroid Build Coastguard Worker     return (y == -1) ? 0 : x % y;
5426*795d594fSAndroid Build Coastguard Worker   }
5427*795d594fSAndroid Build Coastguard Worker 
5428*795d594fSAndroid Build Coastguard Worker   template <typename T>
5429*795d594fSAndroid Build Coastguard Worker   T ComputeFP(T x, T y) const {
5430*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsFloatingPointType(GetType())) << GetType();
5431*795d594fSAndroid Build Coastguard Worker     return std::fmod(x, y);
5432*795d594fSAndroid Build Coastguard Worker   }
5433*795d594fSAndroid Build Coastguard Worker 
5434*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5435*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5436*795d594fSAndroid Build Coastguard Worker   }
5437*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5438*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5439*795d594fSAndroid Build Coastguard Worker   }
5440*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x, HFloatConstant* y) const override {
5441*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(ComputeFP(x->GetValue(), y->GetValue()));
5442*795d594fSAndroid Build Coastguard Worker   }
5443*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x, HDoubleConstant* y) const override {
5444*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(ComputeFP(x->GetValue(), y->GetValue()));
5445*795d594fSAndroid Build Coastguard Worker   }
5446*795d594fSAndroid Build Coastguard Worker 
5447*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Rem);
5448*795d594fSAndroid Build Coastguard Worker 
5449*795d594fSAndroid Build Coastguard Worker  protected:
5450*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Rem);
5451*795d594fSAndroid Build Coastguard Worker };
5452*795d594fSAndroid Build Coastguard Worker 
5453*795d594fSAndroid Build Coastguard Worker class HMin final : public HBinaryOperation {
5454*795d594fSAndroid Build Coastguard Worker  public:
5455*795d594fSAndroid Build Coastguard Worker   HMin(DataType::Type result_type,
5456*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5457*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5458*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc)
5459*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kMin, result_type, left, right, SideEffects::None(), dex_pc) {}
5460*795d594fSAndroid Build Coastguard Worker 
5461*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5462*795d594fSAndroid Build Coastguard Worker 
5463*795d594fSAndroid Build Coastguard Worker   // Evaluation for integral values.
5464*795d594fSAndroid Build Coastguard Worker   template <typename T> static T ComputeIntegral(T x, T y) {
5465*795d594fSAndroid Build Coastguard Worker     return (x <= y) ? x : y;
5466*795d594fSAndroid Build Coastguard Worker   }
5467*795d594fSAndroid Build Coastguard Worker 
5468*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5469*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5470*795d594fSAndroid Build Coastguard Worker   }
5471*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5472*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5473*795d594fSAndroid Build Coastguard Worker   }
5474*795d594fSAndroid Build Coastguard Worker   // TODO: Evaluation for floating-point values.
5475*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
5476*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HFloatConstant* y) const override {
5477*795d594fSAndroid Build Coastguard Worker     return nullptr;
5478*795d594fSAndroid Build Coastguard Worker   }
5479*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
5480*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HDoubleConstant* y) const override {
5481*795d594fSAndroid Build Coastguard Worker     return nullptr;
5482*795d594fSAndroid Build Coastguard Worker   }
5483*795d594fSAndroid Build Coastguard Worker 
5484*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Min);
5485*795d594fSAndroid Build Coastguard Worker 
5486*795d594fSAndroid Build Coastguard Worker  protected:
5487*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Min);
5488*795d594fSAndroid Build Coastguard Worker };
5489*795d594fSAndroid Build Coastguard Worker 
5490*795d594fSAndroid Build Coastguard Worker class HMax final : public HBinaryOperation {
5491*795d594fSAndroid Build Coastguard Worker  public:
5492*795d594fSAndroid Build Coastguard Worker   HMax(DataType::Type result_type,
5493*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5494*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5495*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc)
5496*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kMax, result_type, left, right, SideEffects::None(), dex_pc) {}
5497*795d594fSAndroid Build Coastguard Worker 
5498*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5499*795d594fSAndroid Build Coastguard Worker 
5500*795d594fSAndroid Build Coastguard Worker   // Evaluation for integral values.
5501*795d594fSAndroid Build Coastguard Worker   template <typename T> static T ComputeIntegral(T x, T y) {
5502*795d594fSAndroid Build Coastguard Worker     return (x >= y) ? x : y;
5503*795d594fSAndroid Build Coastguard Worker   }
5504*795d594fSAndroid Build Coastguard Worker 
5505*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5506*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5507*795d594fSAndroid Build Coastguard Worker   }
5508*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5509*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(ComputeIntegral(x->GetValue(), y->GetValue()));
5510*795d594fSAndroid Build Coastguard Worker   }
5511*795d594fSAndroid Build Coastguard Worker   // TODO: Evaluation for floating-point values.
5512*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HFloatConstant* x,
5513*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HFloatConstant* y) const override {
5514*795d594fSAndroid Build Coastguard Worker     return nullptr;
5515*795d594fSAndroid Build Coastguard Worker   }
5516*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate([[maybe_unused]] HDoubleConstant* x,
5517*795d594fSAndroid Build Coastguard Worker                       [[maybe_unused]] HDoubleConstant* y) const override {
5518*795d594fSAndroid Build Coastguard Worker     return nullptr;
5519*795d594fSAndroid Build Coastguard Worker   }
5520*795d594fSAndroid Build Coastguard Worker 
5521*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Max);
5522*795d594fSAndroid Build Coastguard Worker 
5523*795d594fSAndroid Build Coastguard Worker  protected:
5524*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Max);
5525*795d594fSAndroid Build Coastguard Worker };
5526*795d594fSAndroid Build Coastguard Worker 
5527*795d594fSAndroid Build Coastguard Worker class HAbs final : public HUnaryOperation {
5528*795d594fSAndroid Build Coastguard Worker  public:
5529*795d594fSAndroid Build Coastguard Worker   HAbs(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
5530*795d594fSAndroid Build Coastguard Worker       : HUnaryOperation(kAbs, result_type, input, dex_pc) {}
5531*795d594fSAndroid Build Coastguard Worker 
5532*795d594fSAndroid Build Coastguard Worker   // Evaluation for integral values.
5533*795d594fSAndroid Build Coastguard Worker   template <typename T> static T ComputeIntegral(T x) {
5534*795d594fSAndroid Build Coastguard Worker     return x < 0 ? -x : x;
5535*795d594fSAndroid Build Coastguard Worker   }
5536*795d594fSAndroid Build Coastguard Worker 
5537*795d594fSAndroid Build Coastguard Worker   // Evaluation for floating-point values.
5538*795d594fSAndroid Build Coastguard Worker   // Note, as a "quality of implementation", rather than pure "spec compliance",
5539*795d594fSAndroid Build Coastguard Worker   // we require that Math.abs() clears the sign bit (but changes nothing else)
5540*795d594fSAndroid Build Coastguard Worker   // for all floating-point numbers, including NaN (signaling NaN may become quiet though).
5541*795d594fSAndroid Build Coastguard Worker   // http://b/30758343
5542*795d594fSAndroid Build Coastguard Worker   template <typename T, typename S> static T ComputeFP(T x) {
5543*795d594fSAndroid Build Coastguard Worker     S bits = bit_cast<S, T>(x);
5544*795d594fSAndroid Build Coastguard Worker     return bit_cast<T, S>(bits & std::numeric_limits<S>::max());
5545*795d594fSAndroid Build Coastguard Worker   }
5546*795d594fSAndroid Build Coastguard Worker 
5547*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x) const override {
5548*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(ComputeIntegral(x->GetValue()));
5549*795d594fSAndroid Build Coastguard Worker   }
5550*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x) const override {
5551*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(ComputeIntegral(x->GetValue()));
5552*795d594fSAndroid Build Coastguard Worker   }
5553*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HFloatConstant* x) const override {
5554*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetFloatConstant(ComputeFP<float, int32_t>(x->GetValue()));
5555*795d594fSAndroid Build Coastguard Worker   }
5556*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HDoubleConstant* x) const override {
5557*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetDoubleConstant(ComputeFP<double, int64_t>(x->GetValue()));
5558*795d594fSAndroid Build Coastguard Worker   }
5559*795d594fSAndroid Build Coastguard Worker 
5560*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Abs);
5561*795d594fSAndroid Build Coastguard Worker 
5562*795d594fSAndroid Build Coastguard Worker  protected:
5563*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Abs);
5564*795d594fSAndroid Build Coastguard Worker };
5565*795d594fSAndroid Build Coastguard Worker 
5566*795d594fSAndroid Build Coastguard Worker class HDivZeroCheck final : public HExpression<1> {
5567*795d594fSAndroid Build Coastguard Worker  public:
5568*795d594fSAndroid Build Coastguard Worker   // `HDivZeroCheck` can trigger GC, as it may call the `ArithmeticException`
5569*795d594fSAndroid Build Coastguard Worker   // constructor. However it can only do it on a fatal slow path so execution never returns to the
5570*795d594fSAndroid Build Coastguard Worker   // instruction following the current one; thus 'SideEffects::None()' is used.
5571*795d594fSAndroid Build Coastguard Worker   HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
5572*795d594fSAndroid Build Coastguard Worker       : HExpression(kDivZeroCheck, value->GetType(), SideEffects::None(), dex_pc) {
5573*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, value);
5574*795d594fSAndroid Build Coastguard Worker   }
5575*795d594fSAndroid Build Coastguard Worker 
5576*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5577*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
5578*795d594fSAndroid Build Coastguard Worker 
5579*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
5580*795d594fSAndroid Build Coastguard Worker     return true;
5581*795d594fSAndroid Build Coastguard Worker   }
5582*795d594fSAndroid Build Coastguard Worker 
5583*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
5584*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
5585*795d594fSAndroid Build Coastguard Worker 
5586*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(DivZeroCheck);
5587*795d594fSAndroid Build Coastguard Worker 
5588*795d594fSAndroid Build Coastguard Worker  protected:
5589*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(DivZeroCheck);
5590*795d594fSAndroid Build Coastguard Worker };
5591*795d594fSAndroid Build Coastguard Worker 
5592*795d594fSAndroid Build Coastguard Worker class HShl final : public HBinaryOperation {
5593*795d594fSAndroid Build Coastguard Worker  public:
5594*795d594fSAndroid Build Coastguard Worker   HShl(DataType::Type result_type,
5595*795d594fSAndroid Build Coastguard Worker        HInstruction* value,
5596*795d594fSAndroid Build Coastguard Worker        HInstruction* distance,
5597*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5598*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kShl, result_type, value, distance, SideEffects::None(), dex_pc) {
5599*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
5600*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
5601*795d594fSAndroid Build Coastguard Worker   }
5602*795d594fSAndroid Build Coastguard Worker 
5603*795d594fSAndroid Build Coastguard Worker   template <typename T>
5604*795d594fSAndroid Build Coastguard Worker   static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
5605*795d594fSAndroid Build Coastguard Worker     return value << (distance & max_shift_distance);
5606*795d594fSAndroid Build Coastguard Worker   }
5607*795d594fSAndroid Build Coastguard Worker 
5608*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const override {
5609*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(
5610*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance));
5611*795d594fSAndroid Build Coastguard Worker   }
5612*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const override {
5613*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(
5614*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance));
5615*795d594fSAndroid Build Coastguard Worker   }
5616*795d594fSAndroid Build Coastguard Worker 
5617*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Shl);
5618*795d594fSAndroid Build Coastguard Worker 
5619*795d594fSAndroid Build Coastguard Worker  protected:
5620*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Shl);
5621*795d594fSAndroid Build Coastguard Worker };
5622*795d594fSAndroid Build Coastguard Worker 
5623*795d594fSAndroid Build Coastguard Worker class HShr final : public HBinaryOperation {
5624*795d594fSAndroid Build Coastguard Worker  public:
5625*795d594fSAndroid Build Coastguard Worker   HShr(DataType::Type result_type,
5626*795d594fSAndroid Build Coastguard Worker        HInstruction* value,
5627*795d594fSAndroid Build Coastguard Worker        HInstruction* distance,
5628*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5629*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kShr, result_type, value, distance, SideEffects::None(), dex_pc) {
5630*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
5631*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
5632*795d594fSAndroid Build Coastguard Worker   }
5633*795d594fSAndroid Build Coastguard Worker 
5634*795d594fSAndroid Build Coastguard Worker   template <typename T>
5635*795d594fSAndroid Build Coastguard Worker   static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
5636*795d594fSAndroid Build Coastguard Worker     return value >> (distance & max_shift_distance);
5637*795d594fSAndroid Build Coastguard Worker   }
5638*795d594fSAndroid Build Coastguard Worker 
5639*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const override {
5640*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(
5641*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance));
5642*795d594fSAndroid Build Coastguard Worker   }
5643*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const override {
5644*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(
5645*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance));
5646*795d594fSAndroid Build Coastguard Worker   }
5647*795d594fSAndroid Build Coastguard Worker 
5648*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Shr);
5649*795d594fSAndroid Build Coastguard Worker 
5650*795d594fSAndroid Build Coastguard Worker  protected:
5651*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Shr);
5652*795d594fSAndroid Build Coastguard Worker };
5653*795d594fSAndroid Build Coastguard Worker 
5654*795d594fSAndroid Build Coastguard Worker class HUShr final : public HBinaryOperation {
5655*795d594fSAndroid Build Coastguard Worker  public:
5656*795d594fSAndroid Build Coastguard Worker   HUShr(DataType::Type result_type,
5657*795d594fSAndroid Build Coastguard Worker         HInstruction* value,
5658*795d594fSAndroid Build Coastguard Worker         HInstruction* distance,
5659*795d594fSAndroid Build Coastguard Worker         uint32_t dex_pc = kNoDexPc)
5660*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kUShr, result_type, value, distance, SideEffects::None(), dex_pc) {
5661*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(result_type, DataType::Kind(value->GetType()));
5662*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(distance->GetType()));
5663*795d594fSAndroid Build Coastguard Worker   }
5664*795d594fSAndroid Build Coastguard Worker 
5665*795d594fSAndroid Build Coastguard Worker   template <typename T>
5666*795d594fSAndroid Build Coastguard Worker   static T Compute(T value, int32_t distance, int32_t max_shift_distance) {
5667*795d594fSAndroid Build Coastguard Worker     using V = std::make_unsigned_t<T>;
5668*795d594fSAndroid Build Coastguard Worker     V ux = static_cast<V>(value);
5669*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(ux >> (distance & max_shift_distance));
5670*795d594fSAndroid Build Coastguard Worker   }
5671*795d594fSAndroid Build Coastguard Worker 
5672*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const override {
5673*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(
5674*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance));
5675*795d594fSAndroid Build Coastguard Worker   }
5676*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const override {
5677*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(
5678*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance));
5679*795d594fSAndroid Build Coastguard Worker   }
5680*795d594fSAndroid Build Coastguard Worker 
5681*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(UShr);
5682*795d594fSAndroid Build Coastguard Worker 
5683*795d594fSAndroid Build Coastguard Worker  protected:
5684*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UShr);
5685*795d594fSAndroid Build Coastguard Worker };
5686*795d594fSAndroid Build Coastguard Worker 
5687*795d594fSAndroid Build Coastguard Worker class HAnd final : public HBinaryOperation {
5688*795d594fSAndroid Build Coastguard Worker  public:
5689*795d594fSAndroid Build Coastguard Worker   HAnd(DataType::Type result_type,
5690*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5691*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5692*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5693*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kAnd, result_type, left, right, SideEffects::None(), dex_pc) {
5694*795d594fSAndroid Build Coastguard Worker   }
5695*795d594fSAndroid Build Coastguard Worker 
5696*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5697*795d594fSAndroid Build Coastguard Worker 
5698*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x & y; }
5699*795d594fSAndroid Build Coastguard Worker 
5700*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5701*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5702*795d594fSAndroid Build Coastguard Worker   }
5703*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5704*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5705*795d594fSAndroid Build Coastguard Worker   }
5706*795d594fSAndroid Build Coastguard Worker 
5707*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(And);
5708*795d594fSAndroid Build Coastguard Worker 
5709*795d594fSAndroid Build Coastguard Worker  protected:
5710*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(And);
5711*795d594fSAndroid Build Coastguard Worker };
5712*795d594fSAndroid Build Coastguard Worker 
5713*795d594fSAndroid Build Coastguard Worker class HOr final : public HBinaryOperation {
5714*795d594fSAndroid Build Coastguard Worker  public:
5715*795d594fSAndroid Build Coastguard Worker   HOr(DataType::Type result_type,
5716*795d594fSAndroid Build Coastguard Worker       HInstruction* left,
5717*795d594fSAndroid Build Coastguard Worker       HInstruction* right,
5718*795d594fSAndroid Build Coastguard Worker       uint32_t dex_pc = kNoDexPc)
5719*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kOr, result_type, left, right, SideEffects::None(), dex_pc) {
5720*795d594fSAndroid Build Coastguard Worker   }
5721*795d594fSAndroid Build Coastguard Worker 
5722*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5723*795d594fSAndroid Build Coastguard Worker 
5724*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x | y; }
5725*795d594fSAndroid Build Coastguard Worker 
5726*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5727*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5728*795d594fSAndroid Build Coastguard Worker   }
5729*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5730*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5731*795d594fSAndroid Build Coastguard Worker   }
5732*795d594fSAndroid Build Coastguard Worker 
5733*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Or);
5734*795d594fSAndroid Build Coastguard Worker 
5735*795d594fSAndroid Build Coastguard Worker  protected:
5736*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Or);
5737*795d594fSAndroid Build Coastguard Worker };
5738*795d594fSAndroid Build Coastguard Worker 
5739*795d594fSAndroid Build Coastguard Worker class HXor final : public HBinaryOperation {
5740*795d594fSAndroid Build Coastguard Worker  public:
5741*795d594fSAndroid Build Coastguard Worker   HXor(DataType::Type result_type,
5742*795d594fSAndroid Build Coastguard Worker        HInstruction* left,
5743*795d594fSAndroid Build Coastguard Worker        HInstruction* right,
5744*795d594fSAndroid Build Coastguard Worker        uint32_t dex_pc = kNoDexPc)
5745*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kXor, result_type, left, right, SideEffects::None(), dex_pc) {
5746*795d594fSAndroid Build Coastguard Worker   }
5747*795d594fSAndroid Build Coastguard Worker 
5748*795d594fSAndroid Build Coastguard Worker   bool IsCommutative() const override { return true; }
5749*795d594fSAndroid Build Coastguard Worker 
5750*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x, T y) { return x ^ y; }
5751*795d594fSAndroid Build Coastguard Worker 
5752*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
5753*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
5754*795d594fSAndroid Build Coastguard Worker   }
5755*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
5756*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
5757*795d594fSAndroid Build Coastguard Worker   }
5758*795d594fSAndroid Build Coastguard Worker 
5759*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Xor);
5760*795d594fSAndroid Build Coastguard Worker 
5761*795d594fSAndroid Build Coastguard Worker  protected:
5762*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Xor);
5763*795d594fSAndroid Build Coastguard Worker };
5764*795d594fSAndroid Build Coastguard Worker 
5765*795d594fSAndroid Build Coastguard Worker class HRor final : public HBinaryOperation {
5766*795d594fSAndroid Build Coastguard Worker  public:
5767*795d594fSAndroid Build Coastguard Worker   HRor(DataType::Type result_type, HInstruction* value, HInstruction* distance)
5768*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kRor, result_type, value, distance) {
5769*795d594fSAndroid Build Coastguard Worker   }
5770*795d594fSAndroid Build Coastguard Worker 
5771*795d594fSAndroid Build Coastguard Worker   template <typename T>
5772*795d594fSAndroid Build Coastguard Worker   static T Compute(T value, int32_t distance, int32_t max_shift_value) {
5773*795d594fSAndroid Build Coastguard Worker     using V = std::make_unsigned_t<T>;
5774*795d594fSAndroid Build Coastguard Worker     V ux = static_cast<V>(value);
5775*795d594fSAndroid Build Coastguard Worker     if ((distance & max_shift_value) == 0) {
5776*795d594fSAndroid Build Coastguard Worker       return static_cast<T>(ux);
5777*795d594fSAndroid Build Coastguard Worker     } else {
5778*795d594fSAndroid Build Coastguard Worker       const V reg_bits = sizeof(T) * 8;
5779*795d594fSAndroid Build Coastguard Worker       return static_cast<T>(ux >> (distance & max_shift_value)) |
5780*795d594fSAndroid Build Coastguard Worker                            (value << (reg_bits - (distance & max_shift_value)));
5781*795d594fSAndroid Build Coastguard Worker     }
5782*795d594fSAndroid Build Coastguard Worker   }
5783*795d594fSAndroid Build Coastguard Worker 
5784*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const override {
5785*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(
5786*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance));
5787*795d594fSAndroid Build Coastguard Worker   }
5788*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const override {
5789*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(
5790*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance));
5791*795d594fSAndroid Build Coastguard Worker   }
5792*795d594fSAndroid Build Coastguard Worker 
5793*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Ror);
5794*795d594fSAndroid Build Coastguard Worker 
5795*795d594fSAndroid Build Coastguard Worker  protected:
5796*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Ror);
5797*795d594fSAndroid Build Coastguard Worker };
5798*795d594fSAndroid Build Coastguard Worker 
5799*795d594fSAndroid Build Coastguard Worker class HRol final : public HBinaryOperation {
5800*795d594fSAndroid Build Coastguard Worker  public:
5801*795d594fSAndroid Build Coastguard Worker   HRol(DataType::Type result_type, HInstruction* value, HInstruction* distance)
5802*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(kRol, result_type, value, distance) {}
5803*795d594fSAndroid Build Coastguard Worker 
5804*795d594fSAndroid Build Coastguard Worker   template <typename T>
5805*795d594fSAndroid Build Coastguard Worker   static T Compute(T value, int32_t distance, int32_t max_shift_value) {
5806*795d594fSAndroid Build Coastguard Worker     return HRor::Compute(value, -distance, max_shift_value);
5807*795d594fSAndroid Build Coastguard Worker   }
5808*795d594fSAndroid Build Coastguard Worker 
5809*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* value, HIntConstant* distance) const override {
5810*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(
5811*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxIntShiftDistance));
5812*795d594fSAndroid Build Coastguard Worker   }
5813*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* value, HIntConstant* distance) const override {
5814*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(
5815*795d594fSAndroid Build Coastguard Worker         Compute(value->GetValue(), distance->GetValue(), kMaxLongShiftDistance));
5816*795d594fSAndroid Build Coastguard Worker   }
5817*795d594fSAndroid Build Coastguard Worker 
5818*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Rol);
5819*795d594fSAndroid Build Coastguard Worker 
5820*795d594fSAndroid Build Coastguard Worker  protected:
5821*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Rol);
5822*795d594fSAndroid Build Coastguard Worker };
5823*795d594fSAndroid Build Coastguard Worker 
5824*795d594fSAndroid Build Coastguard Worker // The value of a parameter in this method. Its location depends on
5825*795d594fSAndroid Build Coastguard Worker // the calling convention.
5826*795d594fSAndroid Build Coastguard Worker class HParameterValue final : public HExpression<0> {
5827*795d594fSAndroid Build Coastguard Worker  public:
5828*795d594fSAndroid Build Coastguard Worker   HParameterValue(const DexFile& dex_file,
5829*795d594fSAndroid Build Coastguard Worker                   dex::TypeIndex type_index,
5830*795d594fSAndroid Build Coastguard Worker                   uint8_t index,
5831*795d594fSAndroid Build Coastguard Worker                   DataType::Type parameter_type,
5832*795d594fSAndroid Build Coastguard Worker                   bool is_this = false)
5833*795d594fSAndroid Build Coastguard Worker       : HExpression(kParameterValue, parameter_type, SideEffects::None(), kNoDexPc),
5834*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file),
5835*795d594fSAndroid Build Coastguard Worker         type_index_(type_index),
5836*795d594fSAndroid Build Coastguard Worker         index_(index) {
5837*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsThis>(is_this);
5838*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagCanBeNull>(!is_this);
5839*795d594fSAndroid Build Coastguard Worker   }
5840*795d594fSAndroid Build Coastguard Worker 
5841*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
5842*795d594fSAndroid Build Coastguard Worker   dex::TypeIndex GetTypeIndex() const { return type_index_; }
5843*795d594fSAndroid Build Coastguard Worker   uint8_t GetIndex() const { return index_; }
5844*795d594fSAndroid Build Coastguard Worker   bool IsThis() const { return GetPackedFlag<kFlagIsThis>(); }
5845*795d594fSAndroid Build Coastguard Worker 
5846*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return GetPackedFlag<kFlagCanBeNull>(); }
5847*795d594fSAndroid Build Coastguard Worker   void SetCanBeNull(bool can_be_null) { SetPackedFlag<kFlagCanBeNull>(can_be_null); }
5848*795d594fSAndroid Build Coastguard Worker 
5849*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ParameterValue);
5850*795d594fSAndroid Build Coastguard Worker 
5851*795d594fSAndroid Build Coastguard Worker  protected:
5852*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ParameterValue);
5853*795d594fSAndroid Build Coastguard Worker 
5854*795d594fSAndroid Build Coastguard Worker  private:
5855*795d594fSAndroid Build Coastguard Worker   // Whether or not the parameter value corresponds to 'this' argument.
5856*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsThis = kNumberOfGenericPackedBits;
5857*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagCanBeNull = kFlagIsThis + 1;
5858*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfParameterValuePackedBits = kFlagCanBeNull + 1;
5859*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfParameterValuePackedBits <= kMaxNumberOfPackedBits,
5860*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
5861*795d594fSAndroid Build Coastguard Worker 
5862*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
5863*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex type_index_;
5864*795d594fSAndroid Build Coastguard Worker   // The index of this parameter in the parameters list. Must be less
5865*795d594fSAndroid Build Coastguard Worker   // than HGraph::number_of_in_vregs_.
5866*795d594fSAndroid Build Coastguard Worker   const uint8_t index_;
5867*795d594fSAndroid Build Coastguard Worker };
5868*795d594fSAndroid Build Coastguard Worker 
5869*795d594fSAndroid Build Coastguard Worker class HNot final : public HUnaryOperation {
5870*795d594fSAndroid Build Coastguard Worker  public:
5871*795d594fSAndroid Build Coastguard Worker   HNot(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
5872*795d594fSAndroid Build Coastguard Worker       : HUnaryOperation(kNot, result_type, input, dex_pc) {
5873*795d594fSAndroid Build Coastguard Worker   }
5874*795d594fSAndroid Build Coastguard Worker 
5875*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
5876*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
5877*795d594fSAndroid Build Coastguard Worker     return true;
5878*795d594fSAndroid Build Coastguard Worker   }
5879*795d594fSAndroid Build Coastguard Worker 
5880*795d594fSAndroid Build Coastguard Worker   template <typename T> static T Compute(T x) { return ~x; }
5881*795d594fSAndroid Build Coastguard Worker 
5882*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x) const override {
5883*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
5884*795d594fSAndroid Build Coastguard Worker   }
5885*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x) const override {
5886*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
5887*795d594fSAndroid Build Coastguard Worker   }
5888*795d594fSAndroid Build Coastguard Worker 
5889*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Not);
5890*795d594fSAndroid Build Coastguard Worker 
5891*795d594fSAndroid Build Coastguard Worker  protected:
5892*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Not);
5893*795d594fSAndroid Build Coastguard Worker };
5894*795d594fSAndroid Build Coastguard Worker 
5895*795d594fSAndroid Build Coastguard Worker class HBooleanNot final : public HUnaryOperation {
5896*795d594fSAndroid Build Coastguard Worker  public:
5897*795d594fSAndroid Build Coastguard Worker   explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc)
5898*795d594fSAndroid Build Coastguard Worker       : HUnaryOperation(kBooleanNot, DataType::Type::kBool, input, dex_pc) {
5899*795d594fSAndroid Build Coastguard Worker   }
5900*795d594fSAndroid Build Coastguard Worker 
5901*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
5902*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
5903*795d594fSAndroid Build Coastguard Worker     return true;
5904*795d594fSAndroid Build Coastguard Worker   }
5905*795d594fSAndroid Build Coastguard Worker 
5906*795d594fSAndroid Build Coastguard Worker   template <typename T> static bool Compute(T x) {
5907*795d594fSAndroid Build Coastguard Worker     DCHECK(IsUint<1>(x)) << x;
5908*795d594fSAndroid Build Coastguard Worker     return !x;
5909*795d594fSAndroid Build Coastguard Worker   }
5910*795d594fSAndroid Build Coastguard Worker 
5911*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x) const override {
5912*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
5913*795d594fSAndroid Build Coastguard Worker   }
5914*795d594fSAndroid Build Coastguard Worker 
5915*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(BooleanNot);
5916*795d594fSAndroid Build Coastguard Worker 
5917*795d594fSAndroid Build Coastguard Worker  protected:
5918*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BooleanNot);
5919*795d594fSAndroid Build Coastguard Worker };
5920*795d594fSAndroid Build Coastguard Worker 
5921*795d594fSAndroid Build Coastguard Worker class HTypeConversion final : public HExpression<1> {
5922*795d594fSAndroid Build Coastguard Worker  public:
5923*795d594fSAndroid Build Coastguard Worker   // Instantiate a type conversion of `input` to `result_type`.
5924*795d594fSAndroid Build Coastguard Worker   HTypeConversion(DataType::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
5925*795d594fSAndroid Build Coastguard Worker       : HExpression(kTypeConversion, result_type, SideEffects::None(), dex_pc) {
5926*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
5927*795d594fSAndroid Build Coastguard Worker     // Invariant: We should never generate a conversion to a Boolean value.
5928*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(DataType::Type::kBool, result_type);
5929*795d594fSAndroid Build Coastguard Worker   }
5930*795d594fSAndroid Build Coastguard Worker 
5931*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInput() const { return InputAt(0); }
5932*795d594fSAndroid Build Coastguard Worker   DataType::Type GetInputType() const { return GetInput()->GetType(); }
5933*795d594fSAndroid Build Coastguard Worker   DataType::Type GetResultType() const { return GetType(); }
5934*795d594fSAndroid Build Coastguard Worker 
5935*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5936*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
5937*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
5938*795d594fSAndroid Build Coastguard Worker     return true;
5939*795d594fSAndroid Build Coastguard Worker   }
5940*795d594fSAndroid Build Coastguard Worker   // Return whether the conversion is implicit. This includes conversion to the same type.
5941*795d594fSAndroid Build Coastguard Worker   bool IsImplicitConversion() const {
5942*795d594fSAndroid Build Coastguard Worker     return DataType::IsTypeConversionImplicit(GetInputType(), GetResultType());
5943*795d594fSAndroid Build Coastguard Worker   }
5944*795d594fSAndroid Build Coastguard Worker 
5945*795d594fSAndroid Build Coastguard Worker   // Try to statically evaluate the conversion and return a HConstant
5946*795d594fSAndroid Build Coastguard Worker   // containing the result.  If the input cannot be converted, return nullptr.
5947*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation() const;
5948*795d594fSAndroid Build Coastguard Worker 
5949*795d594fSAndroid Build Coastguard Worker   // Same but for `input` instead of GetInput().
5950*795d594fSAndroid Build Coastguard Worker   HConstant* TryStaticEvaluation(HInstruction* input) const;
5951*795d594fSAndroid Build Coastguard Worker 
5952*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(TypeConversion);
5953*795d594fSAndroid Build Coastguard Worker 
5954*795d594fSAndroid Build Coastguard Worker  protected:
5955*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(TypeConversion);
5956*795d594fSAndroid Build Coastguard Worker };
5957*795d594fSAndroid Build Coastguard Worker 
5958*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kNoRegNumber = -1;
5959*795d594fSAndroid Build Coastguard Worker 
5960*795d594fSAndroid Build Coastguard Worker class HNullCheck final : public HExpression<1> {
5961*795d594fSAndroid Build Coastguard Worker  public:
5962*795d594fSAndroid Build Coastguard Worker   // `HNullCheck` can trigger GC, as it may call the `NullPointerException`
5963*795d594fSAndroid Build Coastguard Worker   // constructor. However it can only do it on a fatal slow path so execution never returns to the
5964*795d594fSAndroid Build Coastguard Worker   // instruction following the current one; thus 'SideEffects::None()' is used.
5965*795d594fSAndroid Build Coastguard Worker   HNullCheck(HInstruction* value, uint32_t dex_pc)
5966*795d594fSAndroid Build Coastguard Worker       : HExpression(kNullCheck, value->GetType(), SideEffects::None(), dex_pc) {
5967*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, value);
5968*795d594fSAndroid Build Coastguard Worker   }
5969*795d594fSAndroid Build Coastguard Worker 
5970*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
5971*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
5972*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
5973*795d594fSAndroid Build Coastguard Worker     return true;
5974*795d594fSAndroid Build Coastguard Worker   }
5975*795d594fSAndroid Build Coastguard Worker 
5976*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
5977*795d594fSAndroid Build Coastguard Worker 
5978*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
5979*795d594fSAndroid Build Coastguard Worker 
5980*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
5981*795d594fSAndroid Build Coastguard Worker 
5982*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(NullCheck);
5983*795d594fSAndroid Build Coastguard Worker 
5984*795d594fSAndroid Build Coastguard Worker  protected:
5985*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(NullCheck);
5986*795d594fSAndroid Build Coastguard Worker };
5987*795d594fSAndroid Build Coastguard Worker 
5988*795d594fSAndroid Build Coastguard Worker // Embeds an ArtField and all the information required by the compiler. We cache
5989*795d594fSAndroid Build Coastguard Worker // that information to avoid requiring the mutator lock every time we need it.
5990*795d594fSAndroid Build Coastguard Worker class FieldInfo : public ValueObject {
5991*795d594fSAndroid Build Coastguard Worker  public:
5992*795d594fSAndroid Build Coastguard Worker   FieldInfo(ArtField* field,
5993*795d594fSAndroid Build Coastguard Worker             MemberOffset field_offset,
5994*795d594fSAndroid Build Coastguard Worker             DataType::Type field_type,
5995*795d594fSAndroid Build Coastguard Worker             bool is_volatile,
5996*795d594fSAndroid Build Coastguard Worker             uint32_t index,
5997*795d594fSAndroid Build Coastguard Worker             uint16_t declaring_class_def_index,
5998*795d594fSAndroid Build Coastguard Worker             const DexFile& dex_file)
5999*795d594fSAndroid Build Coastguard Worker       : field_(field),
6000*795d594fSAndroid Build Coastguard Worker         field_offset_(field_offset),
6001*795d594fSAndroid Build Coastguard Worker         field_type_(field_type),
6002*795d594fSAndroid Build Coastguard Worker         is_volatile_(is_volatile),
6003*795d594fSAndroid Build Coastguard Worker         index_(index),
6004*795d594fSAndroid Build Coastguard Worker         declaring_class_def_index_(declaring_class_def_index),
6005*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file) {}
6006*795d594fSAndroid Build Coastguard Worker 
6007*795d594fSAndroid Build Coastguard Worker   ArtField* GetField() const { return field_; }
6008*795d594fSAndroid Build Coastguard Worker   MemberOffset GetFieldOffset() const { return field_offset_; }
6009*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return field_type_; }
6010*795d594fSAndroid Build Coastguard Worker   uint32_t GetFieldIndex() const { return index_; }
6011*795d594fSAndroid Build Coastguard Worker   uint16_t GetDeclaringClassDefIndex() const { return declaring_class_def_index_;}
6012*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
6013*795d594fSAndroid Build Coastguard Worker   bool IsVolatile() const { return is_volatile_; }
6014*795d594fSAndroid Build Coastguard Worker 
6015*795d594fSAndroid Build Coastguard Worker   bool Equals(const FieldInfo& other) const {
6016*795d594fSAndroid Build Coastguard Worker     return field_ == other.field_ &&
6017*795d594fSAndroid Build Coastguard Worker            field_offset_ == other.field_offset_ &&
6018*795d594fSAndroid Build Coastguard Worker            field_type_ == other.field_type_ &&
6019*795d594fSAndroid Build Coastguard Worker            is_volatile_ == other.is_volatile_ &&
6020*795d594fSAndroid Build Coastguard Worker            index_ == other.index_ &&
6021*795d594fSAndroid Build Coastguard Worker            declaring_class_def_index_ == other.declaring_class_def_index_ &&
6022*795d594fSAndroid Build Coastguard Worker            &dex_file_ == &other.dex_file_;
6023*795d594fSAndroid Build Coastguard Worker   }
6024*795d594fSAndroid Build Coastguard Worker 
6025*795d594fSAndroid Build Coastguard Worker   std::ostream& Dump(std::ostream& os) const {
6026*795d594fSAndroid Build Coastguard Worker     os << field_ << ", off: " << field_offset_ << ", type: " << field_type_
6027*795d594fSAndroid Build Coastguard Worker        << ", volatile: " << std::boolalpha << is_volatile_ << ", index_: " << std::dec << index_
6028*795d594fSAndroid Build Coastguard Worker        << ", declaring_class: " << declaring_class_def_index_ << ", dex: " << dex_file_;
6029*795d594fSAndroid Build Coastguard Worker     return os;
6030*795d594fSAndroid Build Coastguard Worker   }
6031*795d594fSAndroid Build Coastguard Worker 
6032*795d594fSAndroid Build Coastguard Worker  private:
6033*795d594fSAndroid Build Coastguard Worker   ArtField* const field_;
6034*795d594fSAndroid Build Coastguard Worker   const MemberOffset field_offset_;
6035*795d594fSAndroid Build Coastguard Worker   const DataType::Type field_type_;
6036*795d594fSAndroid Build Coastguard Worker   const bool is_volatile_;
6037*795d594fSAndroid Build Coastguard Worker   const uint32_t index_;
6038*795d594fSAndroid Build Coastguard Worker   const uint16_t declaring_class_def_index_;
6039*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
6040*795d594fSAndroid Build Coastguard Worker };
6041*795d594fSAndroid Build Coastguard Worker 
6042*795d594fSAndroid Build Coastguard Worker inline bool operator==(const FieldInfo& a, const FieldInfo& b) {
6043*795d594fSAndroid Build Coastguard Worker   return a.Equals(b);
6044*795d594fSAndroid Build Coastguard Worker }
6045*795d594fSAndroid Build Coastguard Worker 
6046*795d594fSAndroid Build Coastguard Worker inline std::ostream& operator<<(std::ostream& os, const FieldInfo& a) {
6047*795d594fSAndroid Build Coastguard Worker   return a.Dump(os);
6048*795d594fSAndroid Build Coastguard Worker }
6049*795d594fSAndroid Build Coastguard Worker 
6050*795d594fSAndroid Build Coastguard Worker class HInstanceFieldGet final : public HExpression<1> {
6051*795d594fSAndroid Build Coastguard Worker  public:
6052*795d594fSAndroid Build Coastguard Worker   HInstanceFieldGet(HInstruction* object,
6053*795d594fSAndroid Build Coastguard Worker                     ArtField* field,
6054*795d594fSAndroid Build Coastguard Worker                     DataType::Type field_type,
6055*795d594fSAndroid Build Coastguard Worker                     MemberOffset field_offset,
6056*795d594fSAndroid Build Coastguard Worker                     bool is_volatile,
6057*795d594fSAndroid Build Coastguard Worker                     uint32_t field_idx,
6058*795d594fSAndroid Build Coastguard Worker                     uint16_t declaring_class_def_index,
6059*795d594fSAndroid Build Coastguard Worker                     const DexFile& dex_file,
6060*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
6061*795d594fSAndroid Build Coastguard Worker       : HExpression(kInstanceFieldGet,
6062*795d594fSAndroid Build Coastguard Worker                     field_type,
6063*795d594fSAndroid Build Coastguard Worker                     SideEffects::FieldReadOfType(field_type, is_volatile),
6064*795d594fSAndroid Build Coastguard Worker                     dex_pc),
6065*795d594fSAndroid Build Coastguard Worker         field_info_(field,
6066*795d594fSAndroid Build Coastguard Worker                     field_offset,
6067*795d594fSAndroid Build Coastguard Worker                     field_type,
6068*795d594fSAndroid Build Coastguard Worker                     is_volatile,
6069*795d594fSAndroid Build Coastguard Worker                     field_idx,
6070*795d594fSAndroid Build Coastguard Worker                     declaring_class_def_index,
6071*795d594fSAndroid Build Coastguard Worker                     dex_file) {
6072*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, object);
6073*795d594fSAndroid Build Coastguard Worker   }
6074*795d594fSAndroid Build Coastguard Worker 
6075*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6076*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return !IsVolatile(); }
6077*795d594fSAndroid Build Coastguard Worker 
6078*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
6079*795d594fSAndroid Build Coastguard Worker     const HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
6080*795d594fSAndroid Build Coastguard Worker     return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
6081*795d594fSAndroid Build Coastguard Worker   }
6082*795d594fSAndroid Build Coastguard Worker 
6083*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
6084*795d594fSAndroid Build Coastguard Worker     return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
6085*795d594fSAndroid Build Coastguard Worker   }
6086*795d594fSAndroid Build Coastguard Worker 
6087*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override {
6088*795d594fSAndroid Build Coastguard Worker     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
6089*795d594fSAndroid Build Coastguard Worker   }
6090*795d594fSAndroid Build Coastguard Worker 
6091*795d594fSAndroid Build Coastguard Worker   bool IsFieldAccess() const override { return true; }
6092*795d594fSAndroid Build Coastguard Worker   const FieldInfo& GetFieldInfo() const override { return field_info_; }
6093*795d594fSAndroid Build Coastguard Worker   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
6094*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
6095*795d594fSAndroid Build Coastguard Worker   bool IsVolatile() const { return field_info_.IsVolatile(); }
6096*795d594fSAndroid Build Coastguard Worker 
6097*795d594fSAndroid Build Coastguard Worker   void SetType(DataType::Type new_type) {
6098*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(GetType()));
6099*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(new_type));
6100*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Size(GetType()), DataType::Size(new_type));
6101*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(new_type);
6102*795d594fSAndroid Build Coastguard Worker   }
6103*795d594fSAndroid Build Coastguard Worker 
6104*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InstanceFieldGet);
6105*795d594fSAndroid Build Coastguard Worker 
6106*795d594fSAndroid Build Coastguard Worker  protected:
6107*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InstanceFieldGet);
6108*795d594fSAndroid Build Coastguard Worker 
6109*795d594fSAndroid Build Coastguard Worker  private:
6110*795d594fSAndroid Build Coastguard Worker   const FieldInfo field_info_;
6111*795d594fSAndroid Build Coastguard Worker };
6112*795d594fSAndroid Build Coastguard Worker 
6113*795d594fSAndroid Build Coastguard Worker enum class WriteBarrierKind {
6114*795d594fSAndroid Build Coastguard Worker   // Emit the write barrier. This write barrier is not being relied on so e.g. codegen can decide to
6115*795d594fSAndroid Build Coastguard Worker   // skip it if the value stored is null. This is the default behavior.
6116*795d594fSAndroid Build Coastguard Worker   kEmitNotBeingReliedOn,
6117*795d594fSAndroid Build Coastguard Worker   // Emit the write barrier. This write barrier is being relied on and must be emitted.
6118*795d594fSAndroid Build Coastguard Worker   kEmitBeingReliedOn,
6119*795d594fSAndroid Build Coastguard Worker   // Skip emitting the write barrier. This could be set because:
6120*795d594fSAndroid Build Coastguard Worker   //  A) The write barrier is not needed (i.e. it is not a reference, or the value is the null
6121*795d594fSAndroid Build Coastguard Worker   //  constant)
6122*795d594fSAndroid Build Coastguard Worker   //  B) This write barrier was coalesced into another one so there's no need to emit it.
6123*795d594fSAndroid Build Coastguard Worker   kDontEmit,
6124*795d594fSAndroid Build Coastguard Worker   kLast = kDontEmit
6125*795d594fSAndroid Build Coastguard Worker };
6126*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, WriteBarrierKind rhs);
6127*795d594fSAndroid Build Coastguard Worker 
6128*795d594fSAndroid Build Coastguard Worker class HInstanceFieldSet final : public HExpression<2> {
6129*795d594fSAndroid Build Coastguard Worker  public:
6130*795d594fSAndroid Build Coastguard Worker   HInstanceFieldSet(HInstruction* object,
6131*795d594fSAndroid Build Coastguard Worker                     HInstruction* value,
6132*795d594fSAndroid Build Coastguard Worker                     ArtField* field,
6133*795d594fSAndroid Build Coastguard Worker                     DataType::Type field_type,
6134*795d594fSAndroid Build Coastguard Worker                     MemberOffset field_offset,
6135*795d594fSAndroid Build Coastguard Worker                     bool is_volatile,
6136*795d594fSAndroid Build Coastguard Worker                     uint32_t field_idx,
6137*795d594fSAndroid Build Coastguard Worker                     uint16_t declaring_class_def_index,
6138*795d594fSAndroid Build Coastguard Worker                     const DexFile& dex_file,
6139*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
6140*795d594fSAndroid Build Coastguard Worker       : HExpression(kInstanceFieldSet,
6141*795d594fSAndroid Build Coastguard Worker                     SideEffects::FieldWriteOfType(field_type, is_volatile),
6142*795d594fSAndroid Build Coastguard Worker                     dex_pc),
6143*795d594fSAndroid Build Coastguard Worker         field_info_(field,
6144*795d594fSAndroid Build Coastguard Worker                     field_offset,
6145*795d594fSAndroid Build Coastguard Worker                     field_type,
6146*795d594fSAndroid Build Coastguard Worker                     is_volatile,
6147*795d594fSAndroid Build Coastguard Worker                     field_idx,
6148*795d594fSAndroid Build Coastguard Worker                     declaring_class_def_index,
6149*795d594fSAndroid Build Coastguard Worker                     dex_file) {
6150*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValueCanBeNull>(true);
6151*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
6152*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, object);
6153*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, value);
6154*795d594fSAndroid Build Coastguard Worker   }
6155*795d594fSAndroid Build Coastguard Worker 
6156*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6157*795d594fSAndroid Build Coastguard Worker 
6158*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
6159*795d594fSAndroid Build Coastguard Worker     return (obj == InputAt(0)) && art::CanDoImplicitNullCheckOn(GetFieldOffset().Uint32Value());
6160*795d594fSAndroid Build Coastguard Worker   }
6161*795d594fSAndroid Build Coastguard Worker 
6162*795d594fSAndroid Build Coastguard Worker   bool IsFieldAccess() const override { return true; }
6163*795d594fSAndroid Build Coastguard Worker   const FieldInfo& GetFieldInfo() const override { return field_info_; }
6164*795d594fSAndroid Build Coastguard Worker   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
6165*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
6166*795d594fSAndroid Build Coastguard Worker   bool IsVolatile() const { return field_info_.IsVolatile(); }
6167*795d594fSAndroid Build Coastguard Worker   HInstruction* GetValue() const { return InputAt(1); }
6168*795d594fSAndroid Build Coastguard Worker   bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
6169*795d594fSAndroid Build Coastguard Worker   void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
6170*795d594fSAndroid Build Coastguard Worker   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
6171*795d594fSAndroid Build Coastguard Worker   void SetWriteBarrierKind(WriteBarrierKind kind) {
6172*795d594fSAndroid Build Coastguard Worker     DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
6173*795d594fSAndroid Build Coastguard Worker         << "We shouldn't go back to the original value.";
6174*795d594fSAndroid Build Coastguard Worker     DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
6175*795d594fSAndroid Build Coastguard Worker                    GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
6176*795d594fSAndroid Build Coastguard Worker         << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
6177*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(kind);
6178*795d594fSAndroid Build Coastguard Worker   }
6179*795d594fSAndroid Build Coastguard Worker 
6180*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InstanceFieldSet);
6181*795d594fSAndroid Build Coastguard Worker 
6182*795d594fSAndroid Build Coastguard Worker  protected:
6183*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InstanceFieldSet);
6184*795d594fSAndroid Build Coastguard Worker 
6185*795d594fSAndroid Build Coastguard Worker  private:
6186*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
6187*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKind = kFlagValueCanBeNull + 1;
6188*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKindSize =
6189*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(WriteBarrierKind::kLast));
6190*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfInstanceFieldSetPackedBits =
6191*795d594fSAndroid Build Coastguard Worker       kWriteBarrierKind + kWriteBarrierKindSize;
6192*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfInstanceFieldSetPackedBits <= kMaxNumberOfPackedBits,
6193*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
6194*795d594fSAndroid Build Coastguard Worker 
6195*795d594fSAndroid Build Coastguard Worker   const FieldInfo field_info_;
6196*795d594fSAndroid Build Coastguard Worker   using WriteBarrierKindField =
6197*795d594fSAndroid Build Coastguard Worker       BitField<WriteBarrierKind, kWriteBarrierKind, kWriteBarrierKindSize>;
6198*795d594fSAndroid Build Coastguard Worker };
6199*795d594fSAndroid Build Coastguard Worker 
6200*795d594fSAndroid Build Coastguard Worker class HArrayGet final : public HExpression<2> {
6201*795d594fSAndroid Build Coastguard Worker  public:
6202*795d594fSAndroid Build Coastguard Worker   HArrayGet(HInstruction* array,
6203*795d594fSAndroid Build Coastguard Worker             HInstruction* index,
6204*795d594fSAndroid Build Coastguard Worker             DataType::Type type,
6205*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc)
6206*795d594fSAndroid Build Coastguard Worker       : HArrayGet(array,
6207*795d594fSAndroid Build Coastguard Worker                   index,
6208*795d594fSAndroid Build Coastguard Worker                   type,
6209*795d594fSAndroid Build Coastguard Worker                   SideEffects::ArrayReadOfType(type),
6210*795d594fSAndroid Build Coastguard Worker                   dex_pc,
6211*795d594fSAndroid Build Coastguard Worker                   /* is_string_char_at= */ false) {
6212*795d594fSAndroid Build Coastguard Worker   }
6213*795d594fSAndroid Build Coastguard Worker 
6214*795d594fSAndroid Build Coastguard Worker   HArrayGet(HInstruction* array,
6215*795d594fSAndroid Build Coastguard Worker             HInstruction* index,
6216*795d594fSAndroid Build Coastguard Worker             DataType::Type type,
6217*795d594fSAndroid Build Coastguard Worker             SideEffects side_effects,
6218*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc,
6219*795d594fSAndroid Build Coastguard Worker             bool is_string_char_at)
6220*795d594fSAndroid Build Coastguard Worker       : HExpression(kArrayGet, type, side_effects, dex_pc) {
6221*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
6222*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, array);
6223*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, index);
6224*795d594fSAndroid Build Coastguard Worker   }
6225*795d594fSAndroid Build Coastguard Worker 
6226*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6227*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
6228*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
6229*795d594fSAndroid Build Coastguard Worker     return true;
6230*795d594fSAndroid Build Coastguard Worker   }
6231*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
6232*795d594fSAndroid Build Coastguard Worker     // TODO: We can be smarter here.
6233*795d594fSAndroid Build Coastguard Worker     // Currently, unless the array is the result of NewArray, the array access is always
6234*795d594fSAndroid Build Coastguard Worker     // preceded by some form of null NullCheck necessary for the bounds check, usually
6235*795d594fSAndroid Build Coastguard Worker     // implicit null check on the ArrayLength input to BoundsCheck or Deoptimize for
6236*795d594fSAndroid Build Coastguard Worker     // dynamic BCE. There are cases when these could be removed to produce better code.
6237*795d594fSAndroid Build Coastguard Worker     // If we ever add optimizations to do so we should allow an implicit check here
6238*795d594fSAndroid Build Coastguard Worker     // (as long as the address falls in the first page).
6239*795d594fSAndroid Build Coastguard Worker     //
6240*795d594fSAndroid Build Coastguard Worker     // As an example of such fancy optimization, we could eliminate BoundsCheck for
6241*795d594fSAndroid Build Coastguard Worker     //     a = cond ? new int[1] : null;
6242*795d594fSAndroid Build Coastguard Worker     //     a[0];  // The Phi does not need bounds check for either input.
6243*795d594fSAndroid Build Coastguard Worker     return false;
6244*795d594fSAndroid Build Coastguard Worker   }
6245*795d594fSAndroid Build Coastguard Worker 
6246*795d594fSAndroid Build Coastguard Worker   bool IsEquivalentOf(HArrayGet* other) const {
6247*795d594fSAndroid Build Coastguard Worker     bool result = (GetDexPc() == other->GetDexPc());
6248*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild && result) {
6249*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(GetBlock(), other->GetBlock());
6250*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(GetArray(), other->GetArray());
6251*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(GetIndex(), other->GetIndex());
6252*795d594fSAndroid Build Coastguard Worker       if (DataType::IsIntOrLongType(GetType())) {
6253*795d594fSAndroid Build Coastguard Worker         DCHECK(DataType::IsFloatingPointType(other->GetType())) << other->GetType();
6254*795d594fSAndroid Build Coastguard Worker       } else {
6255*795d594fSAndroid Build Coastguard Worker         DCHECK(DataType::IsFloatingPointType(GetType())) << GetType();
6256*795d594fSAndroid Build Coastguard Worker         DCHECK(DataType::IsIntOrLongType(other->GetType())) << other->GetType();
6257*795d594fSAndroid Build Coastguard Worker       }
6258*795d594fSAndroid Build Coastguard Worker     }
6259*795d594fSAndroid Build Coastguard Worker     return result;
6260*795d594fSAndroid Build Coastguard Worker   }
6261*795d594fSAndroid Build Coastguard Worker 
6262*795d594fSAndroid Build Coastguard Worker   bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); }
6263*795d594fSAndroid Build Coastguard Worker 
6264*795d594fSAndroid Build Coastguard Worker   HInstruction* GetArray() const { return InputAt(0); }
6265*795d594fSAndroid Build Coastguard Worker   HInstruction* GetIndex() const { return InputAt(1); }
6266*795d594fSAndroid Build Coastguard Worker 
6267*795d594fSAndroid Build Coastguard Worker   void SetType(DataType::Type new_type) {
6268*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(GetType()));
6269*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(new_type));
6270*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Size(GetType()), DataType::Size(new_type));
6271*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(new_type);
6272*795d594fSAndroid Build Coastguard Worker   }
6273*795d594fSAndroid Build Coastguard Worker 
6274*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ArrayGet);
6275*795d594fSAndroid Build Coastguard Worker 
6276*795d594fSAndroid Build Coastguard Worker  protected:
6277*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ArrayGet);
6278*795d594fSAndroid Build Coastguard Worker 
6279*795d594fSAndroid Build Coastguard Worker  private:
6280*795d594fSAndroid Build Coastguard Worker   // We treat a String as an array, creating the HArrayGet from String.charAt()
6281*795d594fSAndroid Build Coastguard Worker   // intrinsic in the instruction simplifier. We can always determine whether
6282*795d594fSAndroid Build Coastguard Worker   // a particular HArrayGet is actually a String.charAt() by looking at the type
6283*795d594fSAndroid Build Coastguard Worker   // of the input but that requires holding the mutator lock, so we prefer to use
6284*795d594fSAndroid Build Coastguard Worker   // a flag, so that code generators don't need to do the locking.
6285*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsStringCharAt = kNumberOfGenericPackedBits;
6286*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfArrayGetPackedBits = kFlagIsStringCharAt + 1;
6287*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfArrayGetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6288*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
6289*795d594fSAndroid Build Coastguard Worker };
6290*795d594fSAndroid Build Coastguard Worker 
6291*795d594fSAndroid Build Coastguard Worker class HArraySet final : public HExpression<3> {
6292*795d594fSAndroid Build Coastguard Worker  public:
6293*795d594fSAndroid Build Coastguard Worker   HArraySet(HInstruction* array,
6294*795d594fSAndroid Build Coastguard Worker             HInstruction* index,
6295*795d594fSAndroid Build Coastguard Worker             HInstruction* value,
6296*795d594fSAndroid Build Coastguard Worker             DataType::Type expected_component_type,
6297*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc)
6298*795d594fSAndroid Build Coastguard Worker       : HArraySet(array,
6299*795d594fSAndroid Build Coastguard Worker                   index,
6300*795d594fSAndroid Build Coastguard Worker                   value,
6301*795d594fSAndroid Build Coastguard Worker                   expected_component_type,
6302*795d594fSAndroid Build Coastguard Worker                   // Make a best guess for side effects now, may be refined during SSA building.
6303*795d594fSAndroid Build Coastguard Worker                   ComputeSideEffects(GetComponentType(value->GetType(), expected_component_type)),
6304*795d594fSAndroid Build Coastguard Worker                   dex_pc) {
6305*795d594fSAndroid Build Coastguard Worker   }
6306*795d594fSAndroid Build Coastguard Worker 
6307*795d594fSAndroid Build Coastguard Worker   HArraySet(HInstruction* array,
6308*795d594fSAndroid Build Coastguard Worker             HInstruction* index,
6309*795d594fSAndroid Build Coastguard Worker             HInstruction* value,
6310*795d594fSAndroid Build Coastguard Worker             DataType::Type expected_component_type,
6311*795d594fSAndroid Build Coastguard Worker             SideEffects side_effects,
6312*795d594fSAndroid Build Coastguard Worker             uint32_t dex_pc)
6313*795d594fSAndroid Build Coastguard Worker       : HExpression(kArraySet, side_effects, dex_pc) {
6314*795d594fSAndroid Build Coastguard Worker     SetPackedField<ExpectedComponentTypeField>(expected_component_type);
6315*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagNeedsTypeCheck>(value->GetType() == DataType::Type::kReference);
6316*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValueCanBeNull>(true);
6317*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(false);
6318*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
6319*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, array);
6320*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, index);
6321*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, value);
6322*795d594fSAndroid Build Coastguard Worker   }
6323*795d594fSAndroid Build Coastguard Worker 
6324*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6325*795d594fSAndroid Build Coastguard Worker 
6326*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
6327*795d594fSAndroid Build Coastguard Worker     // We call a runtime method to throw ArrayStoreException.
6328*795d594fSAndroid Build Coastguard Worker     return NeedsTypeCheck();
6329*795d594fSAndroid Build Coastguard Worker   }
6330*795d594fSAndroid Build Coastguard Worker 
6331*795d594fSAndroid Build Coastguard Worker   // Can throw ArrayStoreException.
6332*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return NeedsTypeCheck(); }
6333*795d594fSAndroid Build Coastguard Worker 
6334*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn([[maybe_unused]] HInstruction* obj) const override {
6335*795d594fSAndroid Build Coastguard Worker     // TODO: Same as for ArrayGet.
6336*795d594fSAndroid Build Coastguard Worker     return false;
6337*795d594fSAndroid Build Coastguard Worker   }
6338*795d594fSAndroid Build Coastguard Worker 
6339*795d594fSAndroid Build Coastguard Worker   void ClearTypeCheck() {
6340*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagNeedsTypeCheck>(false);
6341*795d594fSAndroid Build Coastguard Worker     // Clear the `CanTriggerGC` flag too as we can only trigger a GC when doing a type check.
6342*795d594fSAndroid Build Coastguard Worker     SetSideEffects(GetSideEffects().Exclusion(SideEffects::CanTriggerGC()));
6343*795d594fSAndroid Build Coastguard Worker     // Clear the environment too as we can only throw if we need a type check.
6344*795d594fSAndroid Build Coastguard Worker     RemoveEnvironment();
6345*795d594fSAndroid Build Coastguard Worker   }
6346*795d594fSAndroid Build Coastguard Worker 
6347*795d594fSAndroid Build Coastguard Worker   void ClearValueCanBeNull() {
6348*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValueCanBeNull>(false);
6349*795d594fSAndroid Build Coastguard Worker   }
6350*795d594fSAndroid Build Coastguard Worker 
6351*795d594fSAndroid Build Coastguard Worker   void SetStaticTypeOfArrayIsObjectArray() {
6352*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>(true);
6353*795d594fSAndroid Build Coastguard Worker   }
6354*795d594fSAndroid Build Coastguard Worker 
6355*795d594fSAndroid Build Coastguard Worker   bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
6356*795d594fSAndroid Build Coastguard Worker   bool NeedsTypeCheck() const { return GetPackedFlag<kFlagNeedsTypeCheck>(); }
6357*795d594fSAndroid Build Coastguard Worker   bool StaticTypeOfArrayIsObjectArray() const {
6358*795d594fSAndroid Build Coastguard Worker     return GetPackedFlag<kFlagStaticTypeOfArrayIsObjectArray>();
6359*795d594fSAndroid Build Coastguard Worker   }
6360*795d594fSAndroid Build Coastguard Worker 
6361*795d594fSAndroid Build Coastguard Worker   HInstruction* GetArray() const { return InputAt(0); }
6362*795d594fSAndroid Build Coastguard Worker   HInstruction* GetIndex() const { return InputAt(1); }
6363*795d594fSAndroid Build Coastguard Worker   HInstruction* GetValue() const { return InputAt(2); }
6364*795d594fSAndroid Build Coastguard Worker 
6365*795d594fSAndroid Build Coastguard Worker   DataType::Type GetComponentType() const {
6366*795d594fSAndroid Build Coastguard Worker     return GetComponentType(GetValue()->GetType(), GetRawExpectedComponentType());
6367*795d594fSAndroid Build Coastguard Worker   }
6368*795d594fSAndroid Build Coastguard Worker 
6369*795d594fSAndroid Build Coastguard Worker   static DataType::Type GetComponentType(DataType::Type value_type,
6370*795d594fSAndroid Build Coastguard Worker                                          DataType::Type expected_component_type) {
6371*795d594fSAndroid Build Coastguard Worker     // The Dex format does not type floating point index operations. Since the
6372*795d594fSAndroid Build Coastguard Worker     // `expected_component_type` comes from SSA building and can therefore not
6373*795d594fSAndroid Build Coastguard Worker     // be correct, we also check what is the value type. If it is a floating
6374*795d594fSAndroid Build Coastguard Worker     // point type, we must use that type.
6375*795d594fSAndroid Build Coastguard Worker     return ((value_type == DataType::Type::kFloat32) || (value_type == DataType::Type::kFloat64))
6376*795d594fSAndroid Build Coastguard Worker         ? value_type
6377*795d594fSAndroid Build Coastguard Worker         : expected_component_type;
6378*795d594fSAndroid Build Coastguard Worker   }
6379*795d594fSAndroid Build Coastguard Worker 
6380*795d594fSAndroid Build Coastguard Worker   DataType::Type GetRawExpectedComponentType() const {
6381*795d594fSAndroid Build Coastguard Worker     return GetPackedField<ExpectedComponentTypeField>();
6382*795d594fSAndroid Build Coastguard Worker   }
6383*795d594fSAndroid Build Coastguard Worker 
6384*795d594fSAndroid Build Coastguard Worker   static SideEffects ComputeSideEffects(DataType::Type type) {
6385*795d594fSAndroid Build Coastguard Worker     return SideEffects::ArrayWriteOfType(type).Union(SideEffectsForArchRuntimeCalls(type));
6386*795d594fSAndroid Build Coastguard Worker   }
6387*795d594fSAndroid Build Coastguard Worker 
6388*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls(DataType::Type value_type) {
6389*795d594fSAndroid Build Coastguard Worker     return (value_type == DataType::Type::kReference) ? SideEffects::CanTriggerGC()
6390*795d594fSAndroid Build Coastguard Worker                                                       : SideEffects::None();
6391*795d594fSAndroid Build Coastguard Worker   }
6392*795d594fSAndroid Build Coastguard Worker 
6393*795d594fSAndroid Build Coastguard Worker   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
6394*795d594fSAndroid Build Coastguard Worker 
6395*795d594fSAndroid Build Coastguard Worker   void SetWriteBarrierKind(WriteBarrierKind kind) {
6396*795d594fSAndroid Build Coastguard Worker     DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
6397*795d594fSAndroid Build Coastguard Worker         << "We shouldn't go back to the original value.";
6398*795d594fSAndroid Build Coastguard Worker     DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
6399*795d594fSAndroid Build Coastguard Worker                    GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
6400*795d594fSAndroid Build Coastguard Worker         << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
6401*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(kind);
6402*795d594fSAndroid Build Coastguard Worker   }
6403*795d594fSAndroid Build Coastguard Worker 
6404*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ArraySet);
6405*795d594fSAndroid Build Coastguard Worker 
6406*795d594fSAndroid Build Coastguard Worker  protected:
6407*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ArraySet);
6408*795d594fSAndroid Build Coastguard Worker 
6409*795d594fSAndroid Build Coastguard Worker  private:
6410*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldExpectedComponentType = kNumberOfGenericPackedBits;
6411*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldExpectedComponentTypeSize =
6412*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
6413*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagNeedsTypeCheck =
6414*795d594fSAndroid Build Coastguard Worker       kFieldExpectedComponentType + kFieldExpectedComponentTypeSize;
6415*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagValueCanBeNull = kFlagNeedsTypeCheck + 1;
6416*795d594fSAndroid Build Coastguard Worker   // Cached information for the reference_type_info_ so that codegen
6417*795d594fSAndroid Build Coastguard Worker   // does not need to inspect the static type.
6418*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagStaticTypeOfArrayIsObjectArray = kFlagValueCanBeNull + 1;
6419*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKind = kFlagStaticTypeOfArrayIsObjectArray + 1;
6420*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKindSize =
6421*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(WriteBarrierKind::kLast));
6422*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfArraySetPackedBits = kWriteBarrierKind + kWriteBarrierKindSize;
6423*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfArraySetPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
6424*795d594fSAndroid Build Coastguard Worker   using ExpectedComponentTypeField =
6425*795d594fSAndroid Build Coastguard Worker       BitField<DataType::Type, kFieldExpectedComponentType, kFieldExpectedComponentTypeSize>;
6426*795d594fSAndroid Build Coastguard Worker 
6427*795d594fSAndroid Build Coastguard Worker   using WriteBarrierKindField =
6428*795d594fSAndroid Build Coastguard Worker       BitField<WriteBarrierKind, kWriteBarrierKind, kWriteBarrierKindSize>;
6429*795d594fSAndroid Build Coastguard Worker };
6430*795d594fSAndroid Build Coastguard Worker 
6431*795d594fSAndroid Build Coastguard Worker class HArrayLength final : public HExpression<1> {
6432*795d594fSAndroid Build Coastguard Worker  public:
6433*795d594fSAndroid Build Coastguard Worker   HArrayLength(HInstruction* array, uint32_t dex_pc, bool is_string_length = false)
6434*795d594fSAndroid Build Coastguard Worker       : HExpression(kArrayLength, DataType::Type::kInt32, SideEffects::None(), dex_pc) {
6435*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsStringLength>(is_string_length);
6436*795d594fSAndroid Build Coastguard Worker     // Note that arrays do not change length, so the instruction does not
6437*795d594fSAndroid Build Coastguard Worker     // depend on any write.
6438*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, array);
6439*795d594fSAndroid Build Coastguard Worker   }
6440*795d594fSAndroid Build Coastguard Worker 
6441*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6442*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
6443*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
6444*795d594fSAndroid Build Coastguard Worker     return true;
6445*795d594fSAndroid Build Coastguard Worker   }
6446*795d594fSAndroid Build Coastguard Worker   bool CanDoImplicitNullCheckOn(HInstruction* obj) const override {
6447*795d594fSAndroid Build Coastguard Worker     return obj == InputAt(0);
6448*795d594fSAndroid Build Coastguard Worker   }
6449*795d594fSAndroid Build Coastguard Worker 
6450*795d594fSAndroid Build Coastguard Worker   bool IsStringLength() const { return GetPackedFlag<kFlagIsStringLength>(); }
6451*795d594fSAndroid Build Coastguard Worker 
6452*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ArrayLength);
6453*795d594fSAndroid Build Coastguard Worker 
6454*795d594fSAndroid Build Coastguard Worker  protected:
6455*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ArrayLength);
6456*795d594fSAndroid Build Coastguard Worker 
6457*795d594fSAndroid Build Coastguard Worker  private:
6458*795d594fSAndroid Build Coastguard Worker   // We treat a String as an array, creating the HArrayLength from String.length()
6459*795d594fSAndroid Build Coastguard Worker   // or String.isEmpty() intrinsic in the instruction simplifier. We can always
6460*795d594fSAndroid Build Coastguard Worker   // determine whether a particular HArrayLength is actually a String.length() by
6461*795d594fSAndroid Build Coastguard Worker   // looking at the type of the input but that requires holding the mutator lock, so
6462*795d594fSAndroid Build Coastguard Worker   // we prefer to use a flag, so that code generators don't need to do the locking.
6463*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsStringLength = kNumberOfGenericPackedBits;
6464*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfArrayLengthPackedBits = kFlagIsStringLength + 1;
6465*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfArrayLengthPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6466*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
6467*795d594fSAndroid Build Coastguard Worker };
6468*795d594fSAndroid Build Coastguard Worker 
6469*795d594fSAndroid Build Coastguard Worker class HBoundsCheck final : public HExpression<2> {
6470*795d594fSAndroid Build Coastguard Worker  public:
6471*795d594fSAndroid Build Coastguard Worker   // `HBoundsCheck` can trigger GC, as it may call the `IndexOutOfBoundsException`
6472*795d594fSAndroid Build Coastguard Worker   // constructor. However it can only do it on a fatal slow path so execution never returns to the
6473*795d594fSAndroid Build Coastguard Worker   // instruction following the current one; thus 'SideEffects::None()' is used.
6474*795d594fSAndroid Build Coastguard Worker   HBoundsCheck(HInstruction* index,
6475*795d594fSAndroid Build Coastguard Worker                HInstruction* length,
6476*795d594fSAndroid Build Coastguard Worker                uint32_t dex_pc,
6477*795d594fSAndroid Build Coastguard Worker                bool is_string_char_at = false)
6478*795d594fSAndroid Build Coastguard Worker       : HExpression(kBoundsCheck, index->GetType(), SideEffects::None(), dex_pc) {
6479*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Type::kInt32, DataType::Kind(index->GetType()));
6480*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsStringCharAt>(is_string_char_at);
6481*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, index);
6482*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, length);
6483*795d594fSAndroid Build Coastguard Worker   }
6484*795d594fSAndroid Build Coastguard Worker 
6485*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6486*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
6487*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
6488*795d594fSAndroid Build Coastguard Worker     return true;
6489*795d594fSAndroid Build Coastguard Worker   }
6490*795d594fSAndroid Build Coastguard Worker 
6491*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
6492*795d594fSAndroid Build Coastguard Worker 
6493*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
6494*795d594fSAndroid Build Coastguard Worker 
6495*795d594fSAndroid Build Coastguard Worker   bool IsStringCharAt() const { return GetPackedFlag<kFlagIsStringCharAt>(); }
6496*795d594fSAndroid Build Coastguard Worker 
6497*795d594fSAndroid Build Coastguard Worker   HInstruction* GetIndex() const { return InputAt(0); }
6498*795d594fSAndroid Build Coastguard Worker 
6499*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(BoundsCheck);
6500*795d594fSAndroid Build Coastguard Worker 
6501*795d594fSAndroid Build Coastguard Worker  protected:
6502*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BoundsCheck);
6503*795d594fSAndroid Build Coastguard Worker 
6504*795d594fSAndroid Build Coastguard Worker  private:
6505*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsStringCharAt = kNumberOfGenericPackedBits;
6506*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfBoundsCheckPackedBits = kFlagIsStringCharAt + 1;
6507*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfBoundsCheckPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6508*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
6509*795d594fSAndroid Build Coastguard Worker };
6510*795d594fSAndroid Build Coastguard Worker 
6511*795d594fSAndroid Build Coastguard Worker class HSuspendCheck final : public HExpression<0> {
6512*795d594fSAndroid Build Coastguard Worker  public:
6513*795d594fSAndroid Build Coastguard Worker   explicit HSuspendCheck(uint32_t dex_pc = kNoDexPc, bool is_no_op = false)
6514*795d594fSAndroid Build Coastguard Worker       : HExpression(kSuspendCheck, SideEffects::CanTriggerGC(), dex_pc),
6515*795d594fSAndroid Build Coastguard Worker         slow_path_(nullptr) {
6516*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsNoOp>(is_no_op);
6517*795d594fSAndroid Build Coastguard Worker   }
6518*795d594fSAndroid Build Coastguard Worker 
6519*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6520*795d594fSAndroid Build Coastguard Worker 
6521*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
6522*795d594fSAndroid Build Coastguard Worker     return true;
6523*795d594fSAndroid Build Coastguard Worker   }
6524*795d594fSAndroid Build Coastguard Worker 
6525*795d594fSAndroid Build Coastguard Worker   void SetIsNoOp(bool is_no_op) { SetPackedFlag<kFlagIsNoOp>(is_no_op); }
6526*795d594fSAndroid Build Coastguard Worker   bool IsNoOp() const { return GetPackedFlag<kFlagIsNoOp>(); }
6527*795d594fSAndroid Build Coastguard Worker 
6528*795d594fSAndroid Build Coastguard Worker 
6529*795d594fSAndroid Build Coastguard Worker   void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
6530*795d594fSAndroid Build Coastguard Worker   SlowPathCode* GetSlowPath() const { return slow_path_; }
6531*795d594fSAndroid Build Coastguard Worker 
6532*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(SuspendCheck);
6533*795d594fSAndroid Build Coastguard Worker 
6534*795d594fSAndroid Build Coastguard Worker  protected:
6535*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(SuspendCheck);
6536*795d594fSAndroid Build Coastguard Worker 
6537*795d594fSAndroid Build Coastguard Worker   // True if the HSuspendCheck should not emit any code during codegen. It is
6538*795d594fSAndroid Build Coastguard Worker   // not possible to simply remove this instruction to disable codegen, as
6539*795d594fSAndroid Build Coastguard Worker   // other optimizations (e.g: CHAGuardVisitor::HoistGuard) depend on
6540*795d594fSAndroid Build Coastguard Worker   // HSuspendCheck being present in every loop.
6541*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsNoOp = kNumberOfGenericPackedBits;
6542*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfSuspendCheckPackedBits = kFlagIsNoOp + 1;
6543*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfSuspendCheckPackedBits <= HInstruction::kMaxNumberOfPackedBits,
6544*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
6545*795d594fSAndroid Build Coastguard Worker 
6546*795d594fSAndroid Build Coastguard Worker  private:
6547*795d594fSAndroid Build Coastguard Worker   // Only used for code generation, in order to share the same slow path between back edges
6548*795d594fSAndroid Build Coastguard Worker   // of a same loop.
6549*795d594fSAndroid Build Coastguard Worker   SlowPathCode* slow_path_;
6550*795d594fSAndroid Build Coastguard Worker };
6551*795d594fSAndroid Build Coastguard Worker 
6552*795d594fSAndroid Build Coastguard Worker // Pseudo-instruction which doesn't generate any code.
6553*795d594fSAndroid Build Coastguard Worker // If `emit_environment` is true, it can be used to generate an environment. It is used, for
6554*795d594fSAndroid Build Coastguard Worker // example, to provide the native debugger with mapping information. It ensures that we can generate
6555*795d594fSAndroid Build Coastguard Worker // line number and local variables at this point.
6556*795d594fSAndroid Build Coastguard Worker class HNop : public HExpression<0> {
6557*795d594fSAndroid Build Coastguard Worker  public:
6558*795d594fSAndroid Build Coastguard Worker   explicit HNop(uint32_t dex_pc, bool needs_environment)
6559*795d594fSAndroid Build Coastguard Worker       : HExpression<0>(kNop, SideEffects::None(), dex_pc), needs_environment_(needs_environment) {
6560*795d594fSAndroid Build Coastguard Worker   }
6561*795d594fSAndroid Build Coastguard Worker 
6562*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
6563*795d594fSAndroid Build Coastguard Worker     return needs_environment_;
6564*795d594fSAndroid Build Coastguard Worker   }
6565*795d594fSAndroid Build Coastguard Worker 
6566*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Nop);
6567*795d594fSAndroid Build Coastguard Worker 
6568*795d594fSAndroid Build Coastguard Worker  protected:
6569*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Nop);
6570*795d594fSAndroid Build Coastguard Worker 
6571*795d594fSAndroid Build Coastguard Worker  private:
6572*795d594fSAndroid Build Coastguard Worker   bool needs_environment_;
6573*795d594fSAndroid Build Coastguard Worker };
6574*795d594fSAndroid Build Coastguard Worker 
6575*795d594fSAndroid Build Coastguard Worker /**
6576*795d594fSAndroid Build Coastguard Worker  * Instruction to load a Class object.
6577*795d594fSAndroid Build Coastguard Worker  */
6578*795d594fSAndroid Build Coastguard Worker class HLoadClass final : public HInstruction {
6579*795d594fSAndroid Build Coastguard Worker  public:
6580*795d594fSAndroid Build Coastguard Worker   // Determines how to load the Class.
6581*795d594fSAndroid Build Coastguard Worker   enum class LoadKind {
6582*795d594fSAndroid Build Coastguard Worker     // We cannot load this class. See HSharpening::SharpenLoadClass.
6583*795d594fSAndroid Build Coastguard Worker     kInvalid = -1,
6584*795d594fSAndroid Build Coastguard Worker 
6585*795d594fSAndroid Build Coastguard Worker     // Use the Class* from the method's own ArtMethod*.
6586*795d594fSAndroid Build Coastguard Worker     kReferrersClass,
6587*795d594fSAndroid Build Coastguard Worker 
6588*795d594fSAndroid Build Coastguard Worker     // Use PC-relative boot image Class* address that will be known at link time.
6589*795d594fSAndroid Build Coastguard Worker     // Used for boot image classes referenced by boot image code.
6590*795d594fSAndroid Build Coastguard Worker     kBootImageLinkTimePcRelative,
6591*795d594fSAndroid Build Coastguard Worker 
6592*795d594fSAndroid Build Coastguard Worker     // Load from a boot image entry in the .data.img.rel.ro using a PC-relative load.
6593*795d594fSAndroid Build Coastguard Worker     // Used for boot image classes referenced by apps in AOT-compiled code.
6594*795d594fSAndroid Build Coastguard Worker     kBootImageRelRo,
6595*795d594fSAndroid Build Coastguard Worker 
6596*795d594fSAndroid Build Coastguard Worker     // Load from an app image entry in the .data.img.rel.ro using a PC-relative load.
6597*795d594fSAndroid Build Coastguard Worker     // Used for app image classes referenced by apps in AOT-compiled code.
6598*795d594fSAndroid Build Coastguard Worker     kAppImageRelRo,
6599*795d594fSAndroid Build Coastguard Worker 
6600*795d594fSAndroid Build Coastguard Worker     // Load from an entry in the .bss section using a PC-relative load.
6601*795d594fSAndroid Build Coastguard Worker     // Used for classes outside boot image referenced by AOT-compiled app and boot image code.
6602*795d594fSAndroid Build Coastguard Worker     kBssEntry,
6603*795d594fSAndroid Build Coastguard Worker 
6604*795d594fSAndroid Build Coastguard Worker     // Load from an entry for public class in the .bss section using a PC-relative load.
6605*795d594fSAndroid Build Coastguard Worker     // Used for classes that were unresolved during AOT-compilation outside the literal
6606*795d594fSAndroid Build Coastguard Worker     // package of the compiling class. Such classes are accessible only if they are public
6607*795d594fSAndroid Build Coastguard Worker     // and the .bss entry shall therefore be filled only if the resolved class is public.
6608*795d594fSAndroid Build Coastguard Worker     kBssEntryPublic,
6609*795d594fSAndroid Build Coastguard Worker 
6610*795d594fSAndroid Build Coastguard Worker     // Load from an entry for package class in the .bss section using a PC-relative load.
6611*795d594fSAndroid Build Coastguard Worker     // Used for classes that were unresolved during AOT-compilation but within the literal
6612*795d594fSAndroid Build Coastguard Worker     // package of the compiling class. Such classes are accessible if they are public or
6613*795d594fSAndroid Build Coastguard Worker     // in the same package which, given the literal package match, requires only matching
6614*795d594fSAndroid Build Coastguard Worker     // defining class loader and the .bss entry shall therefore be filled only if at least
6615*795d594fSAndroid Build Coastguard Worker     // one of those conditions holds. Note that all code in an oat file belongs to classes
6616*795d594fSAndroid Build Coastguard Worker     // with the same defining class loader.
6617*795d594fSAndroid Build Coastguard Worker     kBssEntryPackage,
6618*795d594fSAndroid Build Coastguard Worker 
6619*795d594fSAndroid Build Coastguard Worker     // Use a known boot image Class* address, embedded in the code by the codegen.
6620*795d594fSAndroid Build Coastguard Worker     // Used for boot image classes referenced by apps in JIT-compiled code.
6621*795d594fSAndroid Build Coastguard Worker     kJitBootImageAddress,
6622*795d594fSAndroid Build Coastguard Worker 
6623*795d594fSAndroid Build Coastguard Worker     // Load from the root table associated with the JIT compiled method.
6624*795d594fSAndroid Build Coastguard Worker     kJitTableAddress,
6625*795d594fSAndroid Build Coastguard Worker 
6626*795d594fSAndroid Build Coastguard Worker     // Load using a simple runtime call. This is the fall-back load kind when
6627*795d594fSAndroid Build Coastguard Worker     // the codegen is unable to use another appropriate kind.
6628*795d594fSAndroid Build Coastguard Worker     kRuntimeCall,
6629*795d594fSAndroid Build Coastguard Worker 
6630*795d594fSAndroid Build Coastguard Worker     kLast = kRuntimeCall
6631*795d594fSAndroid Build Coastguard Worker   };
6632*795d594fSAndroid Build Coastguard Worker 
6633*795d594fSAndroid Build Coastguard Worker   HLoadClass(HCurrentMethod* current_method,
6634*795d594fSAndroid Build Coastguard Worker              dex::TypeIndex type_index,
6635*795d594fSAndroid Build Coastguard Worker              const DexFile& dex_file,
6636*795d594fSAndroid Build Coastguard Worker              Handle<mirror::Class> klass,
6637*795d594fSAndroid Build Coastguard Worker              bool is_referrers_class,
6638*795d594fSAndroid Build Coastguard Worker              uint32_t dex_pc,
6639*795d594fSAndroid Build Coastguard Worker              bool needs_access_check)
6640*795d594fSAndroid Build Coastguard Worker       : HInstruction(kLoadClass,
6641*795d594fSAndroid Build Coastguard Worker                      DataType::Type::kReference,
6642*795d594fSAndroid Build Coastguard Worker                      SideEffectsForArchRuntimeCalls(),
6643*795d594fSAndroid Build Coastguard Worker                      dex_pc),
6644*795d594fSAndroid Build Coastguard Worker         special_input_(HUserRecord<HInstruction*>(current_method)),
6645*795d594fSAndroid Build Coastguard Worker         type_index_(type_index),
6646*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file),
6647*795d594fSAndroid Build Coastguard Worker         klass_(klass) {
6648*795d594fSAndroid Build Coastguard Worker     // Referrers class should not need access check. We never inline unverified
6649*795d594fSAndroid Build Coastguard Worker     // methods so we can't possibly end up in this situation.
6650*795d594fSAndroid Build Coastguard Worker     DCHECK_IMPLIES(is_referrers_class, !needs_access_check);
6651*795d594fSAndroid Build Coastguard Worker 
6652*795d594fSAndroid Build Coastguard Worker     SetPackedField<LoadKindField>(
6653*795d594fSAndroid Build Coastguard Worker         is_referrers_class ? LoadKind::kReferrersClass : LoadKind::kRuntimeCall);
6654*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagNeedsAccessCheck>(needs_access_check);
6655*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsInImage>(false);
6656*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagGenerateClInitCheck>(false);
6657*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValidLoadedClassRTI>(false);
6658*795d594fSAndroid Build Coastguard Worker   }
6659*795d594fSAndroid Build Coastguard Worker 
6660*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6661*795d594fSAndroid Build Coastguard Worker 
6662*795d594fSAndroid Build Coastguard Worker   void SetLoadKind(LoadKind load_kind);
6663*795d594fSAndroid Build Coastguard Worker 
6664*795d594fSAndroid Build Coastguard Worker   LoadKind GetLoadKind() const {
6665*795d594fSAndroid Build Coastguard Worker     return GetPackedField<LoadKindField>();
6666*795d594fSAndroid Build Coastguard Worker   }
6667*795d594fSAndroid Build Coastguard Worker 
6668*795d594fSAndroid Build Coastguard Worker   bool HasPcRelativeLoadKind() const {
6669*795d594fSAndroid Build Coastguard Worker     return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
6670*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBootImageRelRo ||
6671*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kAppImageRelRo ||
6672*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBssEntry ||
6673*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBssEntryPublic ||
6674*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBssEntryPackage;
6675*795d594fSAndroid Build Coastguard Worker   }
6676*795d594fSAndroid Build Coastguard Worker 
6677*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
6678*795d594fSAndroid Build Coastguard Worker 
6679*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override;
6680*795d594fSAndroid Build Coastguard Worker 
6681*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return type_index_.index_; }
6682*795d594fSAndroid Build Coastguard Worker 
6683*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
6684*795d594fSAndroid Build Coastguard Worker 
6685*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
6686*795d594fSAndroid Build Coastguard Worker     return CanCallRuntime();
6687*795d594fSAndroid Build Coastguard Worker   }
6688*795d594fSAndroid Build Coastguard Worker   bool NeedsBss() const override {
6689*795d594fSAndroid Build Coastguard Worker     LoadKind load_kind = GetLoadKind();
6690*795d594fSAndroid Build Coastguard Worker     return load_kind == LoadKind::kBssEntry ||
6691*795d594fSAndroid Build Coastguard Worker            load_kind == LoadKind::kBssEntryPublic ||
6692*795d594fSAndroid Build Coastguard Worker            load_kind == LoadKind::kBssEntryPackage;
6693*795d594fSAndroid Build Coastguard Worker   }
6694*795d594fSAndroid Build Coastguard Worker 
6695*795d594fSAndroid Build Coastguard Worker   void SetMustGenerateClinitCheck(bool generate_clinit_check) {
6696*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagGenerateClInitCheck>(generate_clinit_check);
6697*795d594fSAndroid Build Coastguard Worker   }
6698*795d594fSAndroid Build Coastguard Worker 
6699*795d594fSAndroid Build Coastguard Worker   bool CanCallRuntime() const {
6700*795d594fSAndroid Build Coastguard Worker     return NeedsAccessCheck() ||
6701*795d594fSAndroid Build Coastguard Worker            MustGenerateClinitCheck() ||
6702*795d594fSAndroid Build Coastguard Worker            NeedsBss() ||
6703*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kRuntimeCall;
6704*795d594fSAndroid Build Coastguard Worker   }
6705*795d594fSAndroid Build Coastguard Worker 
6706*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override {
6707*795d594fSAndroid Build Coastguard Worker     return NeedsAccessCheck() ||
6708*795d594fSAndroid Build Coastguard Worker            MustGenerateClinitCheck() ||
6709*795d594fSAndroid Build Coastguard Worker            // If the class is in the boot or app image, the lookup in the runtime call cannot throw.
6710*795d594fSAndroid Build Coastguard Worker            ((GetLoadKind() == LoadKind::kRuntimeCall || NeedsBss()) && !IsInImage());
6711*795d594fSAndroid Build Coastguard Worker   }
6712*795d594fSAndroid Build Coastguard Worker 
6713*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo GetLoadedClassRTI() {
6714*795d594fSAndroid Build Coastguard Worker     if (GetPackedFlag<kFlagValidLoadedClassRTI>()) {
6715*795d594fSAndroid Build Coastguard Worker       // Note: The is_exact flag from the return value should not be used.
6716*795d594fSAndroid Build Coastguard Worker       return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact= */ true);
6717*795d594fSAndroid Build Coastguard Worker     } else {
6718*795d594fSAndroid Build Coastguard Worker       return ReferenceTypeInfo::CreateInvalid();
6719*795d594fSAndroid Build Coastguard Worker     }
6720*795d594fSAndroid Build Coastguard Worker   }
6721*795d594fSAndroid Build Coastguard Worker 
6722*795d594fSAndroid Build Coastguard Worker   // Loaded class RTI is marked as valid by RTP if the klass_ is admissible.
6723*795d594fSAndroid Build Coastguard Worker   void SetValidLoadedClassRTI() {
6724*795d594fSAndroid Build Coastguard Worker     DCHECK(klass_ != nullptr);
6725*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValidLoadedClassRTI>(true);
6726*795d594fSAndroid Build Coastguard Worker   }
6727*795d594fSAndroid Build Coastguard Worker 
6728*795d594fSAndroid Build Coastguard Worker   dex::TypeIndex GetTypeIndex() const { return type_index_; }
6729*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
6730*795d594fSAndroid Build Coastguard Worker 
6731*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls() {
6732*795d594fSAndroid Build Coastguard Worker     return SideEffects::CanTriggerGC();
6733*795d594fSAndroid Build Coastguard Worker   }
6734*795d594fSAndroid Build Coastguard Worker 
6735*795d594fSAndroid Build Coastguard Worker   bool IsReferrersClass() const { return GetLoadKind() == LoadKind::kReferrersClass; }
6736*795d594fSAndroid Build Coastguard Worker   bool NeedsAccessCheck() const { return GetPackedFlag<kFlagNeedsAccessCheck>(); }
6737*795d594fSAndroid Build Coastguard Worker   bool IsInImage() const { return GetPackedFlag<kFlagIsInImage>(); }
6738*795d594fSAndroid Build Coastguard Worker   bool MustGenerateClinitCheck() const { return GetPackedFlag<kFlagGenerateClInitCheck>(); }
6739*795d594fSAndroid Build Coastguard Worker 
6740*795d594fSAndroid Build Coastguard Worker   bool MustResolveTypeOnSlowPath() const {
6741*795d594fSAndroid Build Coastguard Worker     // Check that this instruction has a slow path.
6742*795d594fSAndroid Build Coastguard Worker     LoadKind load_kind = GetLoadKind();
6743*795d594fSAndroid Build Coastguard Worker     DCHECK(load_kind != LoadKind::kRuntimeCall);  // kRuntimeCall calls on main path.
6744*795d594fSAndroid Build Coastguard Worker     bool must_resolve_type_on_slow_path =
6745*795d594fSAndroid Build Coastguard Worker        load_kind == LoadKind::kBssEntry ||
6746*795d594fSAndroid Build Coastguard Worker        load_kind == LoadKind::kBssEntryPublic ||
6747*795d594fSAndroid Build Coastguard Worker        load_kind == LoadKind::kBssEntryPackage;
6748*795d594fSAndroid Build Coastguard Worker     DCHECK(must_resolve_type_on_slow_path || MustGenerateClinitCheck());
6749*795d594fSAndroid Build Coastguard Worker     return must_resolve_type_on_slow_path;
6750*795d594fSAndroid Build Coastguard Worker   }
6751*795d594fSAndroid Build Coastguard Worker 
6752*795d594fSAndroid Build Coastguard Worker   void MarkInImage() {
6753*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagIsInImage>(true);
6754*795d594fSAndroid Build Coastguard Worker   }
6755*795d594fSAndroid Build Coastguard Worker 
6756*795d594fSAndroid Build Coastguard Worker   void AddSpecialInput(HInstruction* special_input);
6757*795d594fSAndroid Build Coastguard Worker 
6758*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
6759*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
6760*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(
6761*795d594fSAndroid Build Coastguard Worker         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
6762*795d594fSAndroid Build Coastguard Worker   }
6763*795d594fSAndroid Build Coastguard Worker 
6764*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> GetClass() const {
6765*795d594fSAndroid Build Coastguard Worker     return klass_;
6766*795d594fSAndroid Build Coastguard Worker   }
6767*795d594fSAndroid Build Coastguard Worker 
6768*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LoadClass);
6769*795d594fSAndroid Build Coastguard Worker 
6770*795d594fSAndroid Build Coastguard Worker  protected:
6771*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LoadClass);
6772*795d594fSAndroid Build Coastguard Worker 
6773*795d594fSAndroid Build Coastguard Worker  private:
6774*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagNeedsAccessCheck    = kNumberOfGenericPackedBits;
6775*795d594fSAndroid Build Coastguard Worker   // Whether the type is in an image (boot image or app image).
6776*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagIsInImage           = kFlagNeedsAccessCheck + 1;
6777*795d594fSAndroid Build Coastguard Worker   // Whether this instruction must generate the initialization check.
6778*795d594fSAndroid Build Coastguard Worker   // Used for code generation.
6779*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagGenerateClInitCheck = kFlagIsInImage + 1;
6780*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKind           = kFlagGenerateClInitCheck + 1;
6781*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKindSize =
6782*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
6783*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagValidLoadedClassRTI = kFieldLoadKind + kFieldLoadKindSize;
6784*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfLoadClassPackedBits = kFlagValidLoadedClassRTI + 1;
6785*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfLoadClassPackedBits < kMaxNumberOfPackedBits, "Too many packed fields.");
6786*795d594fSAndroid Build Coastguard Worker   using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
6787*795d594fSAndroid Build Coastguard Worker 
6788*795d594fSAndroid Build Coastguard Worker   static bool HasTypeReference(LoadKind load_kind) {
6789*795d594fSAndroid Build Coastguard Worker     return load_kind == LoadKind::kReferrersClass ||
6790*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kBootImageLinkTimePcRelative ||
6791*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kAppImageRelRo ||
6792*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kBssEntry ||
6793*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kBssEntryPublic ||
6794*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kBssEntryPackage ||
6795*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kRuntimeCall;
6796*795d594fSAndroid Build Coastguard Worker   }
6797*795d594fSAndroid Build Coastguard Worker 
6798*795d594fSAndroid Build Coastguard Worker   void SetLoadKindInternal(LoadKind load_kind);
6799*795d594fSAndroid Build Coastguard Worker 
6800*795d594fSAndroid Build Coastguard Worker   // The special input is the HCurrentMethod for kRuntimeCall or kReferrersClass.
6801*795d594fSAndroid Build Coastguard Worker   // For other load kinds it's empty or possibly some architecture-specific instruction
6802*795d594fSAndroid Build Coastguard Worker   // for PC-relative loads, i.e. kBssEntry* or kBootImageLinkTimePcRelative.
6803*795d594fSAndroid Build Coastguard Worker   HUserRecord<HInstruction*> special_input_;
6804*795d594fSAndroid Build Coastguard Worker 
6805*795d594fSAndroid Build Coastguard Worker   // A type index and dex file where the class can be accessed. The dex file can be:
6806*795d594fSAndroid Build Coastguard Worker   // - The compiling method's dex file if the class is defined there too.
6807*795d594fSAndroid Build Coastguard Worker   // - The compiling method's dex file if the class is referenced there.
6808*795d594fSAndroid Build Coastguard Worker   // - The dex file where the class is defined. When the load kind can only be
6809*795d594fSAndroid Build Coastguard Worker   //   kBssEntry* or kRuntimeCall, we cannot emit code for this `HLoadClass`.
6810*795d594fSAndroid Build Coastguard Worker   const dex::TypeIndex type_index_;
6811*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
6812*795d594fSAndroid Build Coastguard Worker 
6813*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> klass_;
6814*795d594fSAndroid Build Coastguard Worker };
6815*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs);
6816*795d594fSAndroid Build Coastguard Worker 
6817*795d594fSAndroid Build Coastguard Worker // Note: defined outside class to see operator<<(., HLoadClass::LoadKind).
6818*795d594fSAndroid Build Coastguard Worker inline void HLoadClass::SetLoadKind(LoadKind load_kind) {
6819*795d594fSAndroid Build Coastguard Worker   // The load kind should be determined before inserting the instruction to the graph.
6820*795d594fSAndroid Build Coastguard Worker   DCHECK(GetBlock() == nullptr);
6821*795d594fSAndroid Build Coastguard Worker   DCHECK(GetEnvironment() == nullptr);
6822*795d594fSAndroid Build Coastguard Worker   SetPackedField<LoadKindField>(load_kind);
6823*795d594fSAndroid Build Coastguard Worker   if (load_kind != LoadKind::kRuntimeCall && load_kind != LoadKind::kReferrersClass) {
6824*795d594fSAndroid Build Coastguard Worker     special_input_ = HUserRecord<HInstruction*>(nullptr);
6825*795d594fSAndroid Build Coastguard Worker   }
6826*795d594fSAndroid Build Coastguard Worker   if (!NeedsEnvironment()) {
6827*795d594fSAndroid Build Coastguard Worker     SetSideEffects(SideEffects::None());
6828*795d594fSAndroid Build Coastguard Worker   }
6829*795d594fSAndroid Build Coastguard Worker }
6830*795d594fSAndroid Build Coastguard Worker 
6831*795d594fSAndroid Build Coastguard Worker // Note: defined outside class to see operator<<(., HLoadClass::LoadKind).
6832*795d594fSAndroid Build Coastguard Worker inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
6833*795d594fSAndroid Build Coastguard Worker   // The special input is used for PC-relative loads on some architectures,
6834*795d594fSAndroid Build Coastguard Worker   // including literal pool loads, which are PC-relative too.
6835*795d594fSAndroid Build Coastguard Worker   DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
6836*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBootImageRelRo ||
6837*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kAppImageRelRo ||
6838*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBssEntry ||
6839*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBssEntryPublic ||
6840*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBssEntryPackage ||
6841*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
6842*795d594fSAndroid Build Coastguard Worker   DCHECK(special_input_.GetInstruction() == nullptr);
6843*795d594fSAndroid Build Coastguard Worker   special_input_ = HUserRecord<HInstruction*>(special_input);
6844*795d594fSAndroid Build Coastguard Worker   special_input->AddUseAt(this, 0);
6845*795d594fSAndroid Build Coastguard Worker }
6846*795d594fSAndroid Build Coastguard Worker 
6847*795d594fSAndroid Build Coastguard Worker class HLoadString final : public HInstruction {
6848*795d594fSAndroid Build Coastguard Worker  public:
6849*795d594fSAndroid Build Coastguard Worker   // Determines how to load the String.
6850*795d594fSAndroid Build Coastguard Worker   enum class LoadKind {
6851*795d594fSAndroid Build Coastguard Worker     // Use PC-relative boot image String* address that will be known at link time.
6852*795d594fSAndroid Build Coastguard Worker     // Used for boot image strings referenced by boot image code.
6853*795d594fSAndroid Build Coastguard Worker     kBootImageLinkTimePcRelative,
6854*795d594fSAndroid Build Coastguard Worker 
6855*795d594fSAndroid Build Coastguard Worker     // Load from a boot image entry in the .data.img.rel.ro using a PC-relative load.
6856*795d594fSAndroid Build Coastguard Worker     // Used for boot image strings referenced by apps in AOT-compiled code.
6857*795d594fSAndroid Build Coastguard Worker     kBootImageRelRo,
6858*795d594fSAndroid Build Coastguard Worker 
6859*795d594fSAndroid Build Coastguard Worker     // Load from an entry in the .bss section using a PC-relative load.
6860*795d594fSAndroid Build Coastguard Worker     // Used for strings outside boot image referenced by AOT-compiled app and boot image code.
6861*795d594fSAndroid Build Coastguard Worker     kBssEntry,
6862*795d594fSAndroid Build Coastguard Worker 
6863*795d594fSAndroid Build Coastguard Worker     // Use a known boot image String* address, embedded in the code by the codegen.
6864*795d594fSAndroid Build Coastguard Worker     // Used for boot image strings referenced by apps in JIT-compiled code.
6865*795d594fSAndroid Build Coastguard Worker     kJitBootImageAddress,
6866*795d594fSAndroid Build Coastguard Worker 
6867*795d594fSAndroid Build Coastguard Worker     // Load from the root table associated with the JIT compiled method.
6868*795d594fSAndroid Build Coastguard Worker     kJitTableAddress,
6869*795d594fSAndroid Build Coastguard Worker 
6870*795d594fSAndroid Build Coastguard Worker     // Load using a simple runtime call. This is the fall-back load kind when
6871*795d594fSAndroid Build Coastguard Worker     // the codegen is unable to use another appropriate kind.
6872*795d594fSAndroid Build Coastguard Worker     kRuntimeCall,
6873*795d594fSAndroid Build Coastguard Worker 
6874*795d594fSAndroid Build Coastguard Worker     kLast = kRuntimeCall,
6875*795d594fSAndroid Build Coastguard Worker   };
6876*795d594fSAndroid Build Coastguard Worker 
6877*795d594fSAndroid Build Coastguard Worker   HLoadString(HCurrentMethod* current_method,
6878*795d594fSAndroid Build Coastguard Worker               dex::StringIndex string_index,
6879*795d594fSAndroid Build Coastguard Worker               const DexFile& dex_file,
6880*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc)
6881*795d594fSAndroid Build Coastguard Worker       : HInstruction(kLoadString,
6882*795d594fSAndroid Build Coastguard Worker                      DataType::Type::kReference,
6883*795d594fSAndroid Build Coastguard Worker                      SideEffectsForArchRuntimeCalls(),
6884*795d594fSAndroid Build Coastguard Worker                      dex_pc),
6885*795d594fSAndroid Build Coastguard Worker         special_input_(HUserRecord<HInstruction*>(current_method)),
6886*795d594fSAndroid Build Coastguard Worker         string_index_(string_index),
6887*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file) {
6888*795d594fSAndroid Build Coastguard Worker     SetPackedField<LoadKindField>(LoadKind::kRuntimeCall);
6889*795d594fSAndroid Build Coastguard Worker   }
6890*795d594fSAndroid Build Coastguard Worker 
6891*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
6892*795d594fSAndroid Build Coastguard Worker   bool NeedsBss() const override {
6893*795d594fSAndroid Build Coastguard Worker     return GetLoadKind() == LoadKind::kBssEntry;
6894*795d594fSAndroid Build Coastguard Worker   }
6895*795d594fSAndroid Build Coastguard Worker 
6896*795d594fSAndroid Build Coastguard Worker   void SetLoadKind(LoadKind load_kind);
6897*795d594fSAndroid Build Coastguard Worker 
6898*795d594fSAndroid Build Coastguard Worker   LoadKind GetLoadKind() const {
6899*795d594fSAndroid Build Coastguard Worker     return GetPackedField<LoadKindField>();
6900*795d594fSAndroid Build Coastguard Worker   }
6901*795d594fSAndroid Build Coastguard Worker 
6902*795d594fSAndroid Build Coastguard Worker   bool HasPcRelativeLoadKind() const {
6903*795d594fSAndroid Build Coastguard Worker     return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
6904*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBootImageRelRo ||
6905*795d594fSAndroid Build Coastguard Worker            GetLoadKind() == LoadKind::kBssEntry;
6906*795d594fSAndroid Build Coastguard Worker   }
6907*795d594fSAndroid Build Coastguard Worker 
6908*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const {
6909*795d594fSAndroid Build Coastguard Worker     return dex_file_;
6910*795d594fSAndroid Build Coastguard Worker   }
6911*795d594fSAndroid Build Coastguard Worker 
6912*795d594fSAndroid Build Coastguard Worker   dex::StringIndex GetStringIndex() const {
6913*795d594fSAndroid Build Coastguard Worker     return string_index_;
6914*795d594fSAndroid Build Coastguard Worker   }
6915*795d594fSAndroid Build Coastguard Worker 
6916*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> GetString() const {
6917*795d594fSAndroid Build Coastguard Worker     return string_;
6918*795d594fSAndroid Build Coastguard Worker   }
6919*795d594fSAndroid Build Coastguard Worker 
6920*795d594fSAndroid Build Coastguard Worker   void SetString(Handle<mirror::String> str) {
6921*795d594fSAndroid Build Coastguard Worker     string_ = str;
6922*795d594fSAndroid Build Coastguard Worker   }
6923*795d594fSAndroid Build Coastguard Worker 
6924*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
6925*795d594fSAndroid Build Coastguard Worker 
6926*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override;
6927*795d594fSAndroid Build Coastguard Worker 
6928*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override { return string_index_.index_; }
6929*795d594fSAndroid Build Coastguard Worker 
6930*795d594fSAndroid Build Coastguard Worker   // Will call the runtime if we need to load the string through
6931*795d594fSAndroid Build Coastguard Worker   // the dex cache and the string is not guaranteed to be there yet.
6932*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
6933*795d594fSAndroid Build Coastguard Worker     LoadKind load_kind = GetLoadKind();
6934*795d594fSAndroid Build Coastguard Worker     if (load_kind == LoadKind::kBootImageLinkTimePcRelative ||
6935*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kBootImageRelRo ||
6936*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kJitBootImageAddress ||
6937*795d594fSAndroid Build Coastguard Worker         load_kind == LoadKind::kJitTableAddress) {
6938*795d594fSAndroid Build Coastguard Worker       return false;
6939*795d594fSAndroid Build Coastguard Worker     }
6940*795d594fSAndroid Build Coastguard Worker     return true;
6941*795d594fSAndroid Build Coastguard Worker   }
6942*795d594fSAndroid Build Coastguard Worker 
6943*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
6944*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return NeedsEnvironment(); }
6945*795d594fSAndroid Build Coastguard Worker 
6946*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls() {
6947*795d594fSAndroid Build Coastguard Worker     return SideEffects::CanTriggerGC();
6948*795d594fSAndroid Build Coastguard Worker   }
6949*795d594fSAndroid Build Coastguard Worker 
6950*795d594fSAndroid Build Coastguard Worker   void AddSpecialInput(HInstruction* special_input);
6951*795d594fSAndroid Build Coastguard Worker 
6952*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
6953*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
6954*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(
6955*795d594fSAndroid Build Coastguard Worker         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
6956*795d594fSAndroid Build Coastguard Worker   }
6957*795d594fSAndroid Build Coastguard Worker 
6958*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LoadString);
6959*795d594fSAndroid Build Coastguard Worker 
6960*795d594fSAndroid Build Coastguard Worker  protected:
6961*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LoadString);
6962*795d594fSAndroid Build Coastguard Worker 
6963*795d594fSAndroid Build Coastguard Worker  private:
6964*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits;
6965*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKindSize =
6966*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
6967*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfLoadStringPackedBits = kFieldLoadKind + kFieldLoadKindSize;
6968*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfLoadStringPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
6969*795d594fSAndroid Build Coastguard Worker   using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
6970*795d594fSAndroid Build Coastguard Worker 
6971*795d594fSAndroid Build Coastguard Worker   void SetLoadKindInternal(LoadKind load_kind);
6972*795d594fSAndroid Build Coastguard Worker 
6973*795d594fSAndroid Build Coastguard Worker   // The special input is the HCurrentMethod for kRuntimeCall.
6974*795d594fSAndroid Build Coastguard Worker   // For other load kinds it's empty or possibly some architecture-specific instruction
6975*795d594fSAndroid Build Coastguard Worker   // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative.
6976*795d594fSAndroid Build Coastguard Worker   HUserRecord<HInstruction*> special_input_;
6977*795d594fSAndroid Build Coastguard Worker 
6978*795d594fSAndroid Build Coastguard Worker   dex::StringIndex string_index_;
6979*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
6980*795d594fSAndroid Build Coastguard Worker 
6981*795d594fSAndroid Build Coastguard Worker   Handle<mirror::String> string_;
6982*795d594fSAndroid Build Coastguard Worker };
6983*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs);
6984*795d594fSAndroid Build Coastguard Worker 
6985*795d594fSAndroid Build Coastguard Worker // Note: defined outside class to see operator<<(., HLoadString::LoadKind).
6986*795d594fSAndroid Build Coastguard Worker inline void HLoadString::SetLoadKind(LoadKind load_kind) {
6987*795d594fSAndroid Build Coastguard Worker   // The load kind should be determined before inserting the instruction to the graph.
6988*795d594fSAndroid Build Coastguard Worker   DCHECK(GetBlock() == nullptr);
6989*795d594fSAndroid Build Coastguard Worker   DCHECK(GetEnvironment() == nullptr);
6990*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(GetLoadKind(), LoadKind::kRuntimeCall);
6991*795d594fSAndroid Build Coastguard Worker   SetPackedField<LoadKindField>(load_kind);
6992*795d594fSAndroid Build Coastguard Worker   if (load_kind != LoadKind::kRuntimeCall) {
6993*795d594fSAndroid Build Coastguard Worker     special_input_ = HUserRecord<HInstruction*>(nullptr);
6994*795d594fSAndroid Build Coastguard Worker   }
6995*795d594fSAndroid Build Coastguard Worker   if (!NeedsEnvironment()) {
6996*795d594fSAndroid Build Coastguard Worker     SetSideEffects(SideEffects::None());
6997*795d594fSAndroid Build Coastguard Worker   }
6998*795d594fSAndroid Build Coastguard Worker }
6999*795d594fSAndroid Build Coastguard Worker 
7000*795d594fSAndroid Build Coastguard Worker // Note: defined outside class to see operator<<(., HLoadString::LoadKind).
7001*795d594fSAndroid Build Coastguard Worker inline void HLoadString::AddSpecialInput(HInstruction* special_input) {
7002*795d594fSAndroid Build Coastguard Worker   // The special input is used for PC-relative loads on some architectures,
7003*795d594fSAndroid Build Coastguard Worker   // including literal pool loads, which are PC-relative too.
7004*795d594fSAndroid Build Coastguard Worker   DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
7005*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBootImageRelRo ||
7006*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kBssEntry ||
7007*795d594fSAndroid Build Coastguard Worker          GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
7008*795d594fSAndroid Build Coastguard Worker   // HLoadString::GetInputRecords() returns an empty array at this point,
7009*795d594fSAndroid Build Coastguard Worker   // so use the GetInputRecords() from the base class to set the input record.
7010*795d594fSAndroid Build Coastguard Worker   DCHECK(special_input_.GetInstruction() == nullptr);
7011*795d594fSAndroid Build Coastguard Worker   special_input_ = HUserRecord<HInstruction*>(special_input);
7012*795d594fSAndroid Build Coastguard Worker   special_input->AddUseAt(this, 0);
7013*795d594fSAndroid Build Coastguard Worker }
7014*795d594fSAndroid Build Coastguard Worker 
7015*795d594fSAndroid Build Coastguard Worker class HLoadMethodHandle final : public HInstruction {
7016*795d594fSAndroid Build Coastguard Worker  public:
7017*795d594fSAndroid Build Coastguard Worker   HLoadMethodHandle(HCurrentMethod* current_method,
7018*795d594fSAndroid Build Coastguard Worker                     uint16_t method_handle_idx,
7019*795d594fSAndroid Build Coastguard Worker                     const DexFile& dex_file,
7020*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc)
7021*795d594fSAndroid Build Coastguard Worker       : HInstruction(kLoadMethodHandle,
7022*795d594fSAndroid Build Coastguard Worker                      DataType::Type::kReference,
7023*795d594fSAndroid Build Coastguard Worker                      SideEffectsForArchRuntimeCalls(),
7024*795d594fSAndroid Build Coastguard Worker                      dex_pc),
7025*795d594fSAndroid Build Coastguard Worker         special_input_(HUserRecord<HInstruction*>(current_method)),
7026*795d594fSAndroid Build Coastguard Worker         method_handle_idx_(method_handle_idx),
7027*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file) {
7028*795d594fSAndroid Build Coastguard Worker   }
7029*795d594fSAndroid Build Coastguard Worker 
7030*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
7031*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
7032*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(
7033*795d594fSAndroid Build Coastguard Worker         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
7034*795d594fSAndroid Build Coastguard Worker   }
7035*795d594fSAndroid Build Coastguard Worker 
7036*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7037*795d594fSAndroid Build Coastguard Worker 
7038*795d594fSAndroid Build Coastguard Worker   uint16_t GetMethodHandleIndex() const { return method_handle_idx_; }
7039*795d594fSAndroid Build Coastguard Worker 
7040*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
7041*795d594fSAndroid Build Coastguard Worker 
7042*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls() {
7043*795d594fSAndroid Build Coastguard Worker     return SideEffects::CanTriggerGC();
7044*795d594fSAndroid Build Coastguard Worker   }
7045*795d594fSAndroid Build Coastguard Worker 
7046*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7047*795d594fSAndroid Build Coastguard Worker 
7048*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7049*795d594fSAndroid Build Coastguard Worker 
7050*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LoadMethodHandle);
7051*795d594fSAndroid Build Coastguard Worker 
7052*795d594fSAndroid Build Coastguard Worker  protected:
7053*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LoadMethodHandle);
7054*795d594fSAndroid Build Coastguard Worker 
7055*795d594fSAndroid Build Coastguard Worker  private:
7056*795d594fSAndroid Build Coastguard Worker   // The special input is the HCurrentMethod for kRuntimeCall.
7057*795d594fSAndroid Build Coastguard Worker   HUserRecord<HInstruction*> special_input_;
7058*795d594fSAndroid Build Coastguard Worker 
7059*795d594fSAndroid Build Coastguard Worker   const uint16_t method_handle_idx_;
7060*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
7061*795d594fSAndroid Build Coastguard Worker };
7062*795d594fSAndroid Build Coastguard Worker 
7063*795d594fSAndroid Build Coastguard Worker class HLoadMethodType final : public HInstruction {
7064*795d594fSAndroid Build Coastguard Worker  public:
7065*795d594fSAndroid Build Coastguard Worker   // Determines how to load the MethodType.
7066*795d594fSAndroid Build Coastguard Worker   enum class LoadKind {
7067*795d594fSAndroid Build Coastguard Worker     // Load from an entry in the .bss section using a PC-relative load.
7068*795d594fSAndroid Build Coastguard Worker     kBssEntry,
7069*795d594fSAndroid Build Coastguard Worker     // Load from the root table associated with the JIT compiled method.
7070*795d594fSAndroid Build Coastguard Worker     kJitTableAddress,
7071*795d594fSAndroid Build Coastguard Worker     // Load using a single runtime call.
7072*795d594fSAndroid Build Coastguard Worker     kRuntimeCall,
7073*795d594fSAndroid Build Coastguard Worker 
7074*795d594fSAndroid Build Coastguard Worker     kLast = kRuntimeCall,
7075*795d594fSAndroid Build Coastguard Worker   };
7076*795d594fSAndroid Build Coastguard Worker 
7077*795d594fSAndroid Build Coastguard Worker   HLoadMethodType(HCurrentMethod* current_method,
7078*795d594fSAndroid Build Coastguard Worker                   dex::ProtoIndex proto_index,
7079*795d594fSAndroid Build Coastguard Worker                   const DexFile& dex_file,
7080*795d594fSAndroid Build Coastguard Worker                   uint32_t dex_pc)
7081*795d594fSAndroid Build Coastguard Worker       : HInstruction(kLoadMethodType,
7082*795d594fSAndroid Build Coastguard Worker                      DataType::Type::kReference,
7083*795d594fSAndroid Build Coastguard Worker                      SideEffectsForArchRuntimeCalls(),
7084*795d594fSAndroid Build Coastguard Worker                      dex_pc),
7085*795d594fSAndroid Build Coastguard Worker         special_input_(HUserRecord<HInstruction*>(current_method)),
7086*795d594fSAndroid Build Coastguard Worker         proto_index_(proto_index),
7087*795d594fSAndroid Build Coastguard Worker         dex_file_(dex_file) {
7088*795d594fSAndroid Build Coastguard Worker     SetPackedField<LoadKindField>(LoadKind::kRuntimeCall);
7089*795d594fSAndroid Build Coastguard Worker   }
7090*795d594fSAndroid Build Coastguard Worker 
7091*795d594fSAndroid Build Coastguard Worker   using HInstruction::GetInputRecords;  // Keep the const version visible.
7092*795d594fSAndroid Build Coastguard Worker   ArrayRef<HUserRecord<HInstruction*>> GetInputRecords() final {
7093*795d594fSAndroid Build Coastguard Worker     return ArrayRef<HUserRecord<HInstruction*>>(
7094*795d594fSAndroid Build Coastguard Worker         &special_input_, (special_input_.GetInstruction() != nullptr) ? 1u : 0u);
7095*795d594fSAndroid Build Coastguard Worker   }
7096*795d594fSAndroid Build Coastguard Worker 
7097*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7098*795d594fSAndroid Build Coastguard Worker 
7099*795d594fSAndroid Build Coastguard Worker   void SetLoadKind(LoadKind load_kind);
7100*795d594fSAndroid Build Coastguard Worker 
7101*795d594fSAndroid Build Coastguard Worker   LoadKind GetLoadKind() const {
7102*795d594fSAndroid Build Coastguard Worker     return GetPackedField<LoadKindField>();
7103*795d594fSAndroid Build Coastguard Worker   }
7104*795d594fSAndroid Build Coastguard Worker 
7105*795d594fSAndroid Build Coastguard Worker   dex::ProtoIndex GetProtoIndex() const { return proto_index_; }
7106*795d594fSAndroid Build Coastguard Worker 
7107*795d594fSAndroid Build Coastguard Worker   Handle<mirror::MethodType> GetMethodType() const { return method_type_; }
7108*795d594fSAndroid Build Coastguard Worker 
7109*795d594fSAndroid Build Coastguard Worker   void SetMethodType(Handle<mirror::MethodType> method_type) { method_type_ = method_type; }
7110*795d594fSAndroid Build Coastguard Worker 
7111*795d594fSAndroid Build Coastguard Worker   const DexFile& GetDexFile() const { return dex_file_; }
7112*795d594fSAndroid Build Coastguard Worker 
7113*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls() {
7114*795d594fSAndroid Build Coastguard Worker     return SideEffects::CanTriggerGC();
7115*795d594fSAndroid Build Coastguard Worker   }
7116*795d594fSAndroid Build Coastguard Worker 
7117*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7118*795d594fSAndroid Build Coastguard Worker 
7119*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7120*795d594fSAndroid Build Coastguard Worker 
7121*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LoadMethodType);
7122*795d594fSAndroid Build Coastguard Worker 
7123*795d594fSAndroid Build Coastguard Worker  protected:
7124*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LoadMethodType);
7125*795d594fSAndroid Build Coastguard Worker 
7126*795d594fSAndroid Build Coastguard Worker  private:
7127*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKind = kNumberOfGenericPackedBits;
7128*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldLoadKindSize =
7129*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(LoadKind::kLast));
7130*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfLoadMethodTypePackedBits = kFieldLoadKind + kFieldLoadKindSize;
7131*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfLoadMethodTypePackedBits <= kMaxNumberOfPackedBits,
7132*795d594fSAndroid Build Coastguard Worker       "Too many packed fields.");
7133*795d594fSAndroid Build Coastguard Worker   using LoadKindField = BitField<LoadKind, kFieldLoadKind, kFieldLoadKindSize>;
7134*795d594fSAndroid Build Coastguard Worker 
7135*795d594fSAndroid Build Coastguard Worker   // The special input is the HCurrentMethod for kRuntimeCall.
7136*795d594fSAndroid Build Coastguard Worker   HUserRecord<HInstruction*> special_input_;
7137*795d594fSAndroid Build Coastguard Worker 
7138*795d594fSAndroid Build Coastguard Worker   const dex::ProtoIndex proto_index_;
7139*795d594fSAndroid Build Coastguard Worker   const DexFile& dex_file_;
7140*795d594fSAndroid Build Coastguard Worker 
7141*795d594fSAndroid Build Coastguard Worker   Handle<mirror::MethodType> method_type_;
7142*795d594fSAndroid Build Coastguard Worker };
7143*795d594fSAndroid Build Coastguard Worker 
7144*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, HLoadMethodType::LoadKind rhs);
7145*795d594fSAndroid Build Coastguard Worker 
7146*795d594fSAndroid Build Coastguard Worker // Note: defined outside class to see operator<<(., HLoadMethodType::LoadKind).
7147*795d594fSAndroid Build Coastguard Worker inline void HLoadMethodType::SetLoadKind(LoadKind load_kind) {
7148*795d594fSAndroid Build Coastguard Worker   // The load kind should be determined before inserting the instruction to the graph.
7149*795d594fSAndroid Build Coastguard Worker   DCHECK(GetBlock() == nullptr);
7150*795d594fSAndroid Build Coastguard Worker   DCHECK(GetEnvironment() == nullptr);
7151*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(GetLoadKind(), LoadKind::kRuntimeCall);
7152*795d594fSAndroid Build Coastguard Worker   DCHECK_IMPLIES(GetLoadKind() == LoadKind::kJitTableAddress, GetMethodType() != nullptr);
7153*795d594fSAndroid Build Coastguard Worker   SetPackedField<LoadKindField>(load_kind);
7154*795d594fSAndroid Build Coastguard Worker }
7155*795d594fSAndroid Build Coastguard Worker 
7156*795d594fSAndroid Build Coastguard Worker /**
7157*795d594fSAndroid Build Coastguard Worker  * Performs an initialization check on its Class object input.
7158*795d594fSAndroid Build Coastguard Worker  */
7159*795d594fSAndroid Build Coastguard Worker class HClinitCheck final : public HExpression<1> {
7160*795d594fSAndroid Build Coastguard Worker  public:
7161*795d594fSAndroid Build Coastguard Worker   HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
7162*795d594fSAndroid Build Coastguard Worker       : HExpression(
7163*795d594fSAndroid Build Coastguard Worker             kClinitCheck,
7164*795d594fSAndroid Build Coastguard Worker             DataType::Type::kReference,
7165*795d594fSAndroid Build Coastguard Worker             SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
7166*795d594fSAndroid Build Coastguard Worker             dex_pc) {
7167*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, constant);
7168*795d594fSAndroid Build Coastguard Worker   }
7169*795d594fSAndroid Build Coastguard Worker   // TODO: Make ClinitCheck clonable.
7170*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
7171*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
7172*795d594fSAndroid Build Coastguard Worker     return true;
7173*795d594fSAndroid Build Coastguard Worker   }
7174*795d594fSAndroid Build Coastguard Worker 
7175*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
7176*795d594fSAndroid Build Coastguard Worker     // May call runtime to initialize the class.
7177*795d594fSAndroid Build Coastguard Worker     return true;
7178*795d594fSAndroid Build Coastguard Worker   }
7179*795d594fSAndroid Build Coastguard Worker 
7180*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7181*795d594fSAndroid Build Coastguard Worker 
7182*795d594fSAndroid Build Coastguard Worker   HLoadClass* GetLoadClass() const {
7183*795d594fSAndroid Build Coastguard Worker     DCHECK(InputAt(0)->IsLoadClass());
7184*795d594fSAndroid Build Coastguard Worker     return InputAt(0)->AsLoadClass();
7185*795d594fSAndroid Build Coastguard Worker   }
7186*795d594fSAndroid Build Coastguard Worker 
7187*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ClinitCheck);
7188*795d594fSAndroid Build Coastguard Worker 
7189*795d594fSAndroid Build Coastguard Worker 
7190*795d594fSAndroid Build Coastguard Worker  protected:
7191*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ClinitCheck);
7192*795d594fSAndroid Build Coastguard Worker };
7193*795d594fSAndroid Build Coastguard Worker 
7194*795d594fSAndroid Build Coastguard Worker class HStaticFieldGet final : public HExpression<1> {
7195*795d594fSAndroid Build Coastguard Worker  public:
7196*795d594fSAndroid Build Coastguard Worker   HStaticFieldGet(HInstruction* cls,
7197*795d594fSAndroid Build Coastguard Worker                   ArtField* field,
7198*795d594fSAndroid Build Coastguard Worker                   DataType::Type field_type,
7199*795d594fSAndroid Build Coastguard Worker                   MemberOffset field_offset,
7200*795d594fSAndroid Build Coastguard Worker                   bool is_volatile,
7201*795d594fSAndroid Build Coastguard Worker                   uint32_t field_idx,
7202*795d594fSAndroid Build Coastguard Worker                   uint16_t declaring_class_def_index,
7203*795d594fSAndroid Build Coastguard Worker                   const DexFile& dex_file,
7204*795d594fSAndroid Build Coastguard Worker                   uint32_t dex_pc)
7205*795d594fSAndroid Build Coastguard Worker       : HExpression(kStaticFieldGet,
7206*795d594fSAndroid Build Coastguard Worker                     field_type,
7207*795d594fSAndroid Build Coastguard Worker                     SideEffects::FieldReadOfType(field_type, is_volatile),
7208*795d594fSAndroid Build Coastguard Worker                     dex_pc),
7209*795d594fSAndroid Build Coastguard Worker         field_info_(field,
7210*795d594fSAndroid Build Coastguard Worker                     field_offset,
7211*795d594fSAndroid Build Coastguard Worker                     field_type,
7212*795d594fSAndroid Build Coastguard Worker                     is_volatile,
7213*795d594fSAndroid Build Coastguard Worker                     field_idx,
7214*795d594fSAndroid Build Coastguard Worker                     declaring_class_def_index,
7215*795d594fSAndroid Build Coastguard Worker                     dex_file) {
7216*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cls);
7217*795d594fSAndroid Build Coastguard Worker   }
7218*795d594fSAndroid Build Coastguard Worker 
7219*795d594fSAndroid Build Coastguard Worker 
7220*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7221*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return !IsVolatile(); }
7222*795d594fSAndroid Build Coastguard Worker 
7223*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
7224*795d594fSAndroid Build Coastguard Worker     const HStaticFieldGet* other_get = other->AsStaticFieldGet();
7225*795d594fSAndroid Build Coastguard Worker     return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
7226*795d594fSAndroid Build Coastguard Worker   }
7227*795d594fSAndroid Build Coastguard Worker 
7228*795d594fSAndroid Build Coastguard Worker   size_t ComputeHashCode() const override {
7229*795d594fSAndroid Build Coastguard Worker     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
7230*795d594fSAndroid Build Coastguard Worker   }
7231*795d594fSAndroid Build Coastguard Worker 
7232*795d594fSAndroid Build Coastguard Worker   bool IsFieldAccess() const override { return true; }
7233*795d594fSAndroid Build Coastguard Worker   const FieldInfo& GetFieldInfo() const override { return field_info_; }
7234*795d594fSAndroid Build Coastguard Worker   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
7235*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
7236*795d594fSAndroid Build Coastguard Worker   bool IsVolatile() const { return field_info_.IsVolatile(); }
7237*795d594fSAndroid Build Coastguard Worker 
7238*795d594fSAndroid Build Coastguard Worker   void SetType(DataType::Type new_type) {
7239*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(GetType()));
7240*795d594fSAndroid Build Coastguard Worker     DCHECK(DataType::IsIntegralType(new_type));
7241*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Size(GetType()), DataType::Size(new_type));
7242*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(new_type);
7243*795d594fSAndroid Build Coastguard Worker   }
7244*795d594fSAndroid Build Coastguard Worker 
7245*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(StaticFieldGet);
7246*795d594fSAndroid Build Coastguard Worker 
7247*795d594fSAndroid Build Coastguard Worker  protected:
7248*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(StaticFieldGet);
7249*795d594fSAndroid Build Coastguard Worker 
7250*795d594fSAndroid Build Coastguard Worker  private:
7251*795d594fSAndroid Build Coastguard Worker   const FieldInfo field_info_;
7252*795d594fSAndroid Build Coastguard Worker };
7253*795d594fSAndroid Build Coastguard Worker 
7254*795d594fSAndroid Build Coastguard Worker class HStaticFieldSet final : public HExpression<2> {
7255*795d594fSAndroid Build Coastguard Worker  public:
7256*795d594fSAndroid Build Coastguard Worker   HStaticFieldSet(HInstruction* cls,
7257*795d594fSAndroid Build Coastguard Worker                   HInstruction* value,
7258*795d594fSAndroid Build Coastguard Worker                   ArtField* field,
7259*795d594fSAndroid Build Coastguard Worker                   DataType::Type field_type,
7260*795d594fSAndroid Build Coastguard Worker                   MemberOffset field_offset,
7261*795d594fSAndroid Build Coastguard Worker                   bool is_volatile,
7262*795d594fSAndroid Build Coastguard Worker                   uint32_t field_idx,
7263*795d594fSAndroid Build Coastguard Worker                   uint16_t declaring_class_def_index,
7264*795d594fSAndroid Build Coastguard Worker                   const DexFile& dex_file,
7265*795d594fSAndroid Build Coastguard Worker                   uint32_t dex_pc)
7266*795d594fSAndroid Build Coastguard Worker       : HExpression(kStaticFieldSet,
7267*795d594fSAndroid Build Coastguard Worker                     SideEffects::FieldWriteOfType(field_type, is_volatile),
7268*795d594fSAndroid Build Coastguard Worker                     dex_pc),
7269*795d594fSAndroid Build Coastguard Worker         field_info_(field,
7270*795d594fSAndroid Build Coastguard Worker                     field_offset,
7271*795d594fSAndroid Build Coastguard Worker                     field_type,
7272*795d594fSAndroid Build Coastguard Worker                     is_volatile,
7273*795d594fSAndroid Build Coastguard Worker                     field_idx,
7274*795d594fSAndroid Build Coastguard Worker                     declaring_class_def_index,
7275*795d594fSAndroid Build Coastguard Worker                     dex_file) {
7276*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValueCanBeNull>(true);
7277*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(WriteBarrierKind::kEmitNotBeingReliedOn);
7278*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, cls);
7279*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, value);
7280*795d594fSAndroid Build Coastguard Worker   }
7281*795d594fSAndroid Build Coastguard Worker 
7282*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7283*795d594fSAndroid Build Coastguard Worker   bool IsFieldAccess() const override { return true; }
7284*795d594fSAndroid Build Coastguard Worker   const FieldInfo& GetFieldInfo() const override { return field_info_; }
7285*795d594fSAndroid Build Coastguard Worker   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
7286*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return field_info_.GetFieldType(); }
7287*795d594fSAndroid Build Coastguard Worker   bool IsVolatile() const { return field_info_.IsVolatile(); }
7288*795d594fSAndroid Build Coastguard Worker 
7289*795d594fSAndroid Build Coastguard Worker   HInstruction* GetValue() const { return InputAt(1); }
7290*795d594fSAndroid Build Coastguard Worker   bool GetValueCanBeNull() const { return GetPackedFlag<kFlagValueCanBeNull>(); }
7291*795d594fSAndroid Build Coastguard Worker   void ClearValueCanBeNull() { SetPackedFlag<kFlagValueCanBeNull>(false); }
7292*795d594fSAndroid Build Coastguard Worker 
7293*795d594fSAndroid Build Coastguard Worker   WriteBarrierKind GetWriteBarrierKind() { return GetPackedField<WriteBarrierKindField>(); }
7294*795d594fSAndroid Build Coastguard Worker   void SetWriteBarrierKind(WriteBarrierKind kind) {
7295*795d594fSAndroid Build Coastguard Worker     DCHECK(kind != WriteBarrierKind::kEmitNotBeingReliedOn)
7296*795d594fSAndroid Build Coastguard Worker         << "We shouldn't go back to the original value.";
7297*795d594fSAndroid Build Coastguard Worker     DCHECK_IMPLIES(kind == WriteBarrierKind::kDontEmit,
7298*795d594fSAndroid Build Coastguard Worker                    GetWriteBarrierKind() != WriteBarrierKind::kEmitBeingReliedOn)
7299*795d594fSAndroid Build Coastguard Worker         << "If a write barrier was relied on by other write barriers, we cannot skip emitting it.";
7300*795d594fSAndroid Build Coastguard Worker     SetPackedField<WriteBarrierKindField>(kind);
7301*795d594fSAndroid Build Coastguard Worker   }
7302*795d594fSAndroid Build Coastguard Worker 
7303*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(StaticFieldSet);
7304*795d594fSAndroid Build Coastguard Worker 
7305*795d594fSAndroid Build Coastguard Worker  protected:
7306*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(StaticFieldSet);
7307*795d594fSAndroid Build Coastguard Worker 
7308*795d594fSAndroid Build Coastguard Worker  private:
7309*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagValueCanBeNull = kNumberOfGenericPackedBits;
7310*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKind = kFlagValueCanBeNull + 1;
7311*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kWriteBarrierKindSize =
7312*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(WriteBarrierKind::kLast));
7313*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfStaticFieldSetPackedBits =
7314*795d594fSAndroid Build Coastguard Worker       kWriteBarrierKind + kWriteBarrierKindSize;
7315*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfStaticFieldSetPackedBits <= kMaxNumberOfPackedBits,
7316*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
7317*795d594fSAndroid Build Coastguard Worker 
7318*795d594fSAndroid Build Coastguard Worker   const FieldInfo field_info_;
7319*795d594fSAndroid Build Coastguard Worker   using WriteBarrierKindField =
7320*795d594fSAndroid Build Coastguard Worker       BitField<WriteBarrierKind, kWriteBarrierKind, kWriteBarrierKindSize>;
7321*795d594fSAndroid Build Coastguard Worker };
7322*795d594fSAndroid Build Coastguard Worker 
7323*795d594fSAndroid Build Coastguard Worker class HStringBuilderAppend final : public HVariableInputSizeInstruction {
7324*795d594fSAndroid Build Coastguard Worker  public:
7325*795d594fSAndroid Build Coastguard Worker   HStringBuilderAppend(HIntConstant* format,
7326*795d594fSAndroid Build Coastguard Worker                        uint32_t number_of_arguments,
7327*795d594fSAndroid Build Coastguard Worker                        uint32_t number_of_out_vregs,
7328*795d594fSAndroid Build Coastguard Worker                        bool has_fp_args,
7329*795d594fSAndroid Build Coastguard Worker                        ArenaAllocator* allocator,
7330*795d594fSAndroid Build Coastguard Worker                        uint32_t dex_pc)
7331*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(
7332*795d594fSAndroid Build Coastguard Worker             kStringBuilderAppend,
7333*795d594fSAndroid Build Coastguard Worker             DataType::Type::kReference,
7334*795d594fSAndroid Build Coastguard Worker             SideEffects::CanTriggerGC().Union(
7335*795d594fSAndroid Build Coastguard Worker                 // The runtime call may read memory from inputs. It never writes outside
7336*795d594fSAndroid Build Coastguard Worker                 // of the newly allocated result object or newly allocated helper objects,
7337*795d594fSAndroid Build Coastguard Worker                 // except for float/double arguments where we reuse thread-local helper objects.
7338*795d594fSAndroid Build Coastguard Worker                 has_fp_args ? SideEffects::AllWritesAndReads() : SideEffects::AllReads()),
7339*795d594fSAndroid Build Coastguard Worker             dex_pc,
7340*795d594fSAndroid Build Coastguard Worker             allocator,
7341*795d594fSAndroid Build Coastguard Worker             number_of_arguments + /* format */ 1u,
7342*795d594fSAndroid Build Coastguard Worker             kArenaAllocInvokeInputs),
7343*795d594fSAndroid Build Coastguard Worker         number_of_out_vregs_(number_of_out_vregs) {
7344*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(number_of_arguments, 1u);  // There must be something to append.
7345*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(FormatIndex(), format);
7346*795d594fSAndroid Build Coastguard Worker   }
7347*795d594fSAndroid Build Coastguard Worker 
7348*795d594fSAndroid Build Coastguard Worker   void SetArgumentAt(size_t index, HInstruction* argument) {
7349*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(index, GetNumberOfArguments());
7350*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(index, argument);
7351*795d594fSAndroid Build Coastguard Worker   }
7352*795d594fSAndroid Build Coastguard Worker 
7353*795d594fSAndroid Build Coastguard Worker   // Return the number of arguments, excluding the format.
7354*795d594fSAndroid Build Coastguard Worker   size_t GetNumberOfArguments() const {
7355*795d594fSAndroid Build Coastguard Worker     DCHECK_GE(InputCount(), 1u);
7356*795d594fSAndroid Build Coastguard Worker     return InputCount() - 1u;
7357*795d594fSAndroid Build Coastguard Worker   }
7358*795d594fSAndroid Build Coastguard Worker 
7359*795d594fSAndroid Build Coastguard Worker   // Return the number of outgoing vregs.
7360*795d594fSAndroid Build Coastguard Worker   uint32_t GetNumberOfOutVRegs() const { return number_of_out_vregs_; }
7361*795d594fSAndroid Build Coastguard Worker 
7362*795d594fSAndroid Build Coastguard Worker   size_t FormatIndex() const {
7363*795d594fSAndroid Build Coastguard Worker     return GetNumberOfArguments();
7364*795d594fSAndroid Build Coastguard Worker   }
7365*795d594fSAndroid Build Coastguard Worker 
7366*795d594fSAndroid Build Coastguard Worker   HIntConstant* GetFormat() {
7367*795d594fSAndroid Build Coastguard Worker     return InputAt(FormatIndex())->AsIntConstant();
7368*795d594fSAndroid Build Coastguard Worker   }
7369*795d594fSAndroid Build Coastguard Worker 
7370*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7371*795d594fSAndroid Build Coastguard Worker 
7372*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7373*795d594fSAndroid Build Coastguard Worker 
7374*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
7375*795d594fSAndroid Build Coastguard Worker 
7376*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(StringBuilderAppend);
7377*795d594fSAndroid Build Coastguard Worker 
7378*795d594fSAndroid Build Coastguard Worker  protected:
7379*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(StringBuilderAppend);
7380*795d594fSAndroid Build Coastguard Worker 
7381*795d594fSAndroid Build Coastguard Worker  private:
7382*795d594fSAndroid Build Coastguard Worker   uint32_t number_of_out_vregs_;
7383*795d594fSAndroid Build Coastguard Worker };
7384*795d594fSAndroid Build Coastguard Worker 
7385*795d594fSAndroid Build Coastguard Worker class HUnresolvedInstanceFieldGet final : public HExpression<1> {
7386*795d594fSAndroid Build Coastguard Worker  public:
7387*795d594fSAndroid Build Coastguard Worker   HUnresolvedInstanceFieldGet(HInstruction* obj,
7388*795d594fSAndroid Build Coastguard Worker                               DataType::Type field_type,
7389*795d594fSAndroid Build Coastguard Worker                               uint32_t field_index,
7390*795d594fSAndroid Build Coastguard Worker                               uint32_t dex_pc)
7391*795d594fSAndroid Build Coastguard Worker       : HExpression(kUnresolvedInstanceFieldGet,
7392*795d594fSAndroid Build Coastguard Worker                     field_type,
7393*795d594fSAndroid Build Coastguard Worker                     SideEffects::AllExceptGCDependency(),
7394*795d594fSAndroid Build Coastguard Worker                     dex_pc),
7395*795d594fSAndroid Build Coastguard Worker         field_index_(field_index) {
7396*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, obj);
7397*795d594fSAndroid Build Coastguard Worker   }
7398*795d594fSAndroid Build Coastguard Worker 
7399*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7400*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7401*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7402*795d594fSAndroid Build Coastguard Worker 
7403*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return GetType(); }
7404*795d594fSAndroid Build Coastguard Worker   uint32_t GetFieldIndex() const { return field_index_; }
7405*795d594fSAndroid Build Coastguard Worker 
7406*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(UnresolvedInstanceFieldGet);
7407*795d594fSAndroid Build Coastguard Worker 
7408*795d594fSAndroid Build Coastguard Worker  protected:
7409*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UnresolvedInstanceFieldGet);
7410*795d594fSAndroid Build Coastguard Worker 
7411*795d594fSAndroid Build Coastguard Worker  private:
7412*795d594fSAndroid Build Coastguard Worker   const uint32_t field_index_;
7413*795d594fSAndroid Build Coastguard Worker };
7414*795d594fSAndroid Build Coastguard Worker 
7415*795d594fSAndroid Build Coastguard Worker class HUnresolvedInstanceFieldSet final : public HExpression<2> {
7416*795d594fSAndroid Build Coastguard Worker  public:
7417*795d594fSAndroid Build Coastguard Worker   HUnresolvedInstanceFieldSet(HInstruction* obj,
7418*795d594fSAndroid Build Coastguard Worker                               HInstruction* value,
7419*795d594fSAndroid Build Coastguard Worker                               DataType::Type field_type,
7420*795d594fSAndroid Build Coastguard Worker                               uint32_t field_index,
7421*795d594fSAndroid Build Coastguard Worker                               uint32_t dex_pc)
7422*795d594fSAndroid Build Coastguard Worker       : HExpression(kUnresolvedInstanceFieldSet, SideEffects::AllExceptGCDependency(), dex_pc),
7423*795d594fSAndroid Build Coastguard Worker         field_index_(field_index) {
7424*795d594fSAndroid Build Coastguard Worker     SetPackedField<FieldTypeField>(field_type);
7425*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
7426*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, obj);
7427*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, value);
7428*795d594fSAndroid Build Coastguard Worker   }
7429*795d594fSAndroid Build Coastguard Worker 
7430*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7431*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7432*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7433*795d594fSAndroid Build Coastguard Worker 
7434*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); }
7435*795d594fSAndroid Build Coastguard Worker   uint32_t GetFieldIndex() const { return field_index_; }
7436*795d594fSAndroid Build Coastguard Worker 
7437*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(UnresolvedInstanceFieldSet);
7438*795d594fSAndroid Build Coastguard Worker 
7439*795d594fSAndroid Build Coastguard Worker  protected:
7440*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UnresolvedInstanceFieldSet);
7441*795d594fSAndroid Build Coastguard Worker 
7442*795d594fSAndroid Build Coastguard Worker  private:
7443*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits;
7444*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFieldTypeSize =
7445*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
7446*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits =
7447*795d594fSAndroid Build Coastguard Worker       kFieldFieldType + kFieldFieldTypeSize;
7448*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
7449*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
7450*795d594fSAndroid Build Coastguard Worker   using FieldTypeField = BitField<DataType::Type, kFieldFieldType, kFieldFieldTypeSize>;
7451*795d594fSAndroid Build Coastguard Worker 
7452*795d594fSAndroid Build Coastguard Worker   const uint32_t field_index_;
7453*795d594fSAndroid Build Coastguard Worker };
7454*795d594fSAndroid Build Coastguard Worker 
7455*795d594fSAndroid Build Coastguard Worker class HUnresolvedStaticFieldGet final : public HExpression<0> {
7456*795d594fSAndroid Build Coastguard Worker  public:
7457*795d594fSAndroid Build Coastguard Worker   HUnresolvedStaticFieldGet(DataType::Type field_type,
7458*795d594fSAndroid Build Coastguard Worker                             uint32_t field_index,
7459*795d594fSAndroid Build Coastguard Worker                             uint32_t dex_pc)
7460*795d594fSAndroid Build Coastguard Worker       : HExpression(kUnresolvedStaticFieldGet,
7461*795d594fSAndroid Build Coastguard Worker                     field_type,
7462*795d594fSAndroid Build Coastguard Worker                     SideEffects::AllExceptGCDependency(),
7463*795d594fSAndroid Build Coastguard Worker                     dex_pc),
7464*795d594fSAndroid Build Coastguard Worker         field_index_(field_index) {
7465*795d594fSAndroid Build Coastguard Worker   }
7466*795d594fSAndroid Build Coastguard Worker 
7467*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7468*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7469*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7470*795d594fSAndroid Build Coastguard Worker 
7471*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return GetType(); }
7472*795d594fSAndroid Build Coastguard Worker   uint32_t GetFieldIndex() const { return field_index_; }
7473*795d594fSAndroid Build Coastguard Worker 
7474*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(UnresolvedStaticFieldGet);
7475*795d594fSAndroid Build Coastguard Worker 
7476*795d594fSAndroid Build Coastguard Worker  protected:
7477*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UnresolvedStaticFieldGet);
7478*795d594fSAndroid Build Coastguard Worker 
7479*795d594fSAndroid Build Coastguard Worker  private:
7480*795d594fSAndroid Build Coastguard Worker   const uint32_t field_index_;
7481*795d594fSAndroid Build Coastguard Worker };
7482*795d594fSAndroid Build Coastguard Worker 
7483*795d594fSAndroid Build Coastguard Worker class HUnresolvedStaticFieldSet final : public HExpression<1> {
7484*795d594fSAndroid Build Coastguard Worker  public:
7485*795d594fSAndroid Build Coastguard Worker   HUnresolvedStaticFieldSet(HInstruction* value,
7486*795d594fSAndroid Build Coastguard Worker                             DataType::Type field_type,
7487*795d594fSAndroid Build Coastguard Worker                             uint32_t field_index,
7488*795d594fSAndroid Build Coastguard Worker                             uint32_t dex_pc)
7489*795d594fSAndroid Build Coastguard Worker       : HExpression(kUnresolvedStaticFieldSet, SideEffects::AllExceptGCDependency(), dex_pc),
7490*795d594fSAndroid Build Coastguard Worker         field_index_(field_index) {
7491*795d594fSAndroid Build Coastguard Worker     SetPackedField<FieldTypeField>(field_type);
7492*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(DataType::Kind(field_type), DataType::Kind(value->GetType()));
7493*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, value);
7494*795d594fSAndroid Build Coastguard Worker   }
7495*795d594fSAndroid Build Coastguard Worker 
7496*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7497*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7498*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7499*795d594fSAndroid Build Coastguard Worker 
7500*795d594fSAndroid Build Coastguard Worker   DataType::Type GetFieldType() const { return GetPackedField<FieldTypeField>(); }
7501*795d594fSAndroid Build Coastguard Worker   uint32_t GetFieldIndex() const { return field_index_; }
7502*795d594fSAndroid Build Coastguard Worker 
7503*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(UnresolvedStaticFieldSet);
7504*795d594fSAndroid Build Coastguard Worker 
7505*795d594fSAndroid Build Coastguard Worker  protected:
7506*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(UnresolvedStaticFieldSet);
7507*795d594fSAndroid Build Coastguard Worker 
7508*795d594fSAndroid Build Coastguard Worker  private:
7509*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFieldType = HInstruction::kNumberOfGenericPackedBits;
7510*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldFieldTypeSize =
7511*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(DataType::Type::kLast));
7512*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfUnresolvedStaticFieldSetPackedBits =
7513*795d594fSAndroid Build Coastguard Worker       kFieldFieldType + kFieldFieldTypeSize;
7514*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfUnresolvedStaticFieldSetPackedBits <= HInstruction::kMaxNumberOfPackedBits,
7515*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
7516*795d594fSAndroid Build Coastguard Worker   using FieldTypeField = BitField<DataType::Type, kFieldFieldType, kFieldFieldTypeSize>;
7517*795d594fSAndroid Build Coastguard Worker 
7518*795d594fSAndroid Build Coastguard Worker   const uint32_t field_index_;
7519*795d594fSAndroid Build Coastguard Worker };
7520*795d594fSAndroid Build Coastguard Worker 
7521*795d594fSAndroid Build Coastguard Worker // Implement the move-exception DEX instruction.
7522*795d594fSAndroid Build Coastguard Worker class HLoadException final : public HExpression<0> {
7523*795d594fSAndroid Build Coastguard Worker  public:
7524*795d594fSAndroid Build Coastguard Worker   explicit HLoadException(uint32_t dex_pc = kNoDexPc)
7525*795d594fSAndroid Build Coastguard Worker       : HExpression(kLoadException, DataType::Type::kReference, SideEffects::None(), dex_pc) {
7526*795d594fSAndroid Build Coastguard Worker   }
7527*795d594fSAndroid Build Coastguard Worker 
7528*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return false; }
7529*795d594fSAndroid Build Coastguard Worker 
7530*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(LoadException);
7531*795d594fSAndroid Build Coastguard Worker 
7532*795d594fSAndroid Build Coastguard Worker  protected:
7533*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(LoadException);
7534*795d594fSAndroid Build Coastguard Worker };
7535*795d594fSAndroid Build Coastguard Worker 
7536*795d594fSAndroid Build Coastguard Worker // Implicit part of move-exception which clears thread-local exception storage.
7537*795d594fSAndroid Build Coastguard Worker // Must not be removed because the runtime expects the TLS to get cleared.
7538*795d594fSAndroid Build Coastguard Worker class HClearException final : public HExpression<0> {
7539*795d594fSAndroid Build Coastguard Worker  public:
7540*795d594fSAndroid Build Coastguard Worker   explicit HClearException(uint32_t dex_pc = kNoDexPc)
7541*795d594fSAndroid Build Coastguard Worker       : HExpression(kClearException, SideEffects::AllWrites(), dex_pc) {
7542*795d594fSAndroid Build Coastguard Worker   }
7543*795d594fSAndroid Build Coastguard Worker 
7544*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ClearException);
7545*795d594fSAndroid Build Coastguard Worker 
7546*795d594fSAndroid Build Coastguard Worker  protected:
7547*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ClearException);
7548*795d594fSAndroid Build Coastguard Worker };
7549*795d594fSAndroid Build Coastguard Worker 
7550*795d594fSAndroid Build Coastguard Worker class HThrow final : public HExpression<1> {
7551*795d594fSAndroid Build Coastguard Worker  public:
7552*795d594fSAndroid Build Coastguard Worker   HThrow(HInstruction* exception, uint32_t dex_pc)
7553*795d594fSAndroid Build Coastguard Worker       : HExpression(kThrow, SideEffects::CanTriggerGC(), dex_pc) {
7554*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, exception);
7555*795d594fSAndroid Build Coastguard Worker   }
7556*795d594fSAndroid Build Coastguard Worker 
7557*795d594fSAndroid Build Coastguard Worker   bool IsControlFlow() const override { return true; }
7558*795d594fSAndroid Build Coastguard Worker 
7559*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
7560*795d594fSAndroid Build Coastguard Worker 
7561*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7562*795d594fSAndroid Build Coastguard Worker 
7563*795d594fSAndroid Build Coastguard Worker   bool AlwaysThrows() const override { return true; }
7564*795d594fSAndroid Build Coastguard Worker 
7565*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Throw);
7566*795d594fSAndroid Build Coastguard Worker 
7567*795d594fSAndroid Build Coastguard Worker  protected:
7568*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Throw);
7569*795d594fSAndroid Build Coastguard Worker };
7570*795d594fSAndroid Build Coastguard Worker 
7571*795d594fSAndroid Build Coastguard Worker /**
7572*795d594fSAndroid Build Coastguard Worker  * Implementation strategies for the code generator of a HInstanceOf
7573*795d594fSAndroid Build Coastguard Worker  * or `HCheckCast`.
7574*795d594fSAndroid Build Coastguard Worker  */
7575*795d594fSAndroid Build Coastguard Worker enum class TypeCheckKind {  // private marker to avoid generate-operator-out.py from processing.
7576*795d594fSAndroid Build Coastguard Worker   kUnresolvedCheck,       // Check against an unresolved type.
7577*795d594fSAndroid Build Coastguard Worker   kExactCheck,            // Can do a single class compare.
7578*795d594fSAndroid Build Coastguard Worker   kClassHierarchyCheck,   // Can just walk the super class chain.
7579*795d594fSAndroid Build Coastguard Worker   kAbstractClassCheck,    // Can just walk the super class chain, starting one up.
7580*795d594fSAndroid Build Coastguard Worker   kInterfaceCheck,        // No optimization yet when checking against an interface.
7581*795d594fSAndroid Build Coastguard Worker   kArrayObjectCheck,      // Can just check if the array is not primitive.
7582*795d594fSAndroid Build Coastguard Worker   kArrayCheck,            // No optimization yet when checking against a generic array.
7583*795d594fSAndroid Build Coastguard Worker   kBitstringCheck,        // Compare the type check bitstring.
7584*795d594fSAndroid Build Coastguard Worker   kLast = kArrayCheck
7585*795d594fSAndroid Build Coastguard Worker };
7586*795d594fSAndroid Build Coastguard Worker 
7587*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, TypeCheckKind rhs);
7588*795d594fSAndroid Build Coastguard Worker 
7589*795d594fSAndroid Build Coastguard Worker // Note: HTypeCheckInstruction is just a helper class, not an abstract instruction with an
7590*795d594fSAndroid Build Coastguard Worker // `IsTypeCheckInstruction()`. (New virtual methods in the HInstruction class have a high cost.)
7591*795d594fSAndroid Build Coastguard Worker class HTypeCheckInstruction : public HVariableInputSizeInstruction {
7592*795d594fSAndroid Build Coastguard Worker  public:
7593*795d594fSAndroid Build Coastguard Worker   HTypeCheckInstruction(InstructionKind kind,
7594*795d594fSAndroid Build Coastguard Worker                         DataType::Type type,
7595*795d594fSAndroid Build Coastguard Worker                         HInstruction* object,
7596*795d594fSAndroid Build Coastguard Worker                         HInstruction* target_class_or_null,
7597*795d594fSAndroid Build Coastguard Worker                         TypeCheckKind check_kind,
7598*795d594fSAndroid Build Coastguard Worker                         Handle<mirror::Class> klass,
7599*795d594fSAndroid Build Coastguard Worker                         uint32_t dex_pc,
7600*795d594fSAndroid Build Coastguard Worker                         ArenaAllocator* allocator,
7601*795d594fSAndroid Build Coastguard Worker                         HIntConstant* bitstring_path_to_root,
7602*795d594fSAndroid Build Coastguard Worker                         HIntConstant* bitstring_mask,
7603*795d594fSAndroid Build Coastguard Worker                         SideEffects side_effects)
7604*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(
7605*795d594fSAndroid Build Coastguard Worker           kind,
7606*795d594fSAndroid Build Coastguard Worker           type,
7607*795d594fSAndroid Build Coastguard Worker           side_effects,
7608*795d594fSAndroid Build Coastguard Worker           dex_pc,
7609*795d594fSAndroid Build Coastguard Worker           allocator,
7610*795d594fSAndroid Build Coastguard Worker           /* number_of_inputs= */ check_kind == TypeCheckKind::kBitstringCheck ? 4u : 2u,
7611*795d594fSAndroid Build Coastguard Worker           kArenaAllocTypeCheckInputs),
7612*795d594fSAndroid Build Coastguard Worker         klass_(klass) {
7613*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeCheckKindField>(check_kind);
7614*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagMustDoNullCheck>(true);
7615*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValidTargetClassRTI>(false);
7616*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, object);
7617*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, target_class_or_null);
7618*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(check_kind == TypeCheckKind::kBitstringCheck, bitstring_path_to_root != nullptr);
7619*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(check_kind == TypeCheckKind::kBitstringCheck, bitstring_mask != nullptr);
7620*795d594fSAndroid Build Coastguard Worker     if (check_kind == TypeCheckKind::kBitstringCheck) {
7621*795d594fSAndroid Build Coastguard Worker       DCHECK(target_class_or_null->IsNullConstant());
7622*795d594fSAndroid Build Coastguard Worker       SetRawInputAt(2, bitstring_path_to_root);
7623*795d594fSAndroid Build Coastguard Worker       SetRawInputAt(3, bitstring_mask);
7624*795d594fSAndroid Build Coastguard Worker     } else {
7625*795d594fSAndroid Build Coastguard Worker       DCHECK(target_class_or_null->IsLoadClass());
7626*795d594fSAndroid Build Coastguard Worker     }
7627*795d594fSAndroid Build Coastguard Worker   }
7628*795d594fSAndroid Build Coastguard Worker 
7629*795d594fSAndroid Build Coastguard Worker   HLoadClass* GetTargetClass() const {
7630*795d594fSAndroid Build Coastguard Worker     DCHECK_NE(GetTypeCheckKind(), TypeCheckKind::kBitstringCheck);
7631*795d594fSAndroid Build Coastguard Worker     HInstruction* load_class = InputAt(1);
7632*795d594fSAndroid Build Coastguard Worker     DCHECK(load_class->IsLoadClass());
7633*795d594fSAndroid Build Coastguard Worker     return load_class->AsLoadClass();
7634*795d594fSAndroid Build Coastguard Worker   }
7635*795d594fSAndroid Build Coastguard Worker 
7636*795d594fSAndroid Build Coastguard Worker   uint32_t GetBitstringPathToRoot() const {
7637*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetTypeCheckKind(), TypeCheckKind::kBitstringCheck);
7638*795d594fSAndroid Build Coastguard Worker     HInstruction* path_to_root = InputAt(2);
7639*795d594fSAndroid Build Coastguard Worker     DCHECK(path_to_root->IsIntConstant());
7640*795d594fSAndroid Build Coastguard Worker     return static_cast<uint32_t>(path_to_root->AsIntConstant()->GetValue());
7641*795d594fSAndroid Build Coastguard Worker   }
7642*795d594fSAndroid Build Coastguard Worker 
7643*795d594fSAndroid Build Coastguard Worker   uint32_t GetBitstringMask() const {
7644*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(GetTypeCheckKind(), TypeCheckKind::kBitstringCheck);
7645*795d594fSAndroid Build Coastguard Worker     HInstruction* mask = InputAt(3);
7646*795d594fSAndroid Build Coastguard Worker     DCHECK(mask->IsIntConstant());
7647*795d594fSAndroid Build Coastguard Worker     return static_cast<uint32_t>(mask->AsIntConstant()->GetValue());
7648*795d594fSAndroid Build Coastguard Worker   }
7649*795d594fSAndroid Build Coastguard Worker 
7650*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7651*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
7652*795d594fSAndroid Build Coastguard Worker 
7653*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
7654*795d594fSAndroid Build Coastguard Worker     DCHECK(other->IsInstanceOf() || other->IsCheckCast()) << other->DebugName();
7655*795d594fSAndroid Build Coastguard Worker     return GetPackedFields() == down_cast<const HTypeCheckInstruction*>(other)->GetPackedFields();
7656*795d594fSAndroid Build Coastguard Worker   }
7657*795d594fSAndroid Build Coastguard Worker 
7658*795d594fSAndroid Build Coastguard Worker   bool MustDoNullCheck() const { return GetPackedFlag<kFlagMustDoNullCheck>(); }
7659*795d594fSAndroid Build Coastguard Worker   void ClearMustDoNullCheck() { SetPackedFlag<kFlagMustDoNullCheck>(false); }
7660*795d594fSAndroid Build Coastguard Worker   TypeCheckKind GetTypeCheckKind() const { return GetPackedField<TypeCheckKindField>(); }
7661*795d594fSAndroid Build Coastguard Worker   bool IsExactCheck() const { return GetTypeCheckKind() == TypeCheckKind::kExactCheck; }
7662*795d594fSAndroid Build Coastguard Worker 
7663*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo GetTargetClassRTI() {
7664*795d594fSAndroid Build Coastguard Worker     if (GetPackedFlag<kFlagValidTargetClassRTI>()) {
7665*795d594fSAndroid Build Coastguard Worker       // Note: The is_exact flag from the return value should not be used.
7666*795d594fSAndroid Build Coastguard Worker       return ReferenceTypeInfo::CreateUnchecked(klass_, /* is_exact= */ true);
7667*795d594fSAndroid Build Coastguard Worker     } else {
7668*795d594fSAndroid Build Coastguard Worker       return ReferenceTypeInfo::CreateInvalid();
7669*795d594fSAndroid Build Coastguard Worker     }
7670*795d594fSAndroid Build Coastguard Worker   }
7671*795d594fSAndroid Build Coastguard Worker 
7672*795d594fSAndroid Build Coastguard Worker   // Target class RTI is marked as valid by RTP if the klass_ is admissible.
7673*795d594fSAndroid Build Coastguard Worker   void SetValidTargetClassRTI() {
7674*795d594fSAndroid Build Coastguard Worker     DCHECK(klass_ != nullptr);
7675*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagValidTargetClassRTI>(true);
7676*795d594fSAndroid Build Coastguard Worker   }
7677*795d594fSAndroid Build Coastguard Worker 
7678*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> GetClass() const {
7679*795d594fSAndroid Build Coastguard Worker     return klass_;
7680*795d594fSAndroid Build Coastguard Worker   }
7681*795d594fSAndroid Build Coastguard Worker 
7682*795d594fSAndroid Build Coastguard Worker  protected:
7683*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(TypeCheckInstruction);
7684*795d594fSAndroid Build Coastguard Worker 
7685*795d594fSAndroid Build Coastguard Worker  private:
7686*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldTypeCheckKind = kNumberOfGenericPackedBits;
7687*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldTypeCheckKindSize =
7688*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(TypeCheckKind::kLast));
7689*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagMustDoNullCheck = kFieldTypeCheckKind + kFieldTypeCheckKindSize;
7690*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagValidTargetClassRTI = kFlagMustDoNullCheck + 1;
7691*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfInstanceOfPackedBits = kFlagValidTargetClassRTI + 1;
7692*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfInstanceOfPackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
7693*795d594fSAndroid Build Coastguard Worker   using TypeCheckKindField = BitField<TypeCheckKind, kFieldTypeCheckKind, kFieldTypeCheckKindSize>;
7694*795d594fSAndroid Build Coastguard Worker 
7695*795d594fSAndroid Build Coastguard Worker   Handle<mirror::Class> klass_;
7696*795d594fSAndroid Build Coastguard Worker };
7697*795d594fSAndroid Build Coastguard Worker 
7698*795d594fSAndroid Build Coastguard Worker class HInstanceOf final : public HTypeCheckInstruction {
7699*795d594fSAndroid Build Coastguard Worker  public:
7700*795d594fSAndroid Build Coastguard Worker   HInstanceOf(HInstruction* object,
7701*795d594fSAndroid Build Coastguard Worker               HInstruction* target_class_or_null,
7702*795d594fSAndroid Build Coastguard Worker               TypeCheckKind check_kind,
7703*795d594fSAndroid Build Coastguard Worker               Handle<mirror::Class> klass,
7704*795d594fSAndroid Build Coastguard Worker               uint32_t dex_pc,
7705*795d594fSAndroid Build Coastguard Worker               ArenaAllocator* allocator,
7706*795d594fSAndroid Build Coastguard Worker               HIntConstant* bitstring_path_to_root,
7707*795d594fSAndroid Build Coastguard Worker               HIntConstant* bitstring_mask)
7708*795d594fSAndroid Build Coastguard Worker       : HTypeCheckInstruction(kInstanceOf,
7709*795d594fSAndroid Build Coastguard Worker                               DataType::Type::kBool,
7710*795d594fSAndroid Build Coastguard Worker                               object,
7711*795d594fSAndroid Build Coastguard Worker                               target_class_or_null,
7712*795d594fSAndroid Build Coastguard Worker                               check_kind,
7713*795d594fSAndroid Build Coastguard Worker                               klass,
7714*795d594fSAndroid Build Coastguard Worker                               dex_pc,
7715*795d594fSAndroid Build Coastguard Worker                               allocator,
7716*795d594fSAndroid Build Coastguard Worker                               bitstring_path_to_root,
7717*795d594fSAndroid Build Coastguard Worker                               bitstring_mask,
7718*795d594fSAndroid Build Coastguard Worker                               SideEffectsForArchRuntimeCalls(check_kind)) {}
7719*795d594fSAndroid Build Coastguard Worker 
7720*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7721*795d594fSAndroid Build Coastguard Worker 
7722*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
7723*795d594fSAndroid Build Coastguard Worker     return CanCallRuntime(GetTypeCheckKind());
7724*795d594fSAndroid Build Coastguard Worker   }
7725*795d594fSAndroid Build Coastguard Worker 
7726*795d594fSAndroid Build Coastguard Worker   static bool CanCallRuntime(TypeCheckKind check_kind) {
7727*795d594fSAndroid Build Coastguard Worker     // TODO: Re-evaluate now that mips codegen has been removed.
7728*795d594fSAndroid Build Coastguard Worker     return check_kind != TypeCheckKind::kExactCheck;
7729*795d594fSAndroid Build Coastguard Worker   }
7730*795d594fSAndroid Build Coastguard Worker 
7731*795d594fSAndroid Build Coastguard Worker   static SideEffects SideEffectsForArchRuntimeCalls(TypeCheckKind check_kind) {
7732*795d594fSAndroid Build Coastguard Worker     return CanCallRuntime(check_kind) ? SideEffects::CanTriggerGC() : SideEffects::None();
7733*795d594fSAndroid Build Coastguard Worker   }
7734*795d594fSAndroid Build Coastguard Worker 
7735*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(InstanceOf);
7736*795d594fSAndroid Build Coastguard Worker 
7737*795d594fSAndroid Build Coastguard Worker  protected:
7738*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(InstanceOf);
7739*795d594fSAndroid Build Coastguard Worker };
7740*795d594fSAndroid Build Coastguard Worker 
7741*795d594fSAndroid Build Coastguard Worker class HBoundType final : public HExpression<1> {
7742*795d594fSAndroid Build Coastguard Worker  public:
7743*795d594fSAndroid Build Coastguard Worker   explicit HBoundType(HInstruction* input, uint32_t dex_pc = kNoDexPc)
7744*795d594fSAndroid Build Coastguard Worker       : HExpression(kBoundType, DataType::Type::kReference, SideEffects::None(), dex_pc),
7745*795d594fSAndroid Build Coastguard Worker         upper_bound_(ReferenceTypeInfo::CreateInvalid()) {
7746*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagUpperCanBeNull>(true);
7747*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagCanBeNull>(true);
7748*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(input->GetType(), DataType::Type::kReference);
7749*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, input);
7750*795d594fSAndroid Build Coastguard Worker   }
7751*795d594fSAndroid Build Coastguard Worker 
7752*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override;
7753*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7754*795d594fSAndroid Build Coastguard Worker 
7755*795d594fSAndroid Build Coastguard Worker   // {Get,Set}Upper* should only be used in reference type propagation.
7756*795d594fSAndroid Build Coastguard Worker   const ReferenceTypeInfo& GetUpperBound() const { return upper_bound_; }
7757*795d594fSAndroid Build Coastguard Worker   bool GetUpperCanBeNull() const { return GetPackedFlag<kFlagUpperCanBeNull>(); }
7758*795d594fSAndroid Build Coastguard Worker   void SetUpperBound(const ReferenceTypeInfo& upper_bound, bool can_be_null);
7759*795d594fSAndroid Build Coastguard Worker 
7760*795d594fSAndroid Build Coastguard Worker   void SetCanBeNull(bool can_be_null) {
7761*795d594fSAndroid Build Coastguard Worker     DCHECK(GetUpperCanBeNull() || !can_be_null);
7762*795d594fSAndroid Build Coastguard Worker     SetPackedFlag<kFlagCanBeNull>(can_be_null);
7763*795d594fSAndroid Build Coastguard Worker   }
7764*795d594fSAndroid Build Coastguard Worker 
7765*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override { return GetPackedFlag<kFlagCanBeNull>(); }
7766*795d594fSAndroid Build Coastguard Worker 
7767*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(BoundType);
7768*795d594fSAndroid Build Coastguard Worker 
7769*795d594fSAndroid Build Coastguard Worker  protected:
7770*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BoundType);
7771*795d594fSAndroid Build Coastguard Worker 
7772*795d594fSAndroid Build Coastguard Worker  private:
7773*795d594fSAndroid Build Coastguard Worker   // Represents the top constraint that can_be_null_ cannot exceed (i.e. if this
7774*795d594fSAndroid Build Coastguard Worker   // is false then CanBeNull() cannot be true).
7775*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagUpperCanBeNull = kNumberOfGenericPackedBits;
7776*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFlagCanBeNull = kFlagUpperCanBeNull + 1;
7777*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfBoundTypePackedBits = kFlagCanBeNull + 1;
7778*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfBoundTypePackedBits <= kMaxNumberOfPackedBits, "Too many packed fields.");
7779*795d594fSAndroid Build Coastguard Worker 
7780*795d594fSAndroid Build Coastguard Worker   // Encodes the most upper class that this instruction can have. In other words
7781*795d594fSAndroid Build Coastguard Worker   // it is always the case that GetUpperBound().IsSupertypeOf(GetReferenceType()).
7782*795d594fSAndroid Build Coastguard Worker   // It is used to bound the type in cases like:
7783*795d594fSAndroid Build Coastguard Worker   //   if (x instanceof ClassX) {
7784*795d594fSAndroid Build Coastguard Worker   //     // uper_bound_ will be ClassX
7785*795d594fSAndroid Build Coastguard Worker   //   }
7786*795d594fSAndroid Build Coastguard Worker   ReferenceTypeInfo upper_bound_;
7787*795d594fSAndroid Build Coastguard Worker };
7788*795d594fSAndroid Build Coastguard Worker 
7789*795d594fSAndroid Build Coastguard Worker class HCheckCast final : public HTypeCheckInstruction {
7790*795d594fSAndroid Build Coastguard Worker  public:
7791*795d594fSAndroid Build Coastguard Worker   HCheckCast(HInstruction* object,
7792*795d594fSAndroid Build Coastguard Worker              HInstruction* target_class_or_null,
7793*795d594fSAndroid Build Coastguard Worker              TypeCheckKind check_kind,
7794*795d594fSAndroid Build Coastguard Worker              Handle<mirror::Class> klass,
7795*795d594fSAndroid Build Coastguard Worker              uint32_t dex_pc,
7796*795d594fSAndroid Build Coastguard Worker              ArenaAllocator* allocator,
7797*795d594fSAndroid Build Coastguard Worker              HIntConstant* bitstring_path_to_root,
7798*795d594fSAndroid Build Coastguard Worker              HIntConstant* bitstring_mask)
7799*795d594fSAndroid Build Coastguard Worker       : HTypeCheckInstruction(kCheckCast,
7800*795d594fSAndroid Build Coastguard Worker                               DataType::Type::kVoid,
7801*795d594fSAndroid Build Coastguard Worker                               object,
7802*795d594fSAndroid Build Coastguard Worker                               target_class_or_null,
7803*795d594fSAndroid Build Coastguard Worker                               check_kind,
7804*795d594fSAndroid Build Coastguard Worker                               klass,
7805*795d594fSAndroid Build Coastguard Worker                               dex_pc,
7806*795d594fSAndroid Build Coastguard Worker                               allocator,
7807*795d594fSAndroid Build Coastguard Worker                               bitstring_path_to_root,
7808*795d594fSAndroid Build Coastguard Worker                               bitstring_mask,
7809*795d594fSAndroid Build Coastguard Worker                               SideEffects::CanTriggerGC()) {}
7810*795d594fSAndroid Build Coastguard Worker 
7811*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7812*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override {
7813*795d594fSAndroid Build Coastguard Worker     // Instruction may throw a CheckCastError.
7814*795d594fSAndroid Build Coastguard Worker     return true;
7815*795d594fSAndroid Build Coastguard Worker   }
7816*795d594fSAndroid Build Coastguard Worker 
7817*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override { return true; }
7818*795d594fSAndroid Build Coastguard Worker 
7819*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(CheckCast);
7820*795d594fSAndroid Build Coastguard Worker 
7821*795d594fSAndroid Build Coastguard Worker  protected:
7822*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(CheckCast);
7823*795d594fSAndroid Build Coastguard Worker };
7824*795d594fSAndroid Build Coastguard Worker 
7825*795d594fSAndroid Build Coastguard Worker /**
7826*795d594fSAndroid Build Coastguard Worker  * @brief Memory barrier types (see "The JSR-133 Cookbook for Compiler Writers").
7827*795d594fSAndroid Build Coastguard Worker  * @details We define the combined barrier types that are actually required
7828*795d594fSAndroid Build Coastguard Worker  * by the Java Memory Model, rather than using exactly the terminology from
7829*795d594fSAndroid Build Coastguard Worker  * the JSR-133 cookbook.  These should, in many cases, be replaced by acquire/release
7830*795d594fSAndroid Build Coastguard Worker  * primitives.  Note that the JSR-133 cookbook generally does not deal with
7831*795d594fSAndroid Build Coastguard Worker  * store atomicity issues, and the recipes there are not always entirely sufficient.
7832*795d594fSAndroid Build Coastguard Worker  * The current recipe is as follows:
7833*795d594fSAndroid Build Coastguard Worker  * -# Use AnyStore ~= (LoadStore | StoreStore) ~= release barrier before volatile store.
7834*795d594fSAndroid Build Coastguard Worker  * -# Use AnyAny barrier after volatile store.  (StoreLoad is as expensive.)
7835*795d594fSAndroid Build Coastguard Worker  * -# Use LoadAny barrier ~= (LoadLoad | LoadStore) ~= acquire barrier after each volatile load.
7836*795d594fSAndroid Build Coastguard Worker  * -# Use StoreStore barrier after all stores but before return from any constructor whose
7837*795d594fSAndroid Build Coastguard Worker  *    class has final fields.
7838*795d594fSAndroid Build Coastguard Worker  * -# Use NTStoreStore to order non-temporal stores with respect to all later
7839*795d594fSAndroid Build Coastguard Worker  *    store-to-memory instructions.  Only generated together with non-temporal stores.
7840*795d594fSAndroid Build Coastguard Worker  */
7841*795d594fSAndroid Build Coastguard Worker enum MemBarrierKind {
7842*795d594fSAndroid Build Coastguard Worker   kAnyStore,
7843*795d594fSAndroid Build Coastguard Worker   kLoadAny,
7844*795d594fSAndroid Build Coastguard Worker   kStoreStore,
7845*795d594fSAndroid Build Coastguard Worker   kAnyAny,
7846*795d594fSAndroid Build Coastguard Worker   kNTStoreStore,
7847*795d594fSAndroid Build Coastguard Worker   kLastBarrierKind = kNTStoreStore
7848*795d594fSAndroid Build Coastguard Worker };
7849*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, MemBarrierKind kind);
7850*795d594fSAndroid Build Coastguard Worker 
7851*795d594fSAndroid Build Coastguard Worker class HMemoryBarrier final : public HExpression<0> {
7852*795d594fSAndroid Build Coastguard Worker  public:
7853*795d594fSAndroid Build Coastguard Worker   explicit HMemoryBarrier(MemBarrierKind barrier_kind, uint32_t dex_pc = kNoDexPc)
7854*795d594fSAndroid Build Coastguard Worker       : HExpression(kMemoryBarrier,
7855*795d594fSAndroid Build Coastguard Worker                     SideEffects::AllWritesAndReads(),  // Assume write/read on all fields/arrays.
7856*795d594fSAndroid Build Coastguard Worker                     dex_pc) {
7857*795d594fSAndroid Build Coastguard Worker     SetPackedField<BarrierKindField>(barrier_kind);
7858*795d594fSAndroid Build Coastguard Worker   }
7859*795d594fSAndroid Build Coastguard Worker 
7860*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
7861*795d594fSAndroid Build Coastguard Worker 
7862*795d594fSAndroid Build Coastguard Worker   MemBarrierKind GetBarrierKind() { return GetPackedField<BarrierKindField>(); }
7863*795d594fSAndroid Build Coastguard Worker 
7864*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(MemoryBarrier);
7865*795d594fSAndroid Build Coastguard Worker 
7866*795d594fSAndroid Build Coastguard Worker  protected:
7867*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(MemoryBarrier);
7868*795d594fSAndroid Build Coastguard Worker 
7869*795d594fSAndroid Build Coastguard Worker  private:
7870*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldBarrierKind = HInstruction::kNumberOfGenericPackedBits;
7871*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldBarrierKindSize =
7872*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(kLastBarrierKind));
7873*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfMemoryBarrierPackedBits =
7874*795d594fSAndroid Build Coastguard Worker       kFieldBarrierKind + kFieldBarrierKindSize;
7875*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfMemoryBarrierPackedBits <= kMaxNumberOfPackedBits,
7876*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
7877*795d594fSAndroid Build Coastguard Worker   using BarrierKindField = BitField<MemBarrierKind, kFieldBarrierKind, kFieldBarrierKindSize>;
7878*795d594fSAndroid Build Coastguard Worker };
7879*795d594fSAndroid Build Coastguard Worker 
7880*795d594fSAndroid Build Coastguard Worker // A constructor fence orders all prior stores to fields that could be accessed via a final field of
7881*795d594fSAndroid Build Coastguard Worker // the specified object(s), with respect to any subsequent store that might "publish"
7882*795d594fSAndroid Build Coastguard Worker // (i.e. make visible) the specified object to another thread.
7883*795d594fSAndroid Build Coastguard Worker //
7884*795d594fSAndroid Build Coastguard Worker // JLS 17.5.1 "Semantics of final fields" states that a freeze action happens
7885*795d594fSAndroid Build Coastguard Worker // for all final fields (that were set) at the end of the invoked constructor.
7886*795d594fSAndroid Build Coastguard Worker //
7887*795d594fSAndroid Build Coastguard Worker // The constructor fence models the freeze actions for the final fields of an object
7888*795d594fSAndroid Build Coastguard Worker // being constructed (semantically at the end of the constructor). Constructor fences
7889*795d594fSAndroid Build Coastguard Worker // have a per-object affinity; two separate objects being constructed get two separate
7890*795d594fSAndroid Build Coastguard Worker // constructor fences.
7891*795d594fSAndroid Build Coastguard Worker //
7892*795d594fSAndroid Build Coastguard Worker // (Note: that if calling a super-constructor or forwarding to another constructor,
7893*795d594fSAndroid Build Coastguard Worker // the freezes would happen at the end of *that* constructor being invoked).
7894*795d594fSAndroid Build Coastguard Worker //
7895*795d594fSAndroid Build Coastguard Worker // The memory model guarantees that when the object being constructed is "published" after
7896*795d594fSAndroid Build Coastguard Worker // constructor completion (i.e. escapes the current thread via a store), then any final field
7897*795d594fSAndroid Build Coastguard Worker // writes must be observable on other threads (once they observe that publication).
7898*795d594fSAndroid Build Coastguard Worker //
7899*795d594fSAndroid Build Coastguard Worker // Further, anything written before the freeze, and read by dereferencing through the final field,
7900*795d594fSAndroid Build Coastguard Worker // must also be visible (so final object field could itself have an object with non-final fields;
7901*795d594fSAndroid Build Coastguard Worker // yet the freeze must also extend to them).
7902*795d594fSAndroid Build Coastguard Worker //
7903*795d594fSAndroid Build Coastguard Worker // Constructor example:
7904*795d594fSAndroid Build Coastguard Worker //
7905*795d594fSAndroid Build Coastguard Worker //     class HasFinal {
7906*795d594fSAndroid Build Coastguard Worker //        final int field;                              Optimizing IR for <init>()V:
7907*795d594fSAndroid Build Coastguard Worker //        HasFinal() {
7908*795d594fSAndroid Build Coastguard Worker //          field = 123;                                HInstanceFieldSet(this, HasFinal.field, 123)
7909*795d594fSAndroid Build Coastguard Worker //          // freeze(this.field);                      HConstructorFence(this)
7910*795d594fSAndroid Build Coastguard Worker //        }                                             HReturn
7911*795d594fSAndroid Build Coastguard Worker //     }
7912*795d594fSAndroid Build Coastguard Worker //
7913*795d594fSAndroid Build Coastguard Worker // HConstructorFence can serve double duty as a fence for new-instance/new-array allocations of
7914*795d594fSAndroid Build Coastguard Worker // already-initialized classes; in that case the allocation must act as a "default-initializer"
7915*795d594fSAndroid Build Coastguard Worker // of the object which effectively writes the class pointer "final field".
7916*795d594fSAndroid Build Coastguard Worker //
7917*795d594fSAndroid Build Coastguard Worker // For example, we can model default-initialiation as roughly the equivalent of the following:
7918*795d594fSAndroid Build Coastguard Worker //
7919*795d594fSAndroid Build Coastguard Worker //     class Object {
7920*795d594fSAndroid Build Coastguard Worker //       private final Class header;
7921*795d594fSAndroid Build Coastguard Worker //     }
7922*795d594fSAndroid Build Coastguard Worker //
7923*795d594fSAndroid Build Coastguard Worker //  Java code:                                           Optimizing IR:
7924*795d594fSAndroid Build Coastguard Worker //
7925*795d594fSAndroid Build Coastguard Worker //     T new_instance<T>() {
7926*795d594fSAndroid Build Coastguard Worker //       Object obj = allocate_memory(T.class.size);     obj = HInvoke(art_quick_alloc_object, T)
7927*795d594fSAndroid Build Coastguard Worker //       obj.header = T.class;                           // header write is done by above call.
7928*795d594fSAndroid Build Coastguard Worker //       // freeze(obj.header)                           HConstructorFence(obj)
7929*795d594fSAndroid Build Coastguard Worker //       return (T)obj;
7930*795d594fSAndroid Build Coastguard Worker //     }
7931*795d594fSAndroid Build Coastguard Worker //
7932*795d594fSAndroid Build Coastguard Worker // See also:
7933*795d594fSAndroid Build Coastguard Worker // * DexCompilationUnit::RequiresConstructorBarrier
7934*795d594fSAndroid Build Coastguard Worker // * QuasiAtomic::ThreadFenceForConstructor
7935*795d594fSAndroid Build Coastguard Worker //
7936*795d594fSAndroid Build Coastguard Worker class HConstructorFence final : public HVariableInputSizeInstruction {
7937*795d594fSAndroid Build Coastguard Worker                                   // A fence has variable inputs because the inputs can be removed
7938*795d594fSAndroid Build Coastguard Worker                                   // after prepare_for_register_allocation phase.
7939*795d594fSAndroid Build Coastguard Worker                                   // (TODO: In the future a fence could freeze multiple objects
7940*795d594fSAndroid Build Coastguard Worker                                   //        after merging two fences together.)
7941*795d594fSAndroid Build Coastguard Worker  public:
7942*795d594fSAndroid Build Coastguard Worker   // `fence_object` is the reference that needs to be protected for correct publication.
7943*795d594fSAndroid Build Coastguard Worker   //
7944*795d594fSAndroid Build Coastguard Worker   // It makes sense in the following situations:
7945*795d594fSAndroid Build Coastguard Worker   // * <init> constructors, it's the "this" parameter (i.e. HParameterValue, s.t. IsThis() == true).
7946*795d594fSAndroid Build Coastguard Worker   // * new-instance-like instructions, it's the return value (i.e. HNewInstance).
7947*795d594fSAndroid Build Coastguard Worker   //
7948*795d594fSAndroid Build Coastguard Worker   // After construction the `fence_object` becomes the 0th input.
7949*795d594fSAndroid Build Coastguard Worker   // This is not an input in a real sense, but just a convenient place to stash the information
7950*795d594fSAndroid Build Coastguard Worker   // about the associated object.
7951*795d594fSAndroid Build Coastguard Worker   HConstructorFence(HInstruction* fence_object,
7952*795d594fSAndroid Build Coastguard Worker                     uint32_t dex_pc,
7953*795d594fSAndroid Build Coastguard Worker                     ArenaAllocator* allocator)
7954*795d594fSAndroid Build Coastguard Worker     // We strongly suspect there is not a more accurate way to describe the fine-grained reordering
7955*795d594fSAndroid Build Coastguard Worker     // constraints described in the class header. We claim that these SideEffects constraints
7956*795d594fSAndroid Build Coastguard Worker     // enforce a superset of the real constraints.
7957*795d594fSAndroid Build Coastguard Worker     //
7958*795d594fSAndroid Build Coastguard Worker     // The ordering described above is conservatively modeled with SideEffects as follows:
7959*795d594fSAndroid Build Coastguard Worker     //
7960*795d594fSAndroid Build Coastguard Worker     // * To prevent reordering of the publication stores:
7961*795d594fSAndroid Build Coastguard Worker     // ----> "Reads of objects" is the initial SideEffect.
7962*795d594fSAndroid Build Coastguard Worker     // * For every primitive final field store in the constructor:
7963*795d594fSAndroid Build Coastguard Worker     // ----> Union that field's type as a read (e.g. "Read of T") into the SideEffect.
7964*795d594fSAndroid Build Coastguard Worker     // * If there are any stores to reference final fields in the constructor:
7965*795d594fSAndroid Build Coastguard Worker     // ----> Use a more conservative "AllReads" SideEffect because any stores to any references
7966*795d594fSAndroid Build Coastguard Worker     //       that are reachable from `fence_object` also need to be prevented for reordering
7967*795d594fSAndroid Build Coastguard Worker     //       (and we do not want to do alias analysis to figure out what those stores are).
7968*795d594fSAndroid Build Coastguard Worker     //
7969*795d594fSAndroid Build Coastguard Worker     // In the implementation, this initially starts out as an "all reads" side effect; this is an
7970*795d594fSAndroid Build Coastguard Worker     // even more conservative approach than the one described above, and prevents all of the
7971*795d594fSAndroid Build Coastguard Worker     // above reordering without analyzing any of the instructions in the constructor.
7972*795d594fSAndroid Build Coastguard Worker     //
7973*795d594fSAndroid Build Coastguard Worker     // If in a later phase we discover that there are no writes to reference final fields,
7974*795d594fSAndroid Build Coastguard Worker     // we can refine the side effect to a smaller set of type reads (see above constraints).
7975*795d594fSAndroid Build Coastguard Worker       : HVariableInputSizeInstruction(kConstructorFence,
7976*795d594fSAndroid Build Coastguard Worker                                       SideEffects::AllReads(),
7977*795d594fSAndroid Build Coastguard Worker                                       dex_pc,
7978*795d594fSAndroid Build Coastguard Worker                                       allocator,
7979*795d594fSAndroid Build Coastguard Worker                                       /* number_of_inputs= */ 1,
7980*795d594fSAndroid Build Coastguard Worker                                       kArenaAllocConstructorFenceInputs) {
7981*795d594fSAndroid Build Coastguard Worker     DCHECK(fence_object != nullptr);
7982*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, fence_object);
7983*795d594fSAndroid Build Coastguard Worker   }
7984*795d594fSAndroid Build Coastguard Worker 
7985*795d594fSAndroid Build Coastguard Worker   // The object associated with this constructor fence.
7986*795d594fSAndroid Build Coastguard Worker   //
7987*795d594fSAndroid Build Coastguard Worker   // (Note: This will be null after the prepare_for_register_allocation phase,
7988*795d594fSAndroid Build Coastguard Worker   // as all constructor fence inputs are removed there).
7989*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFenceObject() const {
7990*795d594fSAndroid Build Coastguard Worker     return InputAt(0);
7991*795d594fSAndroid Build Coastguard Worker   }
7992*795d594fSAndroid Build Coastguard Worker 
7993*795d594fSAndroid Build Coastguard Worker   // Find all the HConstructorFence uses (`fence_use`) for `this` and:
7994*795d594fSAndroid Build Coastguard Worker   // - Delete `fence_use` from `this`'s use list.
7995*795d594fSAndroid Build Coastguard Worker   // - Delete `this` from `fence_use`'s inputs list.
7996*795d594fSAndroid Build Coastguard Worker   // - If the `fence_use` is dead, remove it from the graph.
7997*795d594fSAndroid Build Coastguard Worker   //
7998*795d594fSAndroid Build Coastguard Worker   // A fence is considered dead once it no longer has any uses
7999*795d594fSAndroid Build Coastguard Worker   // and all of the inputs are dead.
8000*795d594fSAndroid Build Coastguard Worker   //
8001*795d594fSAndroid Build Coastguard Worker   // This must *not* be called during/after prepare_for_register_allocation,
8002*795d594fSAndroid Build Coastguard Worker   // because that removes all the inputs to the fences but the fence is actually
8003*795d594fSAndroid Build Coastguard Worker   // still considered live.
8004*795d594fSAndroid Build Coastguard Worker   //
8005*795d594fSAndroid Build Coastguard Worker   // Returns how many HConstructorFence instructions were removed from graph.
8006*795d594fSAndroid Build Coastguard Worker   static size_t RemoveConstructorFences(HInstruction* instruction);
8007*795d594fSAndroid Build Coastguard Worker 
8008*795d594fSAndroid Build Coastguard Worker   // Combine all inputs of `this` and `other` instruction and remove
8009*795d594fSAndroid Build Coastguard Worker   // `other` from the graph.
8010*795d594fSAndroid Build Coastguard Worker   //
8011*795d594fSAndroid Build Coastguard Worker   // Inputs are unique after the merge.
8012*795d594fSAndroid Build Coastguard Worker   //
8013*795d594fSAndroid Build Coastguard Worker   // Requirement: `this` must not be the same as `other.
8014*795d594fSAndroid Build Coastguard Worker   void Merge(HConstructorFence* other);
8015*795d594fSAndroid Build Coastguard Worker 
8016*795d594fSAndroid Build Coastguard Worker   // Check if this constructor fence is protecting
8017*795d594fSAndroid Build Coastguard Worker   // an HNewInstance or HNewArray that is also the immediate
8018*795d594fSAndroid Build Coastguard Worker   // predecessor of `this`.
8019*795d594fSAndroid Build Coastguard Worker   //
8020*795d594fSAndroid Build Coastguard Worker   // If `ignore_inputs` is true, then the immediate predecessor doesn't need
8021*795d594fSAndroid Build Coastguard Worker   // to be one of the inputs of `this`.
8022*795d594fSAndroid Build Coastguard Worker   //
8023*795d594fSAndroid Build Coastguard Worker   // Returns the associated HNewArray or HNewInstance,
8024*795d594fSAndroid Build Coastguard Worker   // or null otherwise.
8025*795d594fSAndroid Build Coastguard Worker   HInstruction* GetAssociatedAllocation(bool ignore_inputs = false);
8026*795d594fSAndroid Build Coastguard Worker 
8027*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ConstructorFence);
8028*795d594fSAndroid Build Coastguard Worker 
8029*795d594fSAndroid Build Coastguard Worker  protected:
8030*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ConstructorFence);
8031*795d594fSAndroid Build Coastguard Worker };
8032*795d594fSAndroid Build Coastguard Worker 
8033*795d594fSAndroid Build Coastguard Worker class HMonitorOperation final : public HExpression<1> {
8034*795d594fSAndroid Build Coastguard Worker  public:
8035*795d594fSAndroid Build Coastguard Worker   enum class OperationKind {
8036*795d594fSAndroid Build Coastguard Worker     kEnter,
8037*795d594fSAndroid Build Coastguard Worker     kExit,
8038*795d594fSAndroid Build Coastguard Worker     kLast = kExit
8039*795d594fSAndroid Build Coastguard Worker   };
8040*795d594fSAndroid Build Coastguard Worker 
8041*795d594fSAndroid Build Coastguard Worker   HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
8042*795d594fSAndroid Build Coastguard Worker     : HExpression(kMonitorOperation,
8043*795d594fSAndroid Build Coastguard Worker                   SideEffects::AllExceptGCDependency(),  // Assume write/read on all fields/arrays.
8044*795d594fSAndroid Build Coastguard Worker                   dex_pc) {
8045*795d594fSAndroid Build Coastguard Worker     SetPackedField<OperationKindField>(kind);
8046*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, object);
8047*795d594fSAndroid Build Coastguard Worker   }
8048*795d594fSAndroid Build Coastguard Worker 
8049*795d594fSAndroid Build Coastguard Worker   // Instruction may go into runtime, so we need an environment.
8050*795d594fSAndroid Build Coastguard Worker   bool NeedsEnvironment() const override { return true; }
8051*795d594fSAndroid Build Coastguard Worker 
8052*795d594fSAndroid Build Coastguard Worker   bool CanThrow() const override {
8053*795d594fSAndroid Build Coastguard Worker     // Verifier guarantees that monitor-exit cannot throw.
8054*795d594fSAndroid Build Coastguard Worker     // This is important because it allows the HGraphBuilder to remove
8055*795d594fSAndroid Build Coastguard Worker     // a dead throw-catch loop generated for `synchronized` blocks/methods.
8056*795d594fSAndroid Build Coastguard Worker     return IsEnter();
8057*795d594fSAndroid Build Coastguard Worker   }
8058*795d594fSAndroid Build Coastguard Worker 
8059*795d594fSAndroid Build Coastguard Worker   OperationKind GetOperationKind() const { return GetPackedField<OperationKindField>(); }
8060*795d594fSAndroid Build Coastguard Worker   bool IsEnter() const { return GetOperationKind() == OperationKind::kEnter; }
8061*795d594fSAndroid Build Coastguard Worker 
8062*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(MonitorOperation);
8063*795d594fSAndroid Build Coastguard Worker 
8064*795d594fSAndroid Build Coastguard Worker  protected:
8065*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(MonitorOperation);
8066*795d594fSAndroid Build Coastguard Worker 
8067*795d594fSAndroid Build Coastguard Worker  private:
8068*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldOperationKind = HInstruction::kNumberOfGenericPackedBits;
8069*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kFieldOperationKindSize =
8070*795d594fSAndroid Build Coastguard Worker       MinimumBitsToStore(static_cast<size_t>(OperationKind::kLast));
8071*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kNumberOfMonitorOperationPackedBits =
8072*795d594fSAndroid Build Coastguard Worker       kFieldOperationKind + kFieldOperationKindSize;
8073*795d594fSAndroid Build Coastguard Worker   static_assert(kNumberOfMonitorOperationPackedBits <= HInstruction::kMaxNumberOfPackedBits,
8074*795d594fSAndroid Build Coastguard Worker                 "Too many packed fields.");
8075*795d594fSAndroid Build Coastguard Worker   using OperationKindField = BitField<OperationKind, kFieldOperationKind, kFieldOperationKindSize>;
8076*795d594fSAndroid Build Coastguard Worker };
8077*795d594fSAndroid Build Coastguard Worker 
8078*795d594fSAndroid Build Coastguard Worker class HSelect final : public HExpression<3> {
8079*795d594fSAndroid Build Coastguard Worker  public:
8080*795d594fSAndroid Build Coastguard Worker   HSelect(HInstruction* condition,
8081*795d594fSAndroid Build Coastguard Worker           HInstruction* true_value,
8082*795d594fSAndroid Build Coastguard Worker           HInstruction* false_value,
8083*795d594fSAndroid Build Coastguard Worker           uint32_t dex_pc)
8084*795d594fSAndroid Build Coastguard Worker       : HExpression(kSelect, HPhi::ToPhiType(true_value->GetType()), SideEffects::None(), dex_pc) {
8085*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(HPhi::ToPhiType(true_value->GetType()), HPhi::ToPhiType(false_value->GetType()));
8086*795d594fSAndroid Build Coastguard Worker 
8087*795d594fSAndroid Build Coastguard Worker     // First input must be `true_value` or `false_value` to allow codegens to
8088*795d594fSAndroid Build Coastguard Worker     // use the SameAsFirstInput allocation policy. We make it `false_value`, so
8089*795d594fSAndroid Build Coastguard Worker     // that architectures which implement HSelect as a conditional move also
8090*795d594fSAndroid Build Coastguard Worker     // will not need to invert the condition.
8091*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, false_value);
8092*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, true_value);
8093*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(2, condition);
8094*795d594fSAndroid Build Coastguard Worker   }
8095*795d594fSAndroid Build Coastguard Worker 
8096*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
8097*795d594fSAndroid Build Coastguard Worker   HInstruction* GetFalseValue() const { return InputAt(0); }
8098*795d594fSAndroid Build Coastguard Worker   HInstruction* GetTrueValue() const { return InputAt(1); }
8099*795d594fSAndroid Build Coastguard Worker   HInstruction* GetCondition() const { return InputAt(2); }
8100*795d594fSAndroid Build Coastguard Worker 
8101*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
8102*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
8103*795d594fSAndroid Build Coastguard Worker     return true;
8104*795d594fSAndroid Build Coastguard Worker   }
8105*795d594fSAndroid Build Coastguard Worker 
8106*795d594fSAndroid Build Coastguard Worker   bool CanBeNull() const override {
8107*795d594fSAndroid Build Coastguard Worker     return GetTrueValue()->CanBeNull() || GetFalseValue()->CanBeNull();
8108*795d594fSAndroid Build Coastguard Worker   }
8109*795d594fSAndroid Build Coastguard Worker 
8110*795d594fSAndroid Build Coastguard Worker   void UpdateType() {
8111*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(HPhi::ToPhiType(GetTrueValue()->GetType()),
8112*795d594fSAndroid Build Coastguard Worker               HPhi::ToPhiType(GetFalseValue()->GetType()));
8113*795d594fSAndroid Build Coastguard Worker     SetPackedField<TypeField>(HPhi::ToPhiType(GetTrueValue()->GetType()));
8114*795d594fSAndroid Build Coastguard Worker   }
8115*795d594fSAndroid Build Coastguard Worker 
8116*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(Select);
8117*795d594fSAndroid Build Coastguard Worker 
8118*795d594fSAndroid Build Coastguard Worker  protected:
8119*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(Select);
8120*795d594fSAndroid Build Coastguard Worker };
8121*795d594fSAndroid Build Coastguard Worker 
8122*795d594fSAndroid Build Coastguard Worker class MoveOperands : public ArenaObject<kArenaAllocMoveOperands> {
8123*795d594fSAndroid Build Coastguard Worker  public:
8124*795d594fSAndroid Build Coastguard Worker   MoveOperands(Location source,
8125*795d594fSAndroid Build Coastguard Worker                Location destination,
8126*795d594fSAndroid Build Coastguard Worker                DataType::Type type,
8127*795d594fSAndroid Build Coastguard Worker                HInstruction* instruction)
8128*795d594fSAndroid Build Coastguard Worker       : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
8129*795d594fSAndroid Build Coastguard Worker 
8130*795d594fSAndroid Build Coastguard Worker   Location GetSource() const { return source_; }
8131*795d594fSAndroid Build Coastguard Worker   Location GetDestination() const { return destination_; }
8132*795d594fSAndroid Build Coastguard Worker 
8133*795d594fSAndroid Build Coastguard Worker   void SetSource(Location value) { source_ = value; }
8134*795d594fSAndroid Build Coastguard Worker   void SetDestination(Location value) { destination_ = value; }
8135*795d594fSAndroid Build Coastguard Worker 
8136*795d594fSAndroid Build Coastguard Worker   // The parallel move resolver marks moves as "in-progress" by clearing the
8137*795d594fSAndroid Build Coastguard Worker   // destination (but not the source).
8138*795d594fSAndroid Build Coastguard Worker   Location MarkPending() {
8139*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsPending());
8140*795d594fSAndroid Build Coastguard Worker     Location dest = destination_;
8141*795d594fSAndroid Build Coastguard Worker     destination_ = Location::NoLocation();
8142*795d594fSAndroid Build Coastguard Worker     return dest;
8143*795d594fSAndroid Build Coastguard Worker   }
8144*795d594fSAndroid Build Coastguard Worker 
8145*795d594fSAndroid Build Coastguard Worker   void ClearPending(Location dest) {
8146*795d594fSAndroid Build Coastguard Worker     DCHECK(IsPending());
8147*795d594fSAndroid Build Coastguard Worker     destination_ = dest;
8148*795d594fSAndroid Build Coastguard Worker   }
8149*795d594fSAndroid Build Coastguard Worker 
8150*795d594fSAndroid Build Coastguard Worker   bool IsPending() const {
8151*795d594fSAndroid Build Coastguard Worker     DCHECK(source_.IsValid() || destination_.IsInvalid());
8152*795d594fSAndroid Build Coastguard Worker     return destination_.IsInvalid() && source_.IsValid();
8153*795d594fSAndroid Build Coastguard Worker   }
8154*795d594fSAndroid Build Coastguard Worker 
8155*795d594fSAndroid Build Coastguard Worker   // True if this blocks a move from the given location.
8156*795d594fSAndroid Build Coastguard Worker   bool Blocks(Location loc) const {
8157*795d594fSAndroid Build Coastguard Worker     return !IsEliminated() && source_.OverlapsWith(loc);
8158*795d594fSAndroid Build Coastguard Worker   }
8159*795d594fSAndroid Build Coastguard Worker 
8160*795d594fSAndroid Build Coastguard Worker   // A move is redundant if it's been eliminated, if its source and
8161*795d594fSAndroid Build Coastguard Worker   // destination are the same, or if its destination is unneeded.
8162*795d594fSAndroid Build Coastguard Worker   bool IsRedundant() const {
8163*795d594fSAndroid Build Coastguard Worker     return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
8164*795d594fSAndroid Build Coastguard Worker   }
8165*795d594fSAndroid Build Coastguard Worker 
8166*795d594fSAndroid Build Coastguard Worker   // We clear both operands to indicate move that's been eliminated.
8167*795d594fSAndroid Build Coastguard Worker   void Eliminate() {
8168*795d594fSAndroid Build Coastguard Worker     source_ = destination_ = Location::NoLocation();
8169*795d594fSAndroid Build Coastguard Worker   }
8170*795d594fSAndroid Build Coastguard Worker 
8171*795d594fSAndroid Build Coastguard Worker   bool IsEliminated() const {
8172*795d594fSAndroid Build Coastguard Worker     DCHECK_IMPLIES(source_.IsInvalid(), destination_.IsInvalid());
8173*795d594fSAndroid Build Coastguard Worker     return source_.IsInvalid();
8174*795d594fSAndroid Build Coastguard Worker   }
8175*795d594fSAndroid Build Coastguard Worker 
8176*795d594fSAndroid Build Coastguard Worker   DataType::Type GetType() const { return type_; }
8177*795d594fSAndroid Build Coastguard Worker 
8178*795d594fSAndroid Build Coastguard Worker   bool Is64BitMove() const {
8179*795d594fSAndroid Build Coastguard Worker     return DataType::Is64BitType(type_);
8180*795d594fSAndroid Build Coastguard Worker   }
8181*795d594fSAndroid Build Coastguard Worker 
8182*795d594fSAndroid Build Coastguard Worker   HInstruction* GetInstruction() const { return instruction_; }
8183*795d594fSAndroid Build Coastguard Worker 
8184*795d594fSAndroid Build Coastguard Worker  private:
8185*795d594fSAndroid Build Coastguard Worker   Location source_;
8186*795d594fSAndroid Build Coastguard Worker   Location destination_;
8187*795d594fSAndroid Build Coastguard Worker   // The type this move is for.
8188*795d594fSAndroid Build Coastguard Worker   DataType::Type type_;
8189*795d594fSAndroid Build Coastguard Worker   // The instruction this move is assocatied with. Null when this move is
8190*795d594fSAndroid Build Coastguard Worker   // for moving an input in the expected locations of user (including a phi user).
8191*795d594fSAndroid Build Coastguard Worker   // This is only used in debug mode, to ensure we do not connect interval siblings
8192*795d594fSAndroid Build Coastguard Worker   // in the same parallel move.
8193*795d594fSAndroid Build Coastguard Worker   HInstruction* instruction_;
8194*795d594fSAndroid Build Coastguard Worker };
8195*795d594fSAndroid Build Coastguard Worker 
8196*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const MoveOperands& rhs);
8197*795d594fSAndroid Build Coastguard Worker 
8198*795d594fSAndroid Build Coastguard Worker static constexpr size_t kDefaultNumberOfMoves = 4;
8199*795d594fSAndroid Build Coastguard Worker 
8200*795d594fSAndroid Build Coastguard Worker class HParallelMove final : public HExpression<0> {
8201*795d594fSAndroid Build Coastguard Worker  public:
8202*795d594fSAndroid Build Coastguard Worker   explicit HParallelMove(ArenaAllocator* allocator, uint32_t dex_pc = kNoDexPc)
8203*795d594fSAndroid Build Coastguard Worker       : HExpression(kParallelMove, SideEffects::None(), dex_pc),
8204*795d594fSAndroid Build Coastguard Worker         moves_(allocator->Adapter(kArenaAllocMoveOperands)) {
8205*795d594fSAndroid Build Coastguard Worker     moves_.reserve(kDefaultNumberOfMoves);
8206*795d594fSAndroid Build Coastguard Worker   }
8207*795d594fSAndroid Build Coastguard Worker 
8208*795d594fSAndroid Build Coastguard Worker   void AddMove(Location source,
8209*795d594fSAndroid Build Coastguard Worker                Location destination,
8210*795d594fSAndroid Build Coastguard Worker                DataType::Type type,
8211*795d594fSAndroid Build Coastguard Worker                HInstruction* instruction) {
8212*795d594fSAndroid Build Coastguard Worker     DCHECK(source.IsValid());
8213*795d594fSAndroid Build Coastguard Worker     DCHECK(destination.IsValid());
8214*795d594fSAndroid Build Coastguard Worker     if (kIsDebugBuild) {
8215*795d594fSAndroid Build Coastguard Worker       if (instruction != nullptr) {
8216*795d594fSAndroid Build Coastguard Worker         for (const MoveOperands& move : moves_) {
8217*795d594fSAndroid Build Coastguard Worker           if (move.GetInstruction() == instruction) {
8218*795d594fSAndroid Build Coastguard Worker             // Special case the situation where the move is for the spill slot
8219*795d594fSAndroid Build Coastguard Worker             // of the instruction.
8220*795d594fSAndroid Build Coastguard Worker             if ((GetPrevious() == instruction)
8221*795d594fSAndroid Build Coastguard Worker                 || ((GetPrevious() == nullptr)
8222*795d594fSAndroid Build Coastguard Worker                     && instruction->IsPhi()
8223*795d594fSAndroid Build Coastguard Worker                     && instruction->GetBlock() == GetBlock())) {
8224*795d594fSAndroid Build Coastguard Worker               DCHECK_NE(destination.GetKind(), move.GetDestination().GetKind())
8225*795d594fSAndroid Build Coastguard Worker                   << "Doing parallel moves for the same instruction.";
8226*795d594fSAndroid Build Coastguard Worker             } else {
8227*795d594fSAndroid Build Coastguard Worker               DCHECK(false) << "Doing parallel moves for the same instruction.";
8228*795d594fSAndroid Build Coastguard Worker             }
8229*795d594fSAndroid Build Coastguard Worker           }
8230*795d594fSAndroid Build Coastguard Worker         }
8231*795d594fSAndroid Build Coastguard Worker       }
8232*795d594fSAndroid Build Coastguard Worker       for (const MoveOperands& move : moves_) {
8233*795d594fSAndroid Build Coastguard Worker         DCHECK(!destination.OverlapsWith(move.GetDestination()))
8234*795d594fSAndroid Build Coastguard Worker             << "Overlapped destination for two moves in a parallel move: "
8235*795d594fSAndroid Build Coastguard Worker             << move.GetSource() << " ==> " << move.GetDestination() << " and "
8236*795d594fSAndroid Build Coastguard Worker             << source << " ==> " << destination << " for " << SafePrint(instruction);
8237*795d594fSAndroid Build Coastguard Worker       }
8238*795d594fSAndroid Build Coastguard Worker     }
8239*795d594fSAndroid Build Coastguard Worker     moves_.emplace_back(source, destination, type, instruction);
8240*795d594fSAndroid Build Coastguard Worker   }
8241*795d594fSAndroid Build Coastguard Worker 
8242*795d594fSAndroid Build Coastguard Worker   MoveOperands* MoveOperandsAt(size_t index) {
8243*795d594fSAndroid Build Coastguard Worker     return &moves_[index];
8244*795d594fSAndroid Build Coastguard Worker   }
8245*795d594fSAndroid Build Coastguard Worker 
8246*795d594fSAndroid Build Coastguard Worker   size_t NumMoves() const { return moves_.size(); }
8247*795d594fSAndroid Build Coastguard Worker 
8248*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(ParallelMove);
8249*795d594fSAndroid Build Coastguard Worker 
8250*795d594fSAndroid Build Coastguard Worker  protected:
8251*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(ParallelMove);
8252*795d594fSAndroid Build Coastguard Worker 
8253*795d594fSAndroid Build Coastguard Worker  private:
8254*795d594fSAndroid Build Coastguard Worker   ArenaVector<MoveOperands> moves_;
8255*795d594fSAndroid Build Coastguard Worker };
8256*795d594fSAndroid Build Coastguard Worker 
8257*795d594fSAndroid Build Coastguard Worker class HBitwiseNegatedRight final : public HBinaryOperation {
8258*795d594fSAndroid Build Coastguard Worker  public:
8259*795d594fSAndroid Build Coastguard Worker   HBitwiseNegatedRight(DataType::Type result_type,
8260*795d594fSAndroid Build Coastguard Worker                        InstructionKind op,
8261*795d594fSAndroid Build Coastguard Worker                        HInstruction* left,
8262*795d594fSAndroid Build Coastguard Worker                        HInstruction* right,
8263*795d594fSAndroid Build Coastguard Worker                        uint32_t dex_pc = kNoDexPc)
8264*795d594fSAndroid Build Coastguard Worker       : HBinaryOperation(
8265*795d594fSAndroid Build Coastguard Worker             kBitwiseNegatedRight, result_type, left, right, SideEffects::None(), dex_pc),
8266*795d594fSAndroid Build Coastguard Worker         op_kind_(op) {
8267*795d594fSAndroid Build Coastguard Worker     DCHECK(op == HInstruction::kAnd || op == HInstruction::kOr || op == HInstruction::kXor) << op;
8268*795d594fSAndroid Build Coastguard Worker   }
8269*795d594fSAndroid Build Coastguard Worker 
8270*795d594fSAndroid Build Coastguard Worker   template <typename T, typename U>
8271*795d594fSAndroid Build Coastguard Worker   auto Compute(T x, U y) const -> decltype(x & ~y) {
8272*795d594fSAndroid Build Coastguard Worker     static_assert(std::is_same<decltype(x & ~y), decltype(x | ~y)>::value &&
8273*795d594fSAndroid Build Coastguard Worker                       std::is_same<decltype(x & ~y), decltype(x ^ ~y)>::value,
8274*795d594fSAndroid Build Coastguard Worker                   "Inconsistent negated bitwise types");
8275*795d594fSAndroid Build Coastguard Worker     switch (op_kind_) {
8276*795d594fSAndroid Build Coastguard Worker       case HInstruction::kAnd:
8277*795d594fSAndroid Build Coastguard Worker         return x & ~y;
8278*795d594fSAndroid Build Coastguard Worker       case HInstruction::kOr:
8279*795d594fSAndroid Build Coastguard Worker         return x | ~y;
8280*795d594fSAndroid Build Coastguard Worker       case HInstruction::kXor:
8281*795d594fSAndroid Build Coastguard Worker         return x ^ ~y;
8282*795d594fSAndroid Build Coastguard Worker       default:
8283*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Unreachable";
8284*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
8285*795d594fSAndroid Build Coastguard Worker     }
8286*795d594fSAndroid Build Coastguard Worker   }
8287*795d594fSAndroid Build Coastguard Worker 
8288*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals(const HInstruction* other) const override {
8289*795d594fSAndroid Build Coastguard Worker     return op_kind_ == other->AsBitwiseNegatedRight()->op_kind_;
8290*795d594fSAndroid Build Coastguard Worker   }
8291*795d594fSAndroid Build Coastguard Worker 
8292*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const override {
8293*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
8294*795d594fSAndroid Build Coastguard Worker   }
8295*795d594fSAndroid Build Coastguard Worker 
8296*795d594fSAndroid Build Coastguard Worker   HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const override {
8297*795d594fSAndroid Build Coastguard Worker     return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
8298*795d594fSAndroid Build Coastguard Worker   }
8299*795d594fSAndroid Build Coastguard Worker 
8300*795d594fSAndroid Build Coastguard Worker   InstructionKind GetOpKind() const { return op_kind_; }
8301*795d594fSAndroid Build Coastguard Worker 
8302*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(BitwiseNegatedRight);
8303*795d594fSAndroid Build Coastguard Worker 
8304*795d594fSAndroid Build Coastguard Worker  protected:
8305*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(BitwiseNegatedRight);
8306*795d594fSAndroid Build Coastguard Worker 
8307*795d594fSAndroid Build Coastguard Worker  private:
8308*795d594fSAndroid Build Coastguard Worker   // Specifies the bitwise operation, which will be then negated.
8309*795d594fSAndroid Build Coastguard Worker   const InstructionKind op_kind_;
8310*795d594fSAndroid Build Coastguard Worker };
8311*795d594fSAndroid Build Coastguard Worker 
8312*795d594fSAndroid Build Coastguard Worker // This instruction computes an intermediate address pointing in the 'middle' of an object. The
8313*795d594fSAndroid Build Coastguard Worker // result pointer cannot be handled by GC, so extra care is taken to make sure that this value is
8314*795d594fSAndroid Build Coastguard Worker // never used across anything that can trigger GC.
8315*795d594fSAndroid Build Coastguard Worker // The result of this instruction is not a pointer in the sense of `DataType::Type::kreference`.
8316*795d594fSAndroid Build Coastguard Worker // So we represent it by the type `DataType::Type::kInt`.
8317*795d594fSAndroid Build Coastguard Worker class HIntermediateAddress final : public HExpression<2> {
8318*795d594fSAndroid Build Coastguard Worker  public:
8319*795d594fSAndroid Build Coastguard Worker   HIntermediateAddress(HInstruction* base_address, HInstruction* offset, uint32_t dex_pc)
8320*795d594fSAndroid Build Coastguard Worker       : HExpression(kIntermediateAddress,
8321*795d594fSAndroid Build Coastguard Worker                     DataType::Type::kInt32,
8322*795d594fSAndroid Build Coastguard Worker                     SideEffects::DependsOnGC(),
8323*795d594fSAndroid Build Coastguard Worker                     dex_pc) {
8324*795d594fSAndroid Build Coastguard Worker         DCHECK_EQ(DataType::Size(DataType::Type::kInt32),
8325*795d594fSAndroid Build Coastguard Worker                   DataType::Size(DataType::Type::kReference))
8326*795d594fSAndroid Build Coastguard Worker             << "kPrimInt and kPrimNot have different sizes.";
8327*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(0, base_address);
8328*795d594fSAndroid Build Coastguard Worker     SetRawInputAt(1, offset);
8329*795d594fSAndroid Build Coastguard Worker   }
8330*795d594fSAndroid Build Coastguard Worker 
8331*795d594fSAndroid Build Coastguard Worker   bool IsClonable() const override { return true; }
8332*795d594fSAndroid Build Coastguard Worker   bool CanBeMoved() const override { return true; }
8333*795d594fSAndroid Build Coastguard Worker   bool InstructionDataEquals([[maybe_unused]] const HInstruction* other) const override {
8334*795d594fSAndroid Build Coastguard Worker     return true;
8335*795d594fSAndroid Build Coastguard Worker   }
8336*795d594fSAndroid Build Coastguard Worker   bool IsActualObject() const override { return false; }
8337*795d594fSAndroid Build Coastguard Worker 
8338*795d594fSAndroid Build Coastguard Worker   HInstruction* GetBaseAddress() const { return InputAt(0); }
8339*795d594fSAndroid Build Coastguard Worker   HInstruction* GetOffset() const { return InputAt(1); }
8340*795d594fSAndroid Build Coastguard Worker 
8341*795d594fSAndroid Build Coastguard Worker   DECLARE_INSTRUCTION(IntermediateAddress);
8342*795d594fSAndroid Build Coastguard Worker 
8343*795d594fSAndroid Build Coastguard Worker  protected:
8344*795d594fSAndroid Build Coastguard Worker   DEFAULT_COPY_CONSTRUCTOR(IntermediateAddress);
8345*795d594fSAndroid Build Coastguard Worker };
8346*795d594fSAndroid Build Coastguard Worker 
8347*795d594fSAndroid Build Coastguard Worker 
8348*795d594fSAndroid Build Coastguard Worker }  // namespace art
8349*795d594fSAndroid Build Coastguard Worker 
8350*795d594fSAndroid Build Coastguard Worker #include "nodes_vector.h"
8351*795d594fSAndroid Build Coastguard Worker 
8352*795d594fSAndroid Build Coastguard Worker #if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64)
8353*795d594fSAndroid Build Coastguard Worker #include "nodes_shared.h"
8354*795d594fSAndroid Build Coastguard Worker #endif
8355*795d594fSAndroid Build Coastguard Worker #if defined(ART_ENABLE_CODEGEN_x86) || defined(ART_ENABLE_CODEGEN_x86_64)
8356*795d594fSAndroid Build Coastguard Worker #include "nodes_x86.h"
8357*795d594fSAndroid Build Coastguard Worker #endif
8358*795d594fSAndroid Build Coastguard Worker #if defined(ART_ENABLE_CODEGEN_riscv64)
8359*795d594fSAndroid Build Coastguard Worker #include "nodes_riscv64.h"
8360*795d594fSAndroid Build Coastguard Worker #endif
8361*795d594fSAndroid Build Coastguard Worker 
8362*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
8363*795d594fSAndroid Build Coastguard Worker 
8364*795d594fSAndroid Build Coastguard Worker class OptimizingCompilerStats;
8365*795d594fSAndroid Build Coastguard Worker 
8366*795d594fSAndroid Build Coastguard Worker class HGraphVisitor : public ValueObject {
8367*795d594fSAndroid Build Coastguard Worker  public:
8368*795d594fSAndroid Build Coastguard Worker   explicit HGraphVisitor(HGraph* graph, OptimizingCompilerStats* stats = nullptr)
8369*795d594fSAndroid Build Coastguard Worker       : stats_(stats),
8370*795d594fSAndroid Build Coastguard Worker         graph_(graph) {}
8371*795d594fSAndroid Build Coastguard Worker   virtual ~HGraphVisitor() {}
8372*795d594fSAndroid Build Coastguard Worker 
8373*795d594fSAndroid Build Coastguard Worker   virtual void VisitInstruction([[maybe_unused]] HInstruction* instruction) {}
8374*795d594fSAndroid Build Coastguard Worker   virtual void VisitBasicBlock(HBasicBlock* block);
8375*795d594fSAndroid Build Coastguard Worker 
8376*795d594fSAndroid Build Coastguard Worker   // Visit the graph following basic block insertion order.
8377*795d594fSAndroid Build Coastguard Worker   void VisitInsertionOrder();
8378*795d594fSAndroid Build Coastguard Worker 
8379*795d594fSAndroid Build Coastguard Worker   // Visit the graph following dominator tree reverse post-order.
8380*795d594fSAndroid Build Coastguard Worker   void VisitReversePostOrder();
8381*795d594fSAndroid Build Coastguard Worker 
8382*795d594fSAndroid Build Coastguard Worker   HGraph* GetGraph() const { return graph_; }
8383*795d594fSAndroid Build Coastguard Worker 
8384*795d594fSAndroid Build Coastguard Worker   // Visit functions for instruction classes.
8385*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
8386*795d594fSAndroid Build Coastguard Worker   virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
8387*795d594fSAndroid Build Coastguard Worker 
8388*795d594fSAndroid Build Coastguard Worker   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
8389*795d594fSAndroid Build Coastguard Worker 
8390*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
8391*795d594fSAndroid Build Coastguard Worker 
8392*795d594fSAndroid Build Coastguard Worker  protected:
8393*795d594fSAndroid Build Coastguard Worker   void VisitPhis(HBasicBlock* block);
8394*795d594fSAndroid Build Coastguard Worker   void VisitNonPhiInstructions(HBasicBlock* block);
8395*795d594fSAndroid Build Coastguard Worker 
8396*795d594fSAndroid Build Coastguard Worker   OptimizingCompilerStats* stats_;
8397*795d594fSAndroid Build Coastguard Worker 
8398*795d594fSAndroid Build Coastguard Worker  private:
8399*795d594fSAndroid Build Coastguard Worker   HGraph* const graph_;
8400*795d594fSAndroid Build Coastguard Worker 
8401*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
8402*795d594fSAndroid Build Coastguard Worker };
8403*795d594fSAndroid Build Coastguard Worker 
8404*795d594fSAndroid Build Coastguard Worker class HGraphDelegateVisitor : public HGraphVisitor {
8405*795d594fSAndroid Build Coastguard Worker  public:
8406*795d594fSAndroid Build Coastguard Worker   explicit HGraphDelegateVisitor(HGraph* graph, OptimizingCompilerStats* stats = nullptr)
8407*795d594fSAndroid Build Coastguard Worker       : HGraphVisitor(graph, stats) {}
8408*795d594fSAndroid Build Coastguard Worker   virtual ~HGraphDelegateVisitor() {}
8409*795d594fSAndroid Build Coastguard Worker 
8410*795d594fSAndroid Build Coastguard Worker   // Visit functions that delegate to to super class.
8411*795d594fSAndroid Build Coastguard Worker #define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
8412*795d594fSAndroid Build Coastguard Worker   void Visit##name(H##name* instr) override { Visit##super(instr); }
8413*795d594fSAndroid Build Coastguard Worker 
8414*795d594fSAndroid Build Coastguard Worker   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
8415*795d594fSAndroid Build Coastguard Worker 
8416*795d594fSAndroid Build Coastguard Worker #undef DECLARE_VISIT_INSTRUCTION
8417*795d594fSAndroid Build Coastguard Worker 
8418*795d594fSAndroid Build Coastguard Worker  private:
8419*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
8420*795d594fSAndroid Build Coastguard Worker };
8421*795d594fSAndroid Build Coastguard Worker 
8422*795d594fSAndroid Build Coastguard Worker // Create a clone of the instruction, insert it into the graph; replace the old one with a new
8423*795d594fSAndroid Build Coastguard Worker // and remove the old instruction.
8424*795d594fSAndroid Build Coastguard Worker HInstruction* ReplaceInstrOrPhiByClone(HInstruction* instr);
8425*795d594fSAndroid Build Coastguard Worker 
8426*795d594fSAndroid Build Coastguard Worker // Create a clone for each clonable instructions/phis and replace the original with the clone.
8427*795d594fSAndroid Build Coastguard Worker //
8428*795d594fSAndroid Build Coastguard Worker // Used for testing individual instruction cloner.
8429*795d594fSAndroid Build Coastguard Worker class CloneAndReplaceInstructionVisitor final : public HGraphDelegateVisitor {
8430*795d594fSAndroid Build Coastguard Worker  public:
8431*795d594fSAndroid Build Coastguard Worker   explicit CloneAndReplaceInstructionVisitor(HGraph* graph)
8432*795d594fSAndroid Build Coastguard Worker       : HGraphDelegateVisitor(graph), instr_replaced_by_clones_count_(0) {}
8433*795d594fSAndroid Build Coastguard Worker 
8434*795d594fSAndroid Build Coastguard Worker   void VisitInstruction(HInstruction* instruction) override {
8435*795d594fSAndroid Build Coastguard Worker     if (instruction->IsClonable()) {
8436*795d594fSAndroid Build Coastguard Worker       ReplaceInstrOrPhiByClone(instruction);
8437*795d594fSAndroid Build Coastguard Worker       instr_replaced_by_clones_count_++;
8438*795d594fSAndroid Build Coastguard Worker     }
8439*795d594fSAndroid Build Coastguard Worker   }
8440*795d594fSAndroid Build Coastguard Worker 
8441*795d594fSAndroid Build Coastguard Worker   size_t GetInstrReplacedByClonesCount() const { return instr_replaced_by_clones_count_; }
8442*795d594fSAndroid Build Coastguard Worker 
8443*795d594fSAndroid Build Coastguard Worker  private:
8444*795d594fSAndroid Build Coastguard Worker   size_t instr_replaced_by_clones_count_;
8445*795d594fSAndroid Build Coastguard Worker 
8446*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(CloneAndReplaceInstructionVisitor);
8447*795d594fSAndroid Build Coastguard Worker };
8448*795d594fSAndroid Build Coastguard Worker 
8449*795d594fSAndroid Build Coastguard Worker // Iterator over the blocks that are part of the loop; includes blocks which are part
8450*795d594fSAndroid Build Coastguard Worker // of an inner loop. The order in which the blocks are iterated is on their
8451*795d594fSAndroid Build Coastguard Worker // block id.
8452*795d594fSAndroid Build Coastguard Worker class HBlocksInLoopIterator : public ValueObject {
8453*795d594fSAndroid Build Coastguard Worker  public:
8454*795d594fSAndroid Build Coastguard Worker   explicit HBlocksInLoopIterator(const HLoopInformation& info)
8455*795d594fSAndroid Build Coastguard Worker       : blocks_in_loop_(info.GetBlocks()),
8456*795d594fSAndroid Build Coastguard Worker         blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
8457*795d594fSAndroid Build Coastguard Worker         index_(0) {
8458*795d594fSAndroid Build Coastguard Worker     if (!blocks_in_loop_.IsBitSet(index_)) {
8459*795d594fSAndroid Build Coastguard Worker       Advance();
8460*795d594fSAndroid Build Coastguard Worker     }
8461*795d594fSAndroid Build Coastguard Worker   }
8462*795d594fSAndroid Build Coastguard Worker 
8463*795d594fSAndroid Build Coastguard Worker   bool Done() const { return index_ == blocks_.size(); }
8464*795d594fSAndroid Build Coastguard Worker   HBasicBlock* Current() const { return blocks_[index_]; }
8465*795d594fSAndroid Build Coastguard Worker   void Advance() {
8466*795d594fSAndroid Build Coastguard Worker     ++index_;
8467*795d594fSAndroid Build Coastguard Worker     for (size_t e = blocks_.size(); index_ < e; ++index_) {
8468*795d594fSAndroid Build Coastguard Worker       if (blocks_in_loop_.IsBitSet(index_)) {
8469*795d594fSAndroid Build Coastguard Worker         break;
8470*795d594fSAndroid Build Coastguard Worker       }
8471*795d594fSAndroid Build Coastguard Worker     }
8472*795d594fSAndroid Build Coastguard Worker   }
8473*795d594fSAndroid Build Coastguard Worker 
8474*795d594fSAndroid Build Coastguard Worker  private:
8475*795d594fSAndroid Build Coastguard Worker   const BitVector& blocks_in_loop_;
8476*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& blocks_;
8477*795d594fSAndroid Build Coastguard Worker   size_t index_;
8478*795d594fSAndroid Build Coastguard Worker 
8479*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
8480*795d594fSAndroid Build Coastguard Worker };
8481*795d594fSAndroid Build Coastguard Worker 
8482*795d594fSAndroid Build Coastguard Worker // Iterator over the blocks that are part of the loop; includes blocks which are part
8483*795d594fSAndroid Build Coastguard Worker // of an inner loop. The order in which the blocks are iterated is reverse
8484*795d594fSAndroid Build Coastguard Worker // post order.
8485*795d594fSAndroid Build Coastguard Worker class HBlocksInLoopReversePostOrderIterator : public ValueObject {
8486*795d594fSAndroid Build Coastguard Worker  public:
8487*795d594fSAndroid Build Coastguard Worker   explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info)
8488*795d594fSAndroid Build Coastguard Worker       : blocks_in_loop_(info.GetBlocks()),
8489*795d594fSAndroid Build Coastguard Worker         blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
8490*795d594fSAndroid Build Coastguard Worker         index_(0) {
8491*795d594fSAndroid Build Coastguard Worker     if (!blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
8492*795d594fSAndroid Build Coastguard Worker       Advance();
8493*795d594fSAndroid Build Coastguard Worker     }
8494*795d594fSAndroid Build Coastguard Worker   }
8495*795d594fSAndroid Build Coastguard Worker 
8496*795d594fSAndroid Build Coastguard Worker   bool Done() const { return index_ == blocks_.size(); }
8497*795d594fSAndroid Build Coastguard Worker   HBasicBlock* Current() const { return blocks_[index_]; }
8498*795d594fSAndroid Build Coastguard Worker   void Advance() {
8499*795d594fSAndroid Build Coastguard Worker     ++index_;
8500*795d594fSAndroid Build Coastguard Worker     for (size_t e = blocks_.size(); index_ < e; ++index_) {
8501*795d594fSAndroid Build Coastguard Worker       if (blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
8502*795d594fSAndroid Build Coastguard Worker         break;
8503*795d594fSAndroid Build Coastguard Worker       }
8504*795d594fSAndroid Build Coastguard Worker     }
8505*795d594fSAndroid Build Coastguard Worker   }
8506*795d594fSAndroid Build Coastguard Worker 
8507*795d594fSAndroid Build Coastguard Worker  private:
8508*795d594fSAndroid Build Coastguard Worker   const BitVector& blocks_in_loop_;
8509*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& blocks_;
8510*795d594fSAndroid Build Coastguard Worker   size_t index_;
8511*795d594fSAndroid Build Coastguard Worker 
8512*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
8513*795d594fSAndroid Build Coastguard Worker };
8514*795d594fSAndroid Build Coastguard Worker 
8515*795d594fSAndroid Build Coastguard Worker // Iterator over the blocks that are part of the loop; includes blocks which are part
8516*795d594fSAndroid Build Coastguard Worker // of an inner loop. The order in which the blocks are iterated is post order.
8517*795d594fSAndroid Build Coastguard Worker class HBlocksInLoopPostOrderIterator : public ValueObject {
8518*795d594fSAndroid Build Coastguard Worker  public:
8519*795d594fSAndroid Build Coastguard Worker   explicit HBlocksInLoopPostOrderIterator(const HLoopInformation& info)
8520*795d594fSAndroid Build Coastguard Worker       : blocks_in_loop_(info.GetBlocks()),
8521*795d594fSAndroid Build Coastguard Worker         blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
8522*795d594fSAndroid Build Coastguard Worker         index_(blocks_.size() - 1) {
8523*795d594fSAndroid Build Coastguard Worker     if (!blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
8524*795d594fSAndroid Build Coastguard Worker       Advance();
8525*795d594fSAndroid Build Coastguard Worker     }
8526*795d594fSAndroid Build Coastguard Worker   }
8527*795d594fSAndroid Build Coastguard Worker 
8528*795d594fSAndroid Build Coastguard Worker   bool Done() const { return index_ < 0; }
8529*795d594fSAndroid Build Coastguard Worker   HBasicBlock* Current() const { return blocks_[index_]; }
8530*795d594fSAndroid Build Coastguard Worker   void Advance() {
8531*795d594fSAndroid Build Coastguard Worker     --index_;
8532*795d594fSAndroid Build Coastguard Worker     for (; index_ >= 0; --index_) {
8533*795d594fSAndroid Build Coastguard Worker       if (blocks_in_loop_.IsBitSet(blocks_[index_]->GetBlockId())) {
8534*795d594fSAndroid Build Coastguard Worker         break;
8535*795d594fSAndroid Build Coastguard Worker       }
8536*795d594fSAndroid Build Coastguard Worker     }
8537*795d594fSAndroid Build Coastguard Worker   }
8538*795d594fSAndroid Build Coastguard Worker 
8539*795d594fSAndroid Build Coastguard Worker  private:
8540*795d594fSAndroid Build Coastguard Worker   const BitVector& blocks_in_loop_;
8541*795d594fSAndroid Build Coastguard Worker   const ArenaVector<HBasicBlock*>& blocks_;
8542*795d594fSAndroid Build Coastguard Worker 
8543*795d594fSAndroid Build Coastguard Worker   int32_t index_;
8544*795d594fSAndroid Build Coastguard Worker 
8545*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopPostOrderIterator);
8546*795d594fSAndroid Build Coastguard Worker };
8547*795d594fSAndroid Build Coastguard Worker 
8548*795d594fSAndroid Build Coastguard Worker // Returns int64_t value of a properly typed constant.
8549*795d594fSAndroid Build Coastguard Worker inline int64_t Int64FromConstant(HConstant* constant) {
8550*795d594fSAndroid Build Coastguard Worker   if (constant->IsIntConstant()) {
8551*795d594fSAndroid Build Coastguard Worker     return constant->AsIntConstant()->GetValue();
8552*795d594fSAndroid Build Coastguard Worker   } else if (constant->IsLongConstant()) {
8553*795d594fSAndroid Build Coastguard Worker     return constant->AsLongConstant()->GetValue();
8554*795d594fSAndroid Build Coastguard Worker   } else {
8555*795d594fSAndroid Build Coastguard Worker     DCHECK(constant->IsNullConstant()) << constant->DebugName();
8556*795d594fSAndroid Build Coastguard Worker     return 0;
8557*795d594fSAndroid Build Coastguard Worker   }
8558*795d594fSAndroid Build Coastguard Worker }
8559*795d594fSAndroid Build Coastguard Worker 
8560*795d594fSAndroid Build Coastguard Worker // Returns true iff instruction is an integral constant (and sets value on success).
8561*795d594fSAndroid Build Coastguard Worker inline bool IsInt64AndGet(HInstruction* instruction, /*out*/ int64_t* value) {
8562*795d594fSAndroid Build Coastguard Worker   if (instruction->IsIntConstant()) {
8563*795d594fSAndroid Build Coastguard Worker     *value = instruction->AsIntConstant()->GetValue();
8564*795d594fSAndroid Build Coastguard Worker     return true;
8565*795d594fSAndroid Build Coastguard Worker   } else if (instruction->IsLongConstant()) {
8566*795d594fSAndroid Build Coastguard Worker     *value = instruction->AsLongConstant()->GetValue();
8567*795d594fSAndroid Build Coastguard Worker     return true;
8568*795d594fSAndroid Build Coastguard Worker   } else if (instruction->IsNullConstant()) {
8569*795d594fSAndroid Build Coastguard Worker     *value = 0;
8570*795d594fSAndroid Build Coastguard Worker     return true;
8571*795d594fSAndroid Build Coastguard Worker   }
8572*795d594fSAndroid Build Coastguard Worker   return false;
8573*795d594fSAndroid Build Coastguard Worker }
8574*795d594fSAndroid Build Coastguard Worker 
8575*795d594fSAndroid Build Coastguard Worker // Returns true iff instruction is the given integral constant.
8576*795d594fSAndroid Build Coastguard Worker inline bool IsInt64Value(HInstruction* instruction, int64_t value) {
8577*795d594fSAndroid Build Coastguard Worker   int64_t val = 0;
8578*795d594fSAndroid Build Coastguard Worker   return IsInt64AndGet(instruction, &val) && val == value;
8579*795d594fSAndroid Build Coastguard Worker }
8580*795d594fSAndroid Build Coastguard Worker 
8581*795d594fSAndroid Build Coastguard Worker // Returns true iff instruction is a zero bit pattern.
8582*795d594fSAndroid Build Coastguard Worker inline bool IsZeroBitPattern(HInstruction* instruction) {
8583*795d594fSAndroid Build Coastguard Worker   return instruction->IsConstant() && instruction->AsConstant()->IsZeroBitPattern();
8584*795d594fSAndroid Build Coastguard Worker }
8585*795d594fSAndroid Build Coastguard Worker 
8586*795d594fSAndroid Build Coastguard Worker // Implement HInstruction::Is##type() for concrete instructions.
8587*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CHECK(type, super)                                    \
8588*795d594fSAndroid Build Coastguard Worker   inline bool HInstruction::Is##type() const { return GetKind() == k##type; }
8589*795d594fSAndroid Build Coastguard Worker   FOR_EACH_CONCRETE_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
8590*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CHECK
8591*795d594fSAndroid Build Coastguard Worker 
8592*795d594fSAndroid Build Coastguard Worker // Implement HInstruction::Is##type() for abstract instructions.
8593*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CHECK_RESULT(type, super)                             \
8594*795d594fSAndroid Build Coastguard Worker   std::is_base_of<BaseType, H##type>::value,
8595*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CHECK(type, super)                                    \
8596*795d594fSAndroid Build Coastguard Worker   inline bool HInstruction::Is##type() const {                                 \
8597*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(GetKind(), kLastInstructionKind);                                \
8598*795d594fSAndroid Build Coastguard Worker     using BaseType = H##type;                                                  \
8599*795d594fSAndroid Build Coastguard Worker     static constexpr bool results[] = {                                        \
8600*795d594fSAndroid Build Coastguard Worker         FOR_EACH_CONCRETE_INSTRUCTION(INSTRUCTION_TYPE_CHECK_RESULT)           \
8601*795d594fSAndroid Build Coastguard Worker     };                                                                         \
8602*795d594fSAndroid Build Coastguard Worker     return results[static_cast<size_t>(GetKind())];                            \
8603*795d594fSAndroid Build Coastguard Worker   }
8604*795d594fSAndroid Build Coastguard Worker 
8605*795d594fSAndroid Build Coastguard Worker   FOR_EACH_ABSTRACT_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
8606*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CHECK
8607*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CHECK_RESULT
8608*795d594fSAndroid Build Coastguard Worker 
8609*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_TYPE_CAST(type, super)                                     \
8610*795d594fSAndroid Build Coastguard Worker   inline const H##type* HInstruction::As##type() const {                       \
8611*795d594fSAndroid Build Coastguard Worker     DCHECK(Is##type());                                                        \
8612*795d594fSAndroid Build Coastguard Worker     return down_cast<const H##type*>(this);                                    \
8613*795d594fSAndroid Build Coastguard Worker   }                                                                            \
8614*795d594fSAndroid Build Coastguard Worker   inline H##type* HInstruction::As##type() {                                   \
8615*795d594fSAndroid Build Coastguard Worker     DCHECK(Is##type());                                                        \
8616*795d594fSAndroid Build Coastguard Worker     return down_cast<H##type*>(this);                                          \
8617*795d594fSAndroid Build Coastguard Worker   }                                                                            \
8618*795d594fSAndroid Build Coastguard Worker   inline const H##type* HInstruction::As##type##OrNull() const {               \
8619*795d594fSAndroid Build Coastguard Worker     return Is##type() ? down_cast<const H##type*>(this) : nullptr;             \
8620*795d594fSAndroid Build Coastguard Worker   }                                                                            \
8621*795d594fSAndroid Build Coastguard Worker   inline H##type* HInstruction::As##type##OrNull() {                           \
8622*795d594fSAndroid Build Coastguard Worker     return Is##type() ? down_cast<H##type*>(this) : nullptr;                   \
8623*795d594fSAndroid Build Coastguard Worker   }
8624*795d594fSAndroid Build Coastguard Worker 
8625*795d594fSAndroid Build Coastguard Worker   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CAST)
8626*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_TYPE_CAST
8627*795d594fSAndroid Build Coastguard Worker 
8628*795d594fSAndroid Build Coastguard Worker 
8629*795d594fSAndroid Build Coastguard Worker // Create space in `blocks` for adding `number_of_new_blocks` entries
8630*795d594fSAndroid Build Coastguard Worker // starting at location `at`. Blocks after `at` are moved accordingly.
8631*795d594fSAndroid Build Coastguard Worker inline void MakeRoomFor(ArenaVector<HBasicBlock*>* blocks,
8632*795d594fSAndroid Build Coastguard Worker                         size_t number_of_new_blocks,
8633*795d594fSAndroid Build Coastguard Worker                         size_t after) {
8634*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(after, blocks->size());
8635*795d594fSAndroid Build Coastguard Worker   size_t old_size = blocks->size();
8636*795d594fSAndroid Build Coastguard Worker   size_t new_size = old_size + number_of_new_blocks;
8637*795d594fSAndroid Build Coastguard Worker   blocks->resize(new_size);
8638*795d594fSAndroid Build Coastguard Worker   std::copy_backward(blocks->begin() + after + 1u, blocks->begin() + old_size, blocks->end());
8639*795d594fSAndroid Build Coastguard Worker }
8640*795d594fSAndroid Build Coastguard Worker 
8641*795d594fSAndroid Build Coastguard Worker /*
8642*795d594fSAndroid Build Coastguard Worker  * Hunt "under the hood" of array lengths (leading to array references),
8643*795d594fSAndroid Build Coastguard Worker  * null checks (also leading to array references), and new arrays
8644*795d594fSAndroid Build Coastguard Worker  * (leading to the actual length). This makes it more likely related
8645*795d594fSAndroid Build Coastguard Worker  * instructions become actually comparable.
8646*795d594fSAndroid Build Coastguard Worker  */
8647*795d594fSAndroid Build Coastguard Worker inline HInstruction* HuntForDeclaration(HInstruction* instruction) {
8648*795d594fSAndroid Build Coastguard Worker   while (instruction->IsArrayLength() ||
8649*795d594fSAndroid Build Coastguard Worker          instruction->IsNullCheck() ||
8650*795d594fSAndroid Build Coastguard Worker          instruction->IsNewArray()) {
8651*795d594fSAndroid Build Coastguard Worker     instruction = instruction->IsNewArray()
8652*795d594fSAndroid Build Coastguard Worker         ? instruction->AsNewArray()->GetLength()
8653*795d594fSAndroid Build Coastguard Worker         : instruction->InputAt(0);
8654*795d594fSAndroid Build Coastguard Worker   }
8655*795d594fSAndroid Build Coastguard Worker   return instruction;
8656*795d594fSAndroid Build Coastguard Worker }
8657*795d594fSAndroid Build Coastguard Worker 
8658*795d594fSAndroid Build Coastguard Worker inline bool IsAddOrSub(const HInstruction* instruction) {
8659*795d594fSAndroid Build Coastguard Worker   return instruction->IsAdd() || instruction->IsSub();
8660*795d594fSAndroid Build Coastguard Worker }
8661*795d594fSAndroid Build Coastguard Worker 
8662*795d594fSAndroid Build Coastguard Worker void RemoveEnvironmentUses(HInstruction* instruction);
8663*795d594fSAndroid Build Coastguard Worker bool HasEnvironmentUsedByOthers(HInstruction* instruction);
8664*795d594fSAndroid Build Coastguard Worker void ResetEnvironmentInputRecords(HInstruction* instruction);
8665*795d594fSAndroid Build Coastguard Worker 
8666*795d594fSAndroid Build Coastguard Worker // Detects an instruction that is >= 0. As long as the value is carried by
8667*795d594fSAndroid Build Coastguard Worker // a single instruction, arithmetic wrap-around cannot occur.
8668*795d594fSAndroid Build Coastguard Worker bool IsGEZero(HInstruction* instruction);
8669*795d594fSAndroid Build Coastguard Worker 
8670*795d594fSAndroid Build Coastguard Worker }  // namespace art
8671*795d594fSAndroid Build Coastguard Worker 
8672*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_OPTIMIZING_NODES_H_
8673