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