blob: 59255d14c33c192a7fb88847c05cf16404a7349e [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_NODES_H_
18#define ART_COMPILER_OPTIMIZING_NODES_H_
19
David Brazdil8d5b8b22015-03-24 10:51:52 +000020#include "base/arena_containers.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080021#include "base/arena_object.h"
Calin Juravle27df7582015-04-17 19:12:31 +010022#include "dex/compiler_enums.h"
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +000023#include "entrypoints/quick/quick_entrypoints_enum.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000024#include "handle.h"
25#include "handle_scope.h"
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000026#include "invoke_type.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010027#include "locations.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000028#include "mirror/class.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010029#include "offsets.h"
Ian Rogerse63db272014-07-15 15:36:11 -070030#include "primitive.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000031#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000032#include "utils/growable_array.h"
33
34namespace art {
35
David Brazdil1abb4192015-02-17 18:33:36 +000036class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000037class HBasicBlock;
Nicolas Geoffray76b1e172015-05-27 17:18:33 +010038class HCurrentMethod;
David Brazdil8d5b8b22015-03-24 10:51:52 +000039class HDoubleConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010040class HEnvironment;
David Brazdil8d5b8b22015-03-24 10:51:52 +000041class HFloatConstant;
David Brazdilfc6a86a2015-06-26 10:33:45 +000042class HGraphBuilder;
David Brazdil8d5b8b22015-03-24 10:51:52 +000043class HGraphVisitor;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000044class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000045class HIntConstant;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000046class HInvoke;
David Brazdil8d5b8b22015-03-24 10:51:52 +000047class HLongConstant;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +000048class HNullConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010049class HPhi;
Nicolas Geoffray3c049742014-09-24 18:10:46 +010050class HSuspendCheck;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010051class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000052class LocationSummary;
Nicolas Geoffraydb216f42015-05-05 17:02:20 +010053class SlowPathCode;
David Brazdil8d5b8b22015-03-24 10:51:52 +000054class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000055
56static const int kDefaultNumberOfBlocks = 8;
57static const int kDefaultNumberOfSuccessors = 2;
58static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010059static const int kDefaultNumberOfDominatedBlocks = 1;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000060static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000061
Calin Juravle9aec02f2014-11-18 23:06:35 +000062static constexpr uint32_t kMaxIntShiftValue = 0x1f;
63static constexpr uint64_t kMaxLongShiftValue = 0x3f;
64
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010065static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
66
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +010067static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
68
Dave Allison20dfc792014-06-16 20:44:29 -070069enum IfCondition {
70 kCondEQ,
71 kCondNE,
72 kCondLT,
73 kCondLE,
74 kCondGT,
75 kCondGE,
76};
77
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010078class HInstructionList {
79 public:
80 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
81
82 void AddInstruction(HInstruction* instruction);
83 void RemoveInstruction(HInstruction* instruction);
84
David Brazdilc3d743f2015-04-22 13:40:50 +010085 // Insert `instruction` before/after an existing instruction `cursor`.
86 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
87 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
88
Roland Levillain6b469232014-09-25 10:10:38 +010089 // Return true if this list contains `instruction`.
90 bool Contains(HInstruction* instruction) const;
91
Roland Levillainccc07a92014-09-16 14:48:16 +010092 // Return true if `instruction1` is found before `instruction2` in
93 // this instruction list and false otherwise. Abort if none
94 // of these instructions is found.
95 bool FoundBefore(const HInstruction* instruction1,
96 const HInstruction* instruction2) const;
97
Nicolas Geoffray276d9da2015-02-02 18:24:11 +000098 bool IsEmpty() const { return first_instruction_ == nullptr; }
99 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
100
101 // Update the block of all instructions to be `block`.
102 void SetBlockOfInstructions(HBasicBlock* block) const;
103
104 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
105 void Add(const HInstructionList& instruction_list);
106
David Brazdil2d7352b2015-04-20 14:52:42 +0100107 // Return the number of instructions in the list. This is an expensive operation.
108 size_t CountSize() const;
109
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100110 private:
111 HInstruction* first_instruction_;
112 HInstruction* last_instruction_;
113
114 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000115 friend class HGraph;
116 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100117 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100118 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100119
120 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
121};
122
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000123// Control-flow graph of a method. Contains a list of basic blocks.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700124class HGraph : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000125 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100126 HGraph(ArenaAllocator* arena,
127 const DexFile& dex_file,
128 uint32_t method_idx,
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100129 bool should_generate_constructor_barrier,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700130 InstructionSet instruction_set,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100131 InvokeType invoke_type = kInvalidInvokeType,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100132 bool debuggable = false,
133 int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000134 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000135 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100136 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100137 linear_order_(arena, kDefaultNumberOfBlocks),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700138 entry_block_(nullptr),
139 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100140 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100141 number_of_vregs_(0),
142 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000143 temporaries_vreg_slots_(0),
Mark Mendell1152c922015-04-24 17:06:35 -0400144 has_bounds_checks_(false),
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000145 debuggable_(debuggable),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000146 current_instruction_id_(start_instruction_id),
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100147 dex_file_(dex_file),
148 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100149 invoke_type_(invoke_type),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100150 in_ssa_form_(false),
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100151 should_generate_constructor_barrier_(should_generate_constructor_barrier),
Mathieu Chartiere401d142015-04-22 13:56:20 -0700152 instruction_set_(instruction_set),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000153 cached_null_constant_(nullptr),
154 cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000155 cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
156 cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100157 cached_double_constants_(std::less<int64_t>(), arena->Adapter()),
158 cached_current_method_(nullptr) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000159
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000160 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100161 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Roland Levillain93445682014-10-06 19:24:02 +0100162 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000163
David Brazdil69ba7b72015-06-23 18:27:30 +0100164 bool IsInSsaForm() const { return in_ssa_form_; }
165
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000166 HBasicBlock* GetEntryBlock() const { return entry_block_; }
167 HBasicBlock* GetExitBlock() const { return exit_block_; }
David Brazdilc7af85d2015-05-26 12:05:55 +0100168 bool HasExitBlock() const { return exit_block_ != nullptr; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000169
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000170 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
171 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000172
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000173 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100174
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000175 // Try building the SSA form of this graph, with dominance computation and loop
176 // recognition. Returns whether it was successful in doing all these steps.
177 bool TryBuildingSsa() {
178 BuildDominatorTree();
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000179 // The SSA builder requires loops to all be natural. Specifically, the dead phi
180 // elimination phase checks the consistency of the graph when doing a post-order
181 // visit for eliminating dead phis: a dead phi can only have loop header phi
182 // users remaining when being visited.
183 if (!AnalyzeNaturalLoops()) return false;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000184 TransformToSsa();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100185 in_ssa_form_ = true;
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000186 return true;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000187 }
188
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100189 void ComputeDominanceInformation();
190 void ClearDominanceInformation();
191
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000192 void BuildDominatorTree();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000193 void TransformToSsa();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100194 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000195
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000196 // Analyze all natural loops in this graph. Returns false if one
197 // loop is not natural, that is the header does not dominate the
198 // back edge.
199 bool AnalyzeNaturalLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100200
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000201 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
202 void InlineInto(HGraph* outer_graph, HInvoke* invoke);
203
Mingyao Yang3584bce2015-05-19 16:01:59 -0700204 // Need to add a couple of blocks to test if the loop body is entered and
205 // put deoptimization instructions, etc.
206 void TransformLoopHeaderForBCE(HBasicBlock* header);
207
David Brazdil2d7352b2015-04-20 14:52:42 +0100208 // Removes `block` from the graph.
209 void DeleteDeadBlock(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000210
David Brazdilfc6a86a2015-06-26 10:33:45 +0000211 // Splits the edge between `block` and `successor` while preserving the
212 // indices in the predecessor/successor lists. If there are multiple edges
213 // between the blocks, the lowest indices are used.
214 // Returns the new block which is empty and has the same dex pc as `successor`.
215 HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor);
216
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100217 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
218 void SimplifyLoop(HBasicBlock* header);
219
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000220 int32_t GetNextInstructionId() {
221 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000222 return current_instruction_id_++;
223 }
224
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000225 int32_t GetCurrentInstructionId() const {
226 return current_instruction_id_;
227 }
228
229 void SetCurrentInstructionId(int32_t id) {
230 current_instruction_id_ = id;
231 }
232
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100233 uint16_t GetMaximumNumberOfOutVRegs() const {
234 return maximum_number_of_out_vregs_;
235 }
236
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000237 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
238 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100239 }
240
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100241 void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
242 maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
243 }
244
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000245 void UpdateTemporariesVRegSlots(size_t slots) {
246 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100247 }
248
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000249 size_t GetTemporariesVRegSlots() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100250 DCHECK(!in_ssa_form_);
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000251 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100252 }
253
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100254 void SetNumberOfVRegs(uint16_t number_of_vregs) {
255 number_of_vregs_ = number_of_vregs;
256 }
257
258 uint16_t GetNumberOfVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100259 DCHECK(!in_ssa_form_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100260 return number_of_vregs_;
261 }
262
263 void SetNumberOfInVRegs(uint16_t value) {
264 number_of_in_vregs_ = value;
265 }
266
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100267 uint16_t GetNumberOfLocalVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100268 DCHECK(!in_ssa_form_);
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100269 return number_of_vregs_ - number_of_in_vregs_;
270 }
271
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100272 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
273 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100274 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100275
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100276 const GrowableArray<HBasicBlock*>& GetLinearOrder() const {
277 return linear_order_;
278 }
279
Mark Mendell1152c922015-04-24 17:06:35 -0400280 bool HasBoundsChecks() const {
281 return has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800282 }
283
Mark Mendell1152c922015-04-24 17:06:35 -0400284 void SetHasBoundsChecks(bool value) {
285 has_bounds_checks_ = value;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800286 }
287
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100288 bool ShouldGenerateConstructorBarrier() const {
289 return should_generate_constructor_barrier_;
290 }
291
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000292 bool IsDebuggable() const { return debuggable_; }
293
David Brazdil8d5b8b22015-03-24 10:51:52 +0000294 // Returns a constant of the given type and value. If it does not exist
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000295 // already, it is created and inserted into the graph. This method is only for
296 // integral types.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000297 HConstant* GetConstant(Primitive::Type type, int64_t value);
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000298 HNullConstant* GetNullConstant();
David Brazdil8d5b8b22015-03-24 10:51:52 +0000299 HIntConstant* GetIntConstant(int32_t value) {
300 return CreateConstant(value, &cached_int_constants_);
301 }
302 HLongConstant* GetLongConstant(int64_t value) {
303 return CreateConstant(value, &cached_long_constants_);
304 }
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000305 HFloatConstant* GetFloatConstant(float value) {
306 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_);
307 }
308 HDoubleConstant* GetDoubleConstant(double value) {
309 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
310 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000311
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100312 HCurrentMethod* GetCurrentMethod();
313
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000314 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
David Brazdil2d7352b2015-04-20 14:52:42 +0100315
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100316 const DexFile& GetDexFile() const {
317 return dex_file_;
318 }
319
320 uint32_t GetMethodIdx() const {
321 return method_idx_;
322 }
323
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100324 InvokeType GetInvokeType() const {
325 return invoke_type_;
326 }
327
Mark Mendellc4701932015-04-10 13:18:51 -0400328 InstructionSet GetInstructionSet() const {
329 return instruction_set_;
330 }
331
David Brazdil2d7352b2015-04-20 14:52:42 +0100332 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000333 void VisitBlockForDominatorTree(HBasicBlock* block,
334 HBasicBlock* predecessor,
335 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100336 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000337 void VisitBlockForBackEdges(HBasicBlock* block,
338 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100339 ArenaBitVector* visiting);
Roland Levillainfc600dc2014-12-02 17:16:31 +0000340 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100341 void RemoveDeadBlocks(const ArenaBitVector& visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000342
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000343 template <class InstructionType, typename ValueType>
344 InstructionType* CreateConstant(ValueType value,
345 ArenaSafeMap<ValueType, InstructionType*>* cache) {
346 // Try to find an existing constant of the given value.
347 InstructionType* constant = nullptr;
348 auto cached_constant = cache->find(value);
349 if (cached_constant != cache->end()) {
350 constant = cached_constant->second;
351 }
352
353 // If not found or previously deleted, create and cache a new instruction.
Nicolas Geoffrayf78848f2015-06-17 11:57:56 +0100354 // Don't bother reviving a previously deleted instruction, for simplicity.
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000355 if (constant == nullptr || constant->GetBlock() == nullptr) {
356 constant = new (arena_) InstructionType(value);
357 cache->Overwrite(value, constant);
358 InsertConstant(constant);
359 }
360 return constant;
361 }
362
David Brazdil8d5b8b22015-03-24 10:51:52 +0000363 void InsertConstant(HConstant* instruction);
364
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000365 // Cache a float constant into the graph. This method should only be
366 // called by the SsaBuilder when creating "equivalent" instructions.
367 void CacheFloatConstant(HFloatConstant* constant);
368
369 // See CacheFloatConstant comment.
370 void CacheDoubleConstant(HDoubleConstant* constant);
371
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000372 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000373
374 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000375 GrowableArray<HBasicBlock*> blocks_;
376
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100377 // List of blocks to perform a reverse post order tree traversal.
378 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000379
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100380 // List of blocks to perform a linear order tree traversal.
381 GrowableArray<HBasicBlock*> linear_order_;
382
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000383 HBasicBlock* entry_block_;
384 HBasicBlock* exit_block_;
385
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100386 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100387 uint16_t maximum_number_of_out_vregs_;
388
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100389 // The number of virtual registers in this method. Contains the parameters.
390 uint16_t number_of_vregs_;
391
392 // The number of virtual registers used by parameters of this method.
393 uint16_t number_of_in_vregs_;
394
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000395 // Number of vreg size slots that the temporaries use (used in baseline compiler).
396 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100397
Mark Mendell1152c922015-04-24 17:06:35 -0400398 // Has bounds checks. We can totally skip BCE if it's false.
399 bool has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800400
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000401 // Indicates whether the graph should be compiled in a way that
402 // ensures full debuggability. If false, we can apply more
403 // aggressive optimizations that may limit the level of debugging.
404 const bool debuggable_;
405
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000406 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000407 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000408
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100409 // The dex file from which the method is from.
410 const DexFile& dex_file_;
411
412 // The method index in the dex file.
413 const uint32_t method_idx_;
414
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100415 // If inlined, this encodes how the callee is being invoked.
416 const InvokeType invoke_type_;
417
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100418 // Whether the graph has been transformed to SSA form. Only used
419 // in debug mode to ensure we are not using properties only valid
420 // for non-SSA form (like the number of temporaries).
421 bool in_ssa_form_;
422
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100423 const bool should_generate_constructor_barrier_;
424
Mathieu Chartiere401d142015-04-22 13:56:20 -0700425 const InstructionSet instruction_set_;
426
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000427 // Cached constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000428 HNullConstant* cached_null_constant_;
429 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000430 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
David Brazdil8d5b8b22015-03-24 10:51:52 +0000431 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000432 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
David Brazdil46e2a392015-03-16 17:31:52 +0000433
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100434 HCurrentMethod* cached_current_method_;
435
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000436 friend class SsaBuilder; // For caching constants.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100437 friend class SsaLivenessAnalysis; // For the linear order.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000438 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000439 DISALLOW_COPY_AND_ASSIGN(HGraph);
440};
441
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700442class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000443 public:
444 HLoopInformation(HBasicBlock* header, HGraph* graph)
445 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100446 suspend_check_(nullptr),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100447 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100448 // Make bit vector growable, as the number of blocks may change.
449 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100450
451 HBasicBlock* GetHeader() const {
452 return header_;
453 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000454
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000455 void SetHeader(HBasicBlock* block) {
456 header_ = block;
457 }
458
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100459 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
460 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
461 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
462
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000463 void AddBackEdge(HBasicBlock* back_edge) {
464 back_edges_.Add(back_edge);
465 }
466
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100467 void RemoveBackEdge(HBasicBlock* back_edge) {
468 back_edges_.Delete(back_edge);
469 }
470
David Brazdil46e2a392015-03-16 17:31:52 +0000471 bool IsBackEdge(const HBasicBlock& block) const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100472 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
David Brazdil46e2a392015-03-16 17:31:52 +0000473 if (back_edges_.Get(i) == &block) return true;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100474 }
475 return false;
476 }
477
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000478 size_t NumberOfBackEdges() const {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000479 return back_edges_.Size();
480 }
481
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100482 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100483
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100484 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
485 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100486 }
487
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100488 // Returns the lifetime position of the back edge that has the
489 // greatest lifetime position.
490 size_t GetLifetimeEnd() const;
491
492 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
493 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
494 if (back_edges_.Get(i) == existing) {
495 back_edges_.Put(i, new_back_edge);
496 return;
497 }
498 }
499 UNREACHABLE();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100500 }
501
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100502 // Finds blocks that are part of this loop. Returns whether the loop is a natural loop,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100503 // that is the header dominates the back edge.
504 bool Populate();
505
David Brazdila4b8c212015-05-07 09:59:30 +0100506 // Reanalyzes the loop by removing loop info from its blocks and re-running
507 // Populate(). If there are no back edges left, the loop info is completely
508 // removed as well as its SuspendCheck instruction. It must be run on nested
509 // inner loops first.
510 void Update();
511
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100512 // Returns whether this loop information contains `block`.
513 // Note that this loop information *must* be populated before entering this function.
514 bool Contains(const HBasicBlock& block) const;
515
516 // Returns whether this loop information is an inner loop of `other`.
517 // Note that `other` *must* be populated before entering this function.
518 bool IsIn(const HLoopInformation& other) const;
519
520 const ArenaBitVector& GetBlocks() const { return blocks_; }
521
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000522 void Add(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000523 void Remove(HBasicBlock* block);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000524
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000525 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100526 // Internal recursive implementation of `Populate`.
527 void PopulateRecursive(HBasicBlock* block);
528
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000529 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100530 HSuspendCheck* suspend_check_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000531 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100532 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000533
534 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
535};
536
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100537static constexpr size_t kNoLifetime = -1;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100538static constexpr uint32_t kNoDexPc = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100539
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000540// A block in a method. Contains the list of instructions represented
541// as a double linked list. Each block knows its predecessors and
542// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100543
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700544class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000545 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100546 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000547 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000548 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
549 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000550 loop_information_(nullptr),
551 dominator_(nullptr),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100552 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100553 block_id_(-1),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100554 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100555 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000556 lifetime_end_(kNoLifetime),
557 is_catch_block_(false) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000558
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100559 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
560 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000561 }
562
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100563 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
564 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000565 }
566
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100567 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
568 return dominated_blocks_;
569 }
570
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100571 bool IsEntryBlock() const {
572 return graph_->GetEntryBlock() == this;
573 }
574
575 bool IsExitBlock() const {
576 return graph_->GetExitBlock() == this;
577 }
578
David Brazdil46e2a392015-03-16 17:31:52 +0000579 bool IsSingleGoto() const;
David Brazdilfc6a86a2015-06-26 10:33:45 +0000580 bool IsSingleTryBoundary() const;
581
582 // Returns true if this block emits nothing but a jump.
583 bool IsSingleJump() const {
584 HLoopInformation* loop_info = GetLoopInformation();
585 return (IsSingleGoto() || IsSingleTryBoundary())
586 // Back edges generate a suspend check.
587 && (loop_info == nullptr || !loop_info->IsBackEdge(*this));
588 }
David Brazdil46e2a392015-03-16 17:31:52 +0000589
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000590 void AddBackEdge(HBasicBlock* back_edge) {
591 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000592 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000593 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100594 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000595 loop_information_->AddBackEdge(back_edge);
596 }
597
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000598 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000599 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000600
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000601 int GetBlockId() const { return block_id_; }
602 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000603
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000604 HBasicBlock* GetDominator() const { return dominator_; }
605 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100606 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
David Brazdil2d7352b2015-04-20 14:52:42 +0100607 void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000608 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
609 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
610 if (dominated_blocks_.Get(i) == existing) {
611 dominated_blocks_.Put(i, new_block);
612 return;
613 }
614 }
615 LOG(FATAL) << "Unreachable";
616 UNREACHABLE();
617 }
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100618 void ClearDominanceInformation();
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000619
620 int NumberOfBackEdges() const {
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100621 return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000622 }
623
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100624 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
625 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100626 const HInstructionList& GetInstructions() const { return instructions_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100627 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
David Brazdilc3d743f2015-04-22 13:40:50 +0100628 HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
629 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000630
631 void AddSuccessor(HBasicBlock* block) {
632 successors_.Add(block);
633 block->predecessors_.Add(this);
634 }
635
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100636 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
637 size_t successor_index = GetSuccessorIndexOf(existing);
638 DCHECK_NE(successor_index, static_cast<size_t>(-1));
639 existing->RemovePredecessor(this);
640 new_block->predecessors_.Add(this);
641 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000642 }
643
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000644 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
645 size_t predecessor_index = GetPredecessorIndexOf(existing);
646 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
647 existing->RemoveSuccessor(this);
648 new_block->successors_.Add(this);
649 predecessors_.Put(predecessor_index, new_block);
650 }
651
Nicolas Geoffray8b20f882015-06-19 16:17:05 +0100652 // Insert `this` between `predecessor` and `successor. This method
653 // preserves the indicies, and will update the first edge found between
654 // `predecessor` and `successor`.
655 void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
656 size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
657 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
658 size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
659 DCHECK_NE(successor_index, static_cast<size_t>(-1));
660 successor->predecessors_.Put(predecessor_index, this);
661 predecessor->successors_.Put(successor_index, this);
662 successors_.Add(successor);
663 predecessors_.Add(predecessor);
664 }
665
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100666 void RemovePredecessor(HBasicBlock* block) {
667 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100668 }
669
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000670 void RemoveSuccessor(HBasicBlock* block) {
671 successors_.Delete(block);
672 }
673
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100674 void ClearAllPredecessors() {
675 predecessors_.Reset();
676 }
677
678 void AddPredecessor(HBasicBlock* block) {
679 predecessors_.Add(block);
680 block->successors_.Add(this);
681 }
682
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100683 void SwapPredecessors() {
Nicolas Geoffrayc83d4412014-09-18 16:46:20 +0100684 DCHECK_EQ(predecessors_.Size(), 2u);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100685 HBasicBlock* temp = predecessors_.Get(0);
686 predecessors_.Put(0, predecessors_.Get(1));
687 predecessors_.Put(1, temp);
688 }
689
David Brazdil769c9e52015-04-27 13:54:09 +0100690 void SwapSuccessors() {
691 DCHECK_EQ(successors_.Size(), 2u);
692 HBasicBlock* temp = successors_.Get(0);
693 successors_.Put(0, successors_.Get(1));
694 successors_.Put(1, temp);
695 }
696
David Brazdilfc6a86a2015-06-26 10:33:45 +0000697 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const {
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100698 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
699 if (predecessors_.Get(i) == predecessor) {
700 return i;
701 }
702 }
703 return -1;
704 }
705
David Brazdilfc6a86a2015-06-26 10:33:45 +0000706 size_t GetSuccessorIndexOf(HBasicBlock* successor) const {
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100707 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
708 if (successors_.Get(i) == successor) {
709 return i;
710 }
711 }
712 return -1;
713 }
714
David Brazdilfc6a86a2015-06-26 10:33:45 +0000715 HBasicBlock* GetSinglePredecessor() const {
716 DCHECK_EQ(GetPredecessors().Size(), 1u);
717 return GetPredecessors().Get(0);
718 }
719
720 HBasicBlock* GetSingleSuccessor() const {
721 DCHECK_EQ(GetSuccessors().Size(), 1u);
722 return GetSuccessors().Get(0);
723 }
724
725 // Returns whether the first occurrence of `predecessor` in the list of
726 // predecessors is at index `idx`.
727 bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const {
728 DCHECK_EQ(GetPredecessors().Get(idx), predecessor);
729 return GetPredecessorIndexOf(predecessor) == idx;
730 }
731
732 // Returns whether successor at index `idx` is an exception handler.
733 bool IsExceptionalSuccessor(size_t idx) const;
734
735 // Split the block into two blocks just before `cursor`. Returns the newly
David Brazdil56e1acc2015-06-30 15:41:36 +0100736 // created, latter block. Note that this method will add the block to the
737 // graph, create a Goto at the end of the former block and will create an edge
738 // between the blocks. It will not, however, update the reverse post order or
739 // loop information.
David Brazdilfc6a86a2015-06-26 10:33:45 +0000740 HBasicBlock* SplitBefore(HInstruction* cursor);
741
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000742 // Split the block into two blocks just after `cursor`. Returns the newly
743 // created block. Note that this method just updates raw block information,
744 // like predecessors, successors, dominators, and instruction list. It does not
745 // update the graph, reverse post order, loop information, nor make sure the
746 // blocks are consistent (for example ending with a control flow instruction).
747 HBasicBlock* SplitAfter(HInstruction* cursor);
748
749 // Merge `other` at the end of `this`. Successors and dominated blocks of
750 // `other` are changed to be successors and dominated blocks of `this`. Note
751 // that this method does not update the graph, reverse post order, loop
752 // information, nor make sure the blocks are consistent (for example ending
753 // with a control flow instruction).
David Brazdil2d7352b2015-04-20 14:52:42 +0100754 void MergeWithInlined(HBasicBlock* other);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000755
756 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
757 // of `this` are moved to `other`.
758 // Note that this method does not update the graph, reverse post order, loop
759 // information, nor make sure the blocks are consistent (for example ending
David Brazdil46e2a392015-03-16 17:31:52 +0000760 // with a control flow instruction).
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000761 void ReplaceWith(HBasicBlock* other);
762
David Brazdil2d7352b2015-04-20 14:52:42 +0100763 // Merge `other` at the end of `this`. This method updates loops, reverse post
764 // order, links to predecessors, successors, dominators and deletes the block
765 // from the graph. The two blocks must be successive, i.e. `this` the only
766 // predecessor of `other` and vice versa.
767 void MergeWith(HBasicBlock* other);
768
769 // Disconnects `this` from all its predecessors, successors and dominator,
770 // removes it from all loops it is included in and eventually from the graph.
771 // The block must not dominate any other block. Predecessors and successors
772 // are safely updated.
773 void DisconnectAndDelete();
David Brazdil46e2a392015-03-16 17:31:52 +0000774
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000775 void AddInstruction(HInstruction* instruction);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100776 // Insert `instruction` before/after an existing instruction `cursor`.
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100777 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100778 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +0100779 // Replace instruction `initial` with `replacement` within this block.
780 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
781 HInstruction* replacement);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100782 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100783 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
David Brazdil1abb4192015-02-17 18:33:36 +0000784 // RemoveInstruction and RemovePhi delete a given instruction from the respective
785 // instruction list. With 'ensure_safety' set to true, it verifies that the
786 // instruction is not in use and removes it from the use lists of its inputs.
787 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
788 void RemovePhi(HPhi* phi, bool ensure_safety = true);
David Brazdilc7508e92015-04-27 13:28:57 +0100789 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100790
791 bool IsLoopHeader() const {
David Brazdil69a28042015-04-29 17:16:07 +0100792 return IsInLoop() && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100793 }
794
Roland Levillain6b879dd2014-09-22 17:13:44 +0100795 bool IsLoopPreHeaderFirstPredecessor() const {
796 DCHECK(IsLoopHeader());
797 DCHECK(!GetPredecessors().IsEmpty());
798 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
799 }
800
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100801 HLoopInformation* GetLoopInformation() const {
802 return loop_information_;
803 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000804
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000805 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100806 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000807 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100808 void SetInLoop(HLoopInformation* info) {
809 if (IsLoopHeader()) {
810 // Nothing to do. This just means `info` is an outer loop.
David Brazdil69a28042015-04-29 17:16:07 +0100811 } else if (!IsInLoop()) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100812 loop_information_ = info;
813 } else if (loop_information_->Contains(*info->GetHeader())) {
814 // Block is currently part of an outer loop. Make it part of this inner loop.
815 // Note that a non loop header having a loop information means this loop information
816 // has already been populated
817 loop_information_ = info;
818 } else {
819 // Block is part of an inner loop. Do not update the loop information.
820 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
821 // at this point, because this method is being called while populating `info`.
822 }
823 }
824
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000825 // Raw update of the loop information.
826 void SetLoopInformation(HLoopInformation* info) {
827 loop_information_ = info;
828 }
829
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100830 bool IsInLoop() const { return loop_information_ != nullptr; }
831
David Brazdila4b8c212015-05-07 09:59:30 +0100832 // Returns whether this block dominates the blocked passed as parameter.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100833 bool Dominates(HBasicBlock* block) const;
834
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100835 size_t GetLifetimeStart() const { return lifetime_start_; }
836 size_t GetLifetimeEnd() const { return lifetime_end_; }
837
838 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
839 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
840
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100841 uint32_t GetDexPc() const { return dex_pc_; }
842
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000843 bool IsCatchBlock() const { return is_catch_block_; }
844 void SetIsCatchBlock() { is_catch_block_ = true; }
845
David Brazdil8d5b8b22015-03-24 10:51:52 +0000846 bool EndsWithControlFlowInstruction() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +0000847 bool EndsWithIf() const;
848 bool HasSinglePhi() const;
849
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000850 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000851 HGraph* graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000852 GrowableArray<HBasicBlock*> predecessors_;
853 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100854 HInstructionList instructions_;
855 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000856 HLoopInformation* loop_information_;
857 HBasicBlock* dominator_;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100858 GrowableArray<HBasicBlock*> dominated_blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000859 int block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100860 // The dex program counter of the first instruction of this block.
861 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100862 size_t lifetime_start_;
863 size_t lifetime_end_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000864 bool is_catch_block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000865
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000866 friend class HGraph;
867 friend class HInstruction;
868
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000869 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
870};
871
David Brazdilb2bd1c52015-03-25 11:17:37 +0000872// Iterates over the LoopInformation of all loops which contain 'block'
873// from the innermost to the outermost.
874class HLoopInformationOutwardIterator : public ValueObject {
875 public:
876 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
877 : current_(block.GetLoopInformation()) {}
878
879 bool Done() const { return current_ == nullptr; }
880
881 void Advance() {
882 DCHECK(!Done());
David Brazdil69a28042015-04-29 17:16:07 +0100883 current_ = current_->GetPreHeader()->GetLoopInformation();
David Brazdilb2bd1c52015-03-25 11:17:37 +0000884 }
885
886 HLoopInformation* Current() const {
887 DCHECK(!Done());
888 return current_;
889 }
890
891 private:
892 HLoopInformation* current_;
893
894 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
895};
896
Alexandre Ramesef20f712015-06-09 10:29:30 +0100897#define FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100898 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000899 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000900 M(ArrayGet, Instruction) \
901 M(ArrayLength, Instruction) \
902 M(ArraySet, Instruction) \
David Brazdil66d126e2015-04-03 16:02:44 +0100903 M(BooleanNot, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000904 M(BoundsCheck, Instruction) \
Calin Juravleb1498f62015-02-16 13:13:29 +0000905 M(BoundType, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000906 M(CheckCast, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100907 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000908 M(Compare, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100909 M(Condition, BinaryOperation) \
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100910 M(CurrentMethod, Instruction) \
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700911 M(Deoptimize, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000912 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +0000913 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000914 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100915 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000916 M(Exit, Instruction) \
917 M(FloatConstant, Constant) \
918 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100919 M(GreaterThan, Condition) \
920 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100921 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000922 M(InstanceFieldGet, Instruction) \
923 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000924 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100925 M(IntConstant, Constant) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000926 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000927 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100928 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000929 M(LessThan, Condition) \
930 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000931 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000932 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100933 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000934 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100935 M(Local, Instruction) \
936 M(LongConstant, Constant) \
Calin Juravle27df7582015-04-17 19:12:31 +0100937 M(MemoryBarrier, Instruction) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +0000938 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000939 M(Mul, BinaryOperation) \
940 M(Neg, UnaryOperation) \
941 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100942 M(NewInstance, Instruction) \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100943 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000944 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000945 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000946 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000947 M(Or, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100948 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000949 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100950 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000951 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100952 M(Return, Instruction) \
953 M(ReturnVoid, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000954 M(Shl, BinaryOperation) \
955 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100956 M(StaticFieldGet, Instruction) \
957 M(StaticFieldSet, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100958 M(StoreLocal, Instruction) \
959 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100960 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000961 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000962 M(Throw, Instruction) \
David Brazdilfc6a86a2015-06-26 10:33:45 +0000963 M(TryBoundary, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +0000964 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000965 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000966 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000967
Alexandre Ramesef20f712015-06-09 10:29:30 +0100968#define FOR_EACH_CONCRETE_INSTRUCTION_ARM(M)
969
970#define FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M)
971
Alexandre Ramesf39e0642015-06-23 11:33:45 +0100972#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M)
973
Alexandre Ramesef20f712015-06-09 10:29:30 +0100974#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
975
976#define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
977
978#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
979 FOR_EACH_CONCRETE_INSTRUCTION_COMMON(M) \
980 FOR_EACH_CONCRETE_INSTRUCTION_ARM(M) \
981 FOR_EACH_CONCRETE_INSTRUCTION_ARM64(M) \
Alexandre Ramesf39e0642015-06-23 11:33:45 +0100982 FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M) \
Alexandre Ramesef20f712015-06-09 10:29:30 +0100983 FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
984 FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
985
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100986#define FOR_EACH_INSTRUCTION(M) \
987 FOR_EACH_CONCRETE_INSTRUCTION(M) \
988 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +0100989 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +0100990 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100991 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -0700992
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100993#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000994FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
995#undef FORWARD_DECLARATION
996
Roland Levillainccc07a92014-09-16 14:48:16 +0100997#define DECLARE_INSTRUCTION(type) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000998 InstructionKind GetKind() const OVERRIDE { return k##type; } \
999 const char* DebugName() const OVERRIDE { return #type; } \
1000 const H##type* As##type() const OVERRIDE { return this; } \
1001 H##type* As##type() OVERRIDE { return this; } \
1002 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \
Roland Levillainccc07a92014-09-16 14:48:16 +01001003 return other->Is##type(); \
1004 } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001005 void Accept(HGraphVisitor* visitor) OVERRIDE
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001006
David Brazdiled596192015-01-23 10:39:45 +00001007template <typename T> class HUseList;
1008
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001009template <typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001010class HUseListNode : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001011 public:
David Brazdiled596192015-01-23 10:39:45 +00001012 HUseListNode* GetPrevious() const { return prev_; }
1013 HUseListNode* GetNext() const { return next_; }
1014 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001015 size_t GetIndex() const { return index_; }
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001016 void SetIndex(size_t index) { index_ = index; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001017
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001018 private:
David Brazdiled596192015-01-23 10:39:45 +00001019 HUseListNode(T user, size_t index)
1020 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
1021
1022 T const user_;
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001023 size_t index_;
David Brazdiled596192015-01-23 10:39:45 +00001024 HUseListNode<T>* prev_;
1025 HUseListNode<T>* next_;
1026
1027 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001028
1029 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
1030};
1031
David Brazdiled596192015-01-23 10:39:45 +00001032template <typename T>
1033class HUseList : public ValueObject {
1034 public:
1035 HUseList() : first_(nullptr) {}
1036
1037 void Clear() {
1038 first_ = nullptr;
1039 }
1040
1041 // Adds a new entry at the beginning of the use list and returns
1042 // the newly created node.
1043 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +00001044 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +00001045 if (IsEmpty()) {
1046 first_ = new_node;
1047 } else {
1048 first_->prev_ = new_node;
1049 new_node->next_ = first_;
1050 first_ = new_node;
1051 }
1052 return new_node;
1053 }
1054
1055 HUseListNode<T>* GetFirst() const {
1056 return first_;
1057 }
1058
1059 void Remove(HUseListNode<T>* node) {
David Brazdil1abb4192015-02-17 18:33:36 +00001060 DCHECK(node != nullptr);
1061 DCHECK(Contains(node));
1062
David Brazdiled596192015-01-23 10:39:45 +00001063 if (node->prev_ != nullptr) {
1064 node->prev_->next_ = node->next_;
1065 }
1066 if (node->next_ != nullptr) {
1067 node->next_->prev_ = node->prev_;
1068 }
1069 if (node == first_) {
1070 first_ = node->next_;
1071 }
1072 }
1073
David Brazdil1abb4192015-02-17 18:33:36 +00001074 bool Contains(const HUseListNode<T>* node) const {
1075 if (node == nullptr) {
1076 return false;
1077 }
1078 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1079 if (current == node) {
1080 return true;
1081 }
1082 }
1083 return false;
1084 }
1085
David Brazdiled596192015-01-23 10:39:45 +00001086 bool IsEmpty() const {
1087 return first_ == nullptr;
1088 }
1089
1090 bool HasOnlyOneUse() const {
1091 return first_ != nullptr && first_->next_ == nullptr;
1092 }
1093
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001094 size_t SizeSlow() const {
1095 size_t count = 0;
1096 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1097 ++count;
1098 }
1099 return count;
1100 }
1101
David Brazdiled596192015-01-23 10:39:45 +00001102 private:
1103 HUseListNode<T>* first_;
1104};
1105
1106template<typename T>
1107class HUseIterator : public ValueObject {
1108 public:
1109 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
1110
1111 bool Done() const { return current_ == nullptr; }
1112
1113 void Advance() {
1114 DCHECK(!Done());
1115 current_ = current_->GetNext();
1116 }
1117
1118 HUseListNode<T>* Current() const {
1119 DCHECK(!Done());
1120 return current_;
1121 }
1122
1123 private:
1124 HUseListNode<T>* current_;
1125
1126 friend class HValue;
1127};
1128
David Brazdil1abb4192015-02-17 18:33:36 +00001129// This class is used by HEnvironment and HInstruction classes to record the
1130// instructions they use and pointers to the corresponding HUseListNodes kept
1131// by the used instructions.
1132template <typename T>
1133class HUserRecord : public ValueObject {
1134 public:
1135 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
1136 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
1137
1138 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
1139 : instruction_(old_record.instruction_), use_node_(use_node) {
1140 DCHECK(instruction_ != nullptr);
1141 DCHECK(use_node_ != nullptr);
1142 DCHECK(old_record.use_node_ == nullptr);
1143 }
1144
1145 HInstruction* GetInstruction() const { return instruction_; }
1146 HUseListNode<T>* GetUseNode() const { return use_node_; }
1147
1148 private:
1149 // Instruction used by the user.
1150 HInstruction* instruction_;
1151
1152 // Corresponding entry in the use list kept by 'instruction_'.
1153 HUseListNode<T>* use_node_;
1154};
1155
Calin Juravle27df7582015-04-17 19:12:31 +01001156// TODO: Add better documentation to this class and maybe refactor with more suggestive names.
1157// - Has(All)SideEffects suggests that all the side effects are present but only ChangesSomething
1158// flag is consider.
1159// - DependsOn suggests that there is a real dependency between side effects but it only
1160// checks DependendsOnSomething flag.
1161//
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001162// Represents the side effects an instruction may have.
1163class SideEffects : public ValueObject {
1164 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001165 SideEffects() : flags_(0) {}
1166
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001167 static SideEffects None() {
1168 return SideEffects(0);
1169 }
1170
1171 static SideEffects All() {
1172 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
1173 }
1174
1175 static SideEffects ChangesSomething() {
1176 return SideEffects((1 << kFlagChangesCount) - 1);
1177 }
1178
1179 static SideEffects DependsOnSomething() {
1180 int count = kFlagDependsOnCount - kFlagChangesCount;
1181 return SideEffects(((1 << count) - 1) << kFlagChangesCount);
1182 }
1183
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001184 SideEffects Union(SideEffects other) const {
1185 return SideEffects(flags_ | other.flags_);
1186 }
1187
Roland Levillain72bceff2014-09-15 18:29:00 +01001188 bool HasSideEffects() const {
1189 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1190 return (flags_ & all_bits_set) != 0;
1191 }
1192
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001193 bool HasAllSideEffects() const {
1194 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1195 return all_bits_set == (flags_ & all_bits_set);
1196 }
1197
1198 bool DependsOn(SideEffects other) const {
1199 size_t depends_flags = other.ComputeDependsFlags();
1200 return (flags_ & depends_flags) != 0;
1201 }
1202
1203 bool HasDependencies() const {
1204 int count = kFlagDependsOnCount - kFlagChangesCount;
1205 size_t all_bits_set = (1 << count) - 1;
1206 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
1207 }
1208
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001209 private:
1210 static constexpr int kFlagChangesSomething = 0;
1211 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
1212
1213 static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
1214 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
1215
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001216 explicit SideEffects(size_t flags) : flags_(flags) {}
1217
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001218 size_t ComputeDependsFlags() const {
1219 return flags_ << kFlagChangesCount;
1220 }
1221
1222 size_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001223};
1224
David Brazdiled596192015-01-23 10:39:45 +00001225// A HEnvironment object contains the values of virtual registers at a given location.
1226class HEnvironment : public ArenaObject<kArenaAllocMisc> {
1227 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001228 HEnvironment(ArenaAllocator* arena,
1229 size_t number_of_vregs,
1230 const DexFile& dex_file,
1231 uint32_t method_idx,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001232 uint32_t dex_pc,
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001233 InvokeType invoke_type,
1234 HInstruction* holder)
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001235 : vregs_(arena, number_of_vregs),
1236 locations_(arena, number_of_vregs),
1237 parent_(nullptr),
1238 dex_file_(dex_file),
1239 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001240 dex_pc_(dex_pc),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001241 invoke_type_(invoke_type),
1242 holder_(holder) {
David Brazdiled596192015-01-23 10:39:45 +00001243 vregs_.SetSize(number_of_vregs);
1244 for (size_t i = 0; i < number_of_vregs; i++) {
David Brazdil1abb4192015-02-17 18:33:36 +00001245 vregs_.Put(i, HUserRecord<HEnvironment*>());
David Brazdiled596192015-01-23 10:39:45 +00001246 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001247
1248 locations_.SetSize(number_of_vregs);
1249 for (size_t i = 0; i < number_of_vregs; ++i) {
1250 locations_.Put(i, Location());
1251 }
1252 }
1253
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001254 HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001255 : HEnvironment(arena,
1256 to_copy.Size(),
1257 to_copy.GetDexFile(),
1258 to_copy.GetMethodIdx(),
1259 to_copy.GetDexPc(),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001260 to_copy.GetInvokeType(),
1261 holder) {}
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001262
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001263 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001264 if (parent_ != nullptr) {
1265 parent_->SetAndCopyParentChain(allocator, parent);
1266 } else {
1267 parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
1268 parent_->CopyFrom(parent);
1269 if (parent->GetParent() != nullptr) {
1270 parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1271 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001272 }
David Brazdiled596192015-01-23 10:39:45 +00001273 }
1274
Nicolas Geoffray8c0c91a2015-05-07 11:46:05 +01001275 void CopyFrom(const GrowableArray<HInstruction*>& locals);
1276 void CopyFrom(HEnvironment* environment);
1277
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001278 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1279 // input to the loop phi instead. This is for inserting instructions that
1280 // require an environment (like HDeoptimization) in the loop pre-header.
1281 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
David Brazdiled596192015-01-23 10:39:45 +00001282
1283 void SetRawEnvAt(size_t index, HInstruction* instruction) {
David Brazdil1abb4192015-02-17 18:33:36 +00001284 vregs_.Put(index, HUserRecord<HEnvironment*>(instruction));
David Brazdiled596192015-01-23 10:39:45 +00001285 }
1286
1287 HInstruction* GetInstructionAt(size_t index) const {
David Brazdil1abb4192015-02-17 18:33:36 +00001288 return vregs_.Get(index).GetInstruction();
David Brazdiled596192015-01-23 10:39:45 +00001289 }
1290
David Brazdil1abb4192015-02-17 18:33:36 +00001291 void RemoveAsUserOfInput(size_t index) const;
David Brazdiled596192015-01-23 10:39:45 +00001292
1293 size_t Size() const { return vregs_.Size(); }
1294
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001295 HEnvironment* GetParent() const { return parent_; }
1296
1297 void SetLocationAt(size_t index, Location location) {
1298 locations_.Put(index, location);
1299 }
1300
1301 Location GetLocationAt(size_t index) const {
1302 return locations_.Get(index);
1303 }
1304
1305 uint32_t GetDexPc() const {
1306 return dex_pc_;
1307 }
1308
1309 uint32_t GetMethodIdx() const {
1310 return method_idx_;
1311 }
1312
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001313 InvokeType GetInvokeType() const {
1314 return invoke_type_;
1315 }
1316
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001317 const DexFile& GetDexFile() const {
1318 return dex_file_;
1319 }
1320
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001321 HInstruction* GetHolder() const {
1322 return holder_;
1323 }
1324
David Brazdiled596192015-01-23 10:39:45 +00001325 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001326 // Record instructions' use entries of this environment for constant-time removal.
1327 // It should only be called by HInstruction when a new environment use is added.
1328 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1329 DCHECK(env_use->GetUser() == this);
1330 size_t index = env_use->GetIndex();
1331 vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use));
1332 }
David Brazdiled596192015-01-23 10:39:45 +00001333
David Brazdil1abb4192015-02-17 18:33:36 +00001334 GrowableArray<HUserRecord<HEnvironment*> > vregs_;
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001335 GrowableArray<Location> locations_;
1336 HEnvironment* parent_;
1337 const DexFile& dex_file_;
1338 const uint32_t method_idx_;
1339 const uint32_t dex_pc_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001340 const InvokeType invoke_type_;
David Brazdiled596192015-01-23 10:39:45 +00001341
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001342 // The instruction that holds this environment. Only used in debug mode
1343 // to ensure the graph is consistent.
1344 HInstruction* const holder_;
1345
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001346 friend class HInstruction;
David Brazdiled596192015-01-23 10:39:45 +00001347
1348 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1349};
1350
Calin Juravleacf735c2015-02-12 15:25:22 +00001351class ReferenceTypeInfo : ValueObject {
1352 public:
Calin Juravleb1498f62015-02-16 13:13:29 +00001353 typedef Handle<mirror::Class> TypeHandle;
1354
1355 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
1356 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1357 if (type_handle->IsObjectClass()) {
1358 // Override the type handle to be consistent with the case when we get to
1359 // Top but don't have the Object class available. It avoids having to guess
1360 // what value the type_handle has when it's Top.
1361 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1362 } else {
1363 return ReferenceTypeInfo(type_handle, is_exact, false);
1364 }
1365 }
1366
1367 static ReferenceTypeInfo CreateTop(bool is_exact) {
1368 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
Calin Juravleacf735c2015-02-12 15:25:22 +00001369 }
1370
1371 bool IsExact() const { return is_exact_; }
1372 bool IsTop() const { return is_top_; }
Guillaume Sanchez222862c2015-06-09 18:33:02 +01001373 bool IsInterface() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1374 return !IsTop() && GetTypeHandle()->IsInterface();
1375 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001376
1377 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
1378
Calin Juravleb1498f62015-02-16 13:13:29 +00001379 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Calin Juravleacf735c2015-02-12 15:25:22 +00001380 if (IsTop()) {
1381 // Top (equivalent for java.lang.Object) is supertype of anything.
1382 return true;
1383 }
1384 if (rti.IsTop()) {
1385 // If we get here `this` is not Top() so it can't be a supertype.
1386 return false;
1387 }
1388 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
1389 }
1390
1391 // Returns true if the type information provide the same amount of details.
1392 // Note that it does not mean that the instructions have the same actual type
1393 // (e.g. tops are equal but they can be the result of a merge).
1394 bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1395 if (IsExact() != rti.IsExact()) {
1396 return false;
1397 }
1398 if (IsTop() && rti.IsTop()) {
1399 // `Top` means java.lang.Object, so the types are equivalent.
1400 return true;
1401 }
1402 if (IsTop() || rti.IsTop()) {
1403 // If only one is top or object than they are not equivalent.
1404 // NB: We need this extra check because the type_handle of `Top` is invalid
1405 // and we cannot inspect its reference.
1406 return false;
1407 }
1408
1409 // Finally check the types.
1410 return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
1411 }
1412
1413 private:
Calin Juravleb1498f62015-02-16 13:13:29 +00001414 ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
1415 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
1416 : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
1417
Calin Juravleacf735c2015-02-12 15:25:22 +00001418 // The class of the object.
Calin Juravleb1498f62015-02-16 13:13:29 +00001419 TypeHandle type_handle_;
Calin Juravleacf735c2015-02-12 15:25:22 +00001420 // Whether or not the type is exact or a superclass of the actual type.
Calin Juravleb1498f62015-02-16 13:13:29 +00001421 // Whether or not we have any information about this type.
Calin Juravleacf735c2015-02-12 15:25:22 +00001422 bool is_exact_;
1423 // A true value here means that the object type should be java.lang.Object.
1424 // We don't have access to the corresponding mirror object every time so this
1425 // flag acts as a substitute. When true, the TypeHandle refers to a null
1426 // pointer and should not be used.
1427 bool is_top_;
1428};
1429
1430std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
1431
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001432class HInstruction : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001433 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001434 explicit HInstruction(SideEffects side_effects)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001435 : previous_(nullptr),
1436 next_(nullptr),
1437 block_(nullptr),
1438 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001439 ssa_index_(-1),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001440 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001441 locations_(nullptr),
1442 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001443 lifetime_position_(kNoLifetime),
Calin Juravleb1498f62015-02-16 13:13:29 +00001444 side_effects_(side_effects),
1445 reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001446
Dave Allison20dfc792014-06-16 20:44:29 -07001447 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001448
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001449#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001450 enum InstructionKind {
1451 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1452 };
1453#undef DECLARE_KIND
1454
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001455 HInstruction* GetNext() const { return next_; }
1456 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001457
Calin Juravle77520bc2015-01-12 18:45:46 +00001458 HInstruction* GetNextDisregardingMoves() const;
1459 HInstruction* GetPreviousDisregardingMoves() const;
1460
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001461 HBasicBlock* GetBlock() const { return block_; }
1462 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001463 bool IsInBlock() const { return block_ != nullptr; }
1464 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray3ac17fc2014-08-06 23:02:54 +01001465 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001466
Roland Levillain6b879dd2014-09-22 17:13:44 +01001467 virtual size_t InputCount() const = 0;
David Brazdil1abb4192015-02-17 18:33:36 +00001468 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001469
1470 virtual void Accept(HGraphVisitor* visitor) = 0;
1471 virtual const char* DebugName() const = 0;
1472
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001473 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
David Brazdil1abb4192015-02-17 18:33:36 +00001474 void SetRawInputAt(size_t index, HInstruction* input) {
1475 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1476 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001477
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001478 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001479 virtual uint32_t GetDexPc() const {
1480 LOG(FATAL) << "GetDexPc() cannot be called on an instruction that"
1481 " does not need an environment";
1482 UNREACHABLE();
1483 }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001484 virtual bool IsControlFlow() const { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01001485 virtual bool CanThrow() const { return false; }
Roland Levillain72bceff2014-09-15 18:29:00 +01001486 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001487
Calin Juravle10e244f2015-01-26 18:54:32 +00001488 // Does not apply for all instructions, but having this at top level greatly
1489 // simplifies the null check elimination.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001490 virtual bool CanBeNull() const {
1491 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1492 return true;
1493 }
Calin Juravle10e244f2015-01-26 18:54:32 +00001494
Calin Juravle641547a2015-04-21 22:08:51 +01001495 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj) const {
1496 UNUSED(obj);
1497 return false;
1498 }
Calin Juravle77520bc2015-01-12 18:45:46 +00001499
Calin Juravleacf735c2015-02-12 15:25:22 +00001500 void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
Calin Juravle61d544b2015-02-23 16:46:57 +00001501 DCHECK_EQ(GetType(), Primitive::kPrimNot);
Calin Juravleacf735c2015-02-12 15:25:22 +00001502 reference_type_info_ = reference_type_info;
1503 }
1504
Calin Juravle61d544b2015-02-23 16:46:57 +00001505 ReferenceTypeInfo GetReferenceTypeInfo() const {
1506 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1507 return reference_type_info_;
1508 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001509
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001510 void AddUseAt(HInstruction* user, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +00001511 DCHECK(user != nullptr);
1512 HUseListNode<HInstruction*>* use =
1513 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1514 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001515 }
1516
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001517 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +01001518 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +00001519 HUseListNode<HEnvironment*>* env_use =
1520 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1521 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001522 }
1523
David Brazdil1abb4192015-02-17 18:33:36 +00001524 void RemoveAsUserOfInput(size_t input) {
1525 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1526 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1527 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001528
David Brazdil1abb4192015-02-17 18:33:36 +00001529 const HUseList<HInstruction*>& GetUses() const { return uses_; }
1530 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001531
David Brazdiled596192015-01-23 10:39:45 +00001532 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
1533 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001534 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
Alexandre Rames188d4312015-04-09 18:30:21 +01001535 bool HasOnlyOneNonEnvironmentUse() const {
1536 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1537 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001538
Roland Levillain6c82d402014-10-13 16:10:27 +01001539 // Does this instruction strictly dominate `other_instruction`?
1540 // Returns false if this instruction and `other_instruction` are the same.
1541 // Aborts if this instruction and `other_instruction` are both phis.
1542 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +01001543
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001544 int GetId() const { return id_; }
1545 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001546
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001547 int GetSsaIndex() const { return ssa_index_; }
1548 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
1549 bool HasSsaIndex() const { return ssa_index_ != -1; }
1550
1551 bool HasEnvironment() const { return environment_ != nullptr; }
1552 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001553 // Set the `environment_` field. Raw because this method does not
1554 // update the uses lists.
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001555 void SetRawEnvironment(HEnvironment* environment) {
1556 DCHECK(environment_ == nullptr);
1557 DCHECK_EQ(environment->GetHolder(), this);
1558 environment_ = environment;
1559 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001560
1561 // Set the environment of this instruction, copying it from `environment`. While
1562 // copying, the uses lists are being updated.
1563 void CopyEnvironmentFrom(HEnvironment* environment) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001564 DCHECK(environment_ == nullptr);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001565 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001566 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001567 environment_->CopyFrom(environment);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001568 if (environment->GetParent() != nullptr) {
1569 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1570 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001571 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001572
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001573 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
1574 HBasicBlock* block) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001575 DCHECK(environment_ == nullptr);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001576 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001577 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001578 environment_->CopyFromWithLoopPhiAdjustment(environment, block);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001579 if (environment->GetParent() != nullptr) {
1580 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1581 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001582 }
1583
Nicolas Geoffray39468442014-09-02 15:17:15 +01001584 // Returns the number of entries in the environment. Typically, that is the
1585 // number of dex registers in a method. It could be more in case of inlining.
1586 size_t EnvironmentSize() const;
1587
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001588 LocationSummary* GetLocations() const { return locations_; }
1589 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001590
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001591 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001592 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001593
Alexandre Rames188d4312015-04-09 18:30:21 +01001594 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1595 // uses of this instruction by `other` are *not* updated.
1596 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
1597 ReplaceWith(other);
1598 other->ReplaceInput(this, use_index);
1599 }
1600
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001601 // Move `this` instruction before `cursor`.
1602 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001603
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001604#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +01001605 bool Is##type() const { return (As##type() != nullptr); } \
1606 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001607 virtual H##type* As##type() { return nullptr; }
1608
1609 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
1610#undef INSTRUCTION_TYPE_CHECK
1611
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001612 // Returns whether the instruction can be moved within the graph.
1613 virtual bool CanBeMoved() const { return false; }
1614
1615 // Returns whether the two instructions are of the same kind.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001616 virtual bool InstructionTypeEquals(HInstruction* other) const {
1617 UNUSED(other);
1618 return false;
1619 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001620
1621 // Returns whether any data encoded in the two instructions is equal.
1622 // This method does not look at the inputs. Both instructions must be
1623 // of the same type, otherwise the method has undefined behavior.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001624 virtual bool InstructionDataEquals(HInstruction* other) const {
1625 UNUSED(other);
1626 return false;
1627 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001628
1629 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00001630 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001631 // 2) Their inputs are identical.
1632 bool Equals(HInstruction* other) const;
1633
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001634 virtual InstructionKind GetKind() const = 0;
1635
1636 virtual size_t ComputeHashCode() const {
1637 size_t result = GetKind();
1638 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1639 result = (result * 31) + InputAt(i)->GetId();
1640 }
1641 return result;
1642 }
1643
1644 SideEffects GetSideEffects() const { return side_effects_; }
1645
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001646 size_t GetLifetimePosition() const { return lifetime_position_; }
1647 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
1648 LiveInterval* GetLiveInterval() const { return live_interval_; }
1649 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
1650 bool HasLiveInterval() const { return live_interval_ != nullptr; }
1651
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00001652 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1653
1654 // Returns whether the code generation of the instruction will require to have access
1655 // to the current method. Such instructions are:
1656 // (1): Instructions that require an environment, as calling the runtime requires
1657 // to walk the stack and have the current method stored at a specific stack address.
1658 // (2): Object literals like classes and strings, that are loaded from the dex cache
1659 // fields of the current method.
1660 bool NeedsCurrentMethod() const {
1661 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1662 }
1663
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001664 virtual bool NeedsDexCache() const { return false; }
1665
Mark Mendellc4701932015-04-10 13:18:51 -04001666 // Does this instruction have any use in an environment before
1667 // control flow hits 'other'?
1668 bool HasAnyEnvironmentUseBefore(HInstruction* other);
1669
1670 // Remove all references to environment uses of this instruction.
1671 // The caller must ensure that this is safe to do.
1672 void RemoveEnvironmentUsers();
1673
David Brazdil1abb4192015-02-17 18:33:36 +00001674 protected:
1675 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
1676 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
1677
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001678 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001679 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
1680
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001681 HInstruction* previous_;
1682 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001683 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001684
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001685 // An instruction gets an id when it is added to the graph.
1686 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01001687 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001688 int id_;
1689
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001690 // When doing liveness analysis, instructions that have uses get an SSA index.
1691 int ssa_index_;
1692
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001693 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00001694 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001695
1696 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00001697 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001698
Nicolas Geoffray39468442014-09-02 15:17:15 +01001699 // The environment associated with this instruction. Not null if the instruction
1700 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001701 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001702
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001703 // Set by the code generator.
1704 LocationSummary* locations_;
1705
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001706 // Set by the liveness analysis.
1707 LiveInterval* live_interval_;
1708
1709 // Set by the liveness analysis, this is the position in a linear
1710 // order of blocks where this instruction's live interval start.
1711 size_t lifetime_position_;
1712
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001713 const SideEffects side_effects_;
1714
Calin Juravleacf735c2015-02-12 15:25:22 +00001715 // TODO: for primitive types this should be marked as invalid.
1716 ReferenceTypeInfo reference_type_info_;
1717
David Brazdil1abb4192015-02-17 18:33:36 +00001718 friend class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001719 friend class HBasicBlock;
David Brazdil1abb4192015-02-17 18:33:36 +00001720 friend class HEnvironment;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001721 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001722 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001723
1724 DISALLOW_COPY_AND_ASSIGN(HInstruction);
1725};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001726std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001727
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001728class HInputIterator : public ValueObject {
1729 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001730 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001731
1732 bool Done() const { return index_ == instruction_->InputCount(); }
1733 HInstruction* Current() const { return instruction_->InputAt(index_); }
1734 void Advance() { index_++; }
1735
1736 private:
1737 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001738 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001739
1740 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1741};
1742
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001743class HInstructionIterator : public ValueObject {
1744 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001745 explicit HInstructionIterator(const HInstructionList& instructions)
1746 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001747 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001748 }
1749
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001750 bool Done() const { return instruction_ == nullptr; }
1751 HInstruction* Current() const { return instruction_; }
1752 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001753 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001754 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001755 }
1756
1757 private:
1758 HInstruction* instruction_;
1759 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001760
1761 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001762};
1763
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001764class HBackwardInstructionIterator : public ValueObject {
1765 public:
1766 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1767 : instruction_(instructions.last_instruction_) {
1768 next_ = Done() ? nullptr : instruction_->GetPrevious();
1769 }
1770
1771 bool Done() const { return instruction_ == nullptr; }
1772 HInstruction* Current() const { return instruction_; }
1773 void Advance() {
1774 instruction_ = next_;
1775 next_ = Done() ? nullptr : instruction_->GetPrevious();
1776 }
1777
1778 private:
1779 HInstruction* instruction_;
1780 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001781
1782 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001783};
1784
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001785// An embedded container with N elements of type T. Used (with partial
1786// specialization for N=0) because embedded arrays cannot have size 0.
1787template<typename T, intptr_t N>
1788class EmbeddedArray {
1789 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001790 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001791
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001792 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001793
1794 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001795 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001796 return elements_[i];
1797 }
1798
1799 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001800 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001801 return elements_[i];
1802 }
1803
1804 const T& At(intptr_t i) const {
1805 return (*this)[i];
1806 }
1807
1808 void SetAt(intptr_t i, const T& val) {
1809 (*this)[i] = val;
1810 }
1811
1812 private:
1813 T elements_[N];
1814};
1815
1816template<typename T>
1817class EmbeddedArray<T, 0> {
1818 public:
1819 intptr_t length() const { return 0; }
1820 const T& operator[](intptr_t i) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001821 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001822 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001823 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001824 }
1825 T& operator[](intptr_t i) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001826 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001827 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001828 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001829 }
1830};
1831
1832template<intptr_t N>
1833class HTemplateInstruction: public HInstruction {
1834 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001835 HTemplateInstruction<N>(SideEffects side_effects)
1836 : HInstruction(side_effects), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07001837 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001838
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001839 size_t InputCount() const OVERRIDE { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001840
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001841 protected:
David Brazdil1abb4192015-02-17 18:33:36 +00001842 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; }
1843
1844 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
1845 inputs_[i] = input;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001846 }
1847
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001848 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001849 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001850
1851 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001852};
1853
Dave Allison20dfc792014-06-16 20:44:29 -07001854template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001855class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07001856 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001857 HExpression<N>(Primitive::Type type, SideEffects side_effects)
1858 : HTemplateInstruction<N>(side_effects), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07001859 virtual ~HExpression() {}
1860
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001861 Primitive::Type GetType() const OVERRIDE { return type_; }
Dave Allison20dfc792014-06-16 20:44:29 -07001862
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001863 protected:
1864 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07001865};
1866
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001867// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1868// instruction that branches to the exit block.
1869class HReturnVoid : public HTemplateInstruction<0> {
1870 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001871 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001872
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001873 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001874
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001875 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001876
1877 private:
1878 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1879};
1880
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001881// Represents dex's RETURN opcodes. A HReturn is a control flow
1882// instruction that branches to the exit block.
1883class HReturn : public HTemplateInstruction<1> {
1884 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001885 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001886 SetRawInputAt(0, value);
1887 }
1888
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001889 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001890
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001891 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001892
1893 private:
1894 DISALLOW_COPY_AND_ASSIGN(HReturn);
1895};
1896
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001897// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001898// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001899// exit block.
1900class HExit : public HTemplateInstruction<0> {
1901 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001902 HExit() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001903
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001904 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001905
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001906 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001907
1908 private:
1909 DISALLOW_COPY_AND_ASSIGN(HExit);
1910};
1911
1912// Jumps from one block to another.
1913class HGoto : public HTemplateInstruction<0> {
1914 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001915 HGoto() : HTemplateInstruction(SideEffects::None()) {}
1916
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001917 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001918
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001919 HBasicBlock* GetSuccessor() const {
David Brazdilfc6a86a2015-06-26 10:33:45 +00001920 return GetBlock()->GetSingleSuccessor();
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001921 }
1922
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001923 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001924
1925 private:
1926 DISALLOW_COPY_AND_ASSIGN(HGoto);
1927};
1928
Dave Allison20dfc792014-06-16 20:44:29 -07001929
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001930// Conditional branch. A block ending with an HIf instruction must have
1931// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001932class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001933 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001934 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001935 SetRawInputAt(0, input);
1936 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001937
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001938 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001939
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001940 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001941 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001942 }
1943
1944 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001945 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001946 }
1947
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001948 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001949
1950 private:
1951 DISALLOW_COPY_AND_ASSIGN(HIf);
1952};
1953
David Brazdilfc6a86a2015-06-26 10:33:45 +00001954
1955// Abstract instruction which marks the beginning and/or end of a try block and
1956// links it to the respective exception handlers. Behaves the same as a Goto in
1957// non-exceptional control flow.
1958// Normal-flow successor is stored at index zero, exception handlers under
1959// higher indices in no particular order.
1960class HTryBoundary : public HTemplateInstruction<0> {
1961 public:
David Brazdil56e1acc2015-06-30 15:41:36 +01001962 enum BoundaryKind {
1963 kEntry,
1964 kExit,
1965 };
1966
1967 explicit HTryBoundary(BoundaryKind kind)
1968 : HTemplateInstruction(SideEffects::None()), kind_(kind) {}
David Brazdilfc6a86a2015-06-26 10:33:45 +00001969
1970 bool IsControlFlow() const OVERRIDE { return true; }
1971
1972 // Returns the block's non-exceptional successor (index zero).
1973 HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors().Get(0); }
1974
1975 // Returns whether `handler` is among its exception handlers (non-zero index
1976 // successors).
1977 bool HasExceptionHandler(HBasicBlock* handler) const {
1978 DCHECK(handler->IsCatchBlock());
1979 return GetBlock()->GetSuccessors().Contains(handler, /* start_from */ 1);
1980 }
1981
1982 // Returns whether successor at index `idx` is an exception handler.
1983 bool IsExceptionalSuccessor(size_t idx) const {
1984 DCHECK_LT(idx, GetBlock()->GetSuccessors().Size());
1985 bool is_handler = (idx != 0);
1986 DCHECK(!is_handler || GetBlock()->GetSuccessors().Get(idx)->IsCatchBlock());
1987 return is_handler;
1988 }
1989
1990 // If not present already, adds `handler` to its block's list of exception
1991 // handlers.
1992 void AddExceptionHandler(HBasicBlock* handler) {
1993 if (!HasExceptionHandler(handler)) {
1994 GetBlock()->AddSuccessor(handler);
1995 }
1996 }
1997
David Brazdil56e1acc2015-06-30 15:41:36 +01001998 bool IsEntry() const { return kind_ == BoundaryKind::kEntry; }
David Brazdilfc6a86a2015-06-26 10:33:45 +00001999
2000 DECLARE_INSTRUCTION(TryBoundary);
2001
2002 private:
David Brazdil56e1acc2015-06-30 15:41:36 +01002003 const BoundaryKind kind_;
David Brazdilfc6a86a2015-06-26 10:33:45 +00002004
2005 DISALLOW_COPY_AND_ASSIGN(HTryBoundary);
2006};
2007
2008
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002009// Deoptimize to interpreter, upon checking a condition.
2010class HDeoptimize : public HTemplateInstruction<1> {
2011 public:
2012 HDeoptimize(HInstruction* cond, uint32_t dex_pc)
2013 : HTemplateInstruction(SideEffects::None()),
2014 dex_pc_(dex_pc) {
2015 SetRawInputAt(0, cond);
2016 }
2017
2018 bool NeedsEnvironment() const OVERRIDE { return true; }
2019 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002020 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002021
2022 DECLARE_INSTRUCTION(Deoptimize);
2023
2024 private:
2025 uint32_t dex_pc_;
2026
2027 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
2028};
2029
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002030// Represents the ArtMethod that was passed as a first argument to
2031// the method. It is used by instructions that depend on it, like
2032// instructions that work with the dex cache.
2033class HCurrentMethod : public HExpression<0> {
2034 public:
Mathieu Chartiere401d142015-04-22 13:56:20 -07002035 explicit HCurrentMethod(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01002036
2037 DECLARE_INSTRUCTION(CurrentMethod);
2038
2039 private:
2040 DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
2041};
2042
Roland Levillain88cb1752014-10-20 16:36:47 +01002043class HUnaryOperation : public HExpression<1> {
2044 public:
2045 HUnaryOperation(Primitive::Type result_type, HInstruction* input)
2046 : HExpression(result_type, SideEffects::None()) {
2047 SetRawInputAt(0, input);
2048 }
2049
2050 HInstruction* GetInput() const { return InputAt(0); }
2051 Primitive::Type GetResultType() const { return GetType(); }
2052
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002053 bool CanBeMoved() const OVERRIDE { return true; }
2054 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002055 UNUSED(other);
2056 return true;
2057 }
Roland Levillain88cb1752014-10-20 16:36:47 +01002058
Roland Levillain9240d6a2014-10-20 16:47:04 +01002059 // Try to statically evaluate `operation` and return a HConstant
2060 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002061 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01002062 HConstant* TryStaticEvaluation() const;
2063
2064 // Apply this operation to `x`.
2065 virtual int32_t Evaluate(int32_t x) const = 0;
2066 virtual int64_t Evaluate(int64_t x) const = 0;
2067
Roland Levillain88cb1752014-10-20 16:36:47 +01002068 DECLARE_INSTRUCTION(UnaryOperation);
2069
2070 private:
2071 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
2072};
2073
Dave Allison20dfc792014-06-16 20:44:29 -07002074class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002075 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002076 HBinaryOperation(Primitive::Type result_type,
2077 HInstruction* left,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002078 HInstruction* right) : HExpression(result_type, SideEffects::None()) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002079 SetRawInputAt(0, left);
2080 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002081 }
2082
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002083 HInstruction* GetLeft() const { return InputAt(0); }
2084 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07002085 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002086
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002087 virtual bool IsCommutative() const { return false; }
2088
2089 // Put constant on the right.
2090 // Returns whether order is changed.
2091 bool OrderInputsWithConstantOnTheRight() {
2092 HInstruction* left = InputAt(0);
2093 HInstruction* right = InputAt(1);
2094 if (left->IsConstant() && !right->IsConstant()) {
2095 ReplaceInput(right, 0);
2096 ReplaceInput(left, 1);
2097 return true;
2098 }
2099 return false;
2100 }
2101
2102 // Order inputs by instruction id, but favor constant on the right side.
2103 // This helps GVN for commutative ops.
2104 void OrderInputs() {
2105 DCHECK(IsCommutative());
2106 HInstruction* left = InputAt(0);
2107 HInstruction* right = InputAt(1);
2108 if (left == right || (!left->IsConstant() && right->IsConstant())) {
2109 return;
2110 }
2111 if (OrderInputsWithConstantOnTheRight()) {
2112 return;
2113 }
2114 // Order according to instruction id.
2115 if (left->GetId() > right->GetId()) {
2116 ReplaceInput(right, 0);
2117 ReplaceInput(left, 1);
2118 }
2119 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002120
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002121 bool CanBeMoved() const OVERRIDE { return true; }
2122 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002123 UNUSED(other);
2124 return true;
2125 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002126
Roland Levillain9240d6a2014-10-20 16:47:04 +01002127 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01002128 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002129 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01002130 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01002131
2132 // Apply this operation to `x` and `y`.
2133 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
2134 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
2135
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002136 // Returns an input that can legally be used as the right input and is
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002137 // constant, or null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002138 HConstant* GetConstantRight() const;
2139
2140 // If `GetConstantRight()` returns one of the input, this returns the other
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002141 // one. Otherwise it returns null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002142 HInstruction* GetLeastConstantLeft() const;
2143
Roland Levillainccc07a92014-09-16 14:48:16 +01002144 DECLARE_INSTRUCTION(BinaryOperation);
2145
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002146 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002147 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
2148};
2149
Mark Mendellc4701932015-04-10 13:18:51 -04002150// The comparison bias applies for floating point operations and indicates how NaN
2151// comparisons are treated:
2152enum ComparisonBias {
2153 kNoBias, // bias is not applicable (i.e. for long operation)
2154 kGtBias, // return 1 for NaN comparisons
2155 kLtBias, // return -1 for NaN comparisons
2156};
2157
Dave Allison20dfc792014-06-16 20:44:29 -07002158class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002159 public:
Dave Allison20dfc792014-06-16 20:44:29 -07002160 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002161 : HBinaryOperation(Primitive::kPrimBoolean, first, second),
Mark Mendellc4701932015-04-10 13:18:51 -04002162 needs_materialization_(true),
2163 bias_(kNoBias) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002164
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002165 bool NeedsMaterialization() const { return needs_materialization_; }
2166 void ClearNeedsMaterialization() { needs_materialization_ = false; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002167
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002168 // For code generation purposes, returns whether this instruction is just before
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002169 // `instruction`, and disregard moves in between.
2170 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002171
Dave Allison20dfc792014-06-16 20:44:29 -07002172 DECLARE_INSTRUCTION(Condition);
2173
2174 virtual IfCondition GetCondition() const = 0;
2175
Mark Mendellc4701932015-04-10 13:18:51 -04002176 virtual IfCondition GetOppositeCondition() const = 0;
2177
2178 bool IsGtBias() { return bias_ == kGtBias; }
2179
2180 void SetBias(ComparisonBias bias) { bias_ = bias; }
2181
2182 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2183 return bias_ == other->AsCondition()->bias_;
2184 }
2185
Dave Allison20dfc792014-06-16 20:44:29 -07002186 private:
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002187 // For register allocation purposes, returns whether this instruction needs to be
2188 // materialized (that is, not just be in the processor flags).
2189 bool needs_materialization_;
2190
Mark Mendellc4701932015-04-10 13:18:51 -04002191 // Needed if we merge a HCompare into a HCondition.
2192 ComparisonBias bias_;
2193
Dave Allison20dfc792014-06-16 20:44:29 -07002194 DISALLOW_COPY_AND_ASSIGN(HCondition);
2195};
2196
2197// Instruction to check if two inputs are equal to each other.
2198class HEqual : public HCondition {
2199 public:
2200 HEqual(HInstruction* first, HInstruction* second)
2201 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002202
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002203 bool IsCommutative() const OVERRIDE { return true; }
2204
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002205 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002206 return x == y ? 1 : 0;
2207 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002208 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002209 return x == y ? 1 : 0;
2210 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002211
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002212 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002213
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002214 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002215 return kCondEQ;
2216 }
2217
Mark Mendellc4701932015-04-10 13:18:51 -04002218 IfCondition GetOppositeCondition() const OVERRIDE {
2219 return kCondNE;
2220 }
2221
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002222 private:
2223 DISALLOW_COPY_AND_ASSIGN(HEqual);
2224};
2225
Dave Allison20dfc792014-06-16 20:44:29 -07002226class HNotEqual : public HCondition {
2227 public:
2228 HNotEqual(HInstruction* first, HInstruction* second)
2229 : HCondition(first, second) {}
2230
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002231 bool IsCommutative() const OVERRIDE { return true; }
2232
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002233 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002234 return x != y ? 1 : 0;
2235 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002236 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002237 return x != y ? 1 : 0;
2238 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002239
Dave Allison20dfc792014-06-16 20:44:29 -07002240 DECLARE_INSTRUCTION(NotEqual);
2241
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002242 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002243 return kCondNE;
2244 }
2245
Mark Mendellc4701932015-04-10 13:18:51 -04002246 IfCondition GetOppositeCondition() const OVERRIDE {
2247 return kCondEQ;
2248 }
2249
Dave Allison20dfc792014-06-16 20:44:29 -07002250 private:
2251 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
2252};
2253
2254class HLessThan : public HCondition {
2255 public:
2256 HLessThan(HInstruction* first, HInstruction* second)
2257 : HCondition(first, second) {}
2258
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002259 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002260 return x < y ? 1 : 0;
2261 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002262 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002263 return x < y ? 1 : 0;
2264 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002265
Dave Allison20dfc792014-06-16 20:44:29 -07002266 DECLARE_INSTRUCTION(LessThan);
2267
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002268 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002269 return kCondLT;
2270 }
2271
Mark Mendellc4701932015-04-10 13:18:51 -04002272 IfCondition GetOppositeCondition() const OVERRIDE {
2273 return kCondGE;
2274 }
2275
Dave Allison20dfc792014-06-16 20:44:29 -07002276 private:
2277 DISALLOW_COPY_AND_ASSIGN(HLessThan);
2278};
2279
2280class HLessThanOrEqual : public HCondition {
2281 public:
2282 HLessThanOrEqual(HInstruction* first, HInstruction* second)
2283 : HCondition(first, second) {}
2284
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002285 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002286 return x <= y ? 1 : 0;
2287 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002288 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002289 return x <= y ? 1 : 0;
2290 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002291
Dave Allison20dfc792014-06-16 20:44:29 -07002292 DECLARE_INSTRUCTION(LessThanOrEqual);
2293
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002294 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002295 return kCondLE;
2296 }
2297
Mark Mendellc4701932015-04-10 13:18:51 -04002298 IfCondition GetOppositeCondition() const OVERRIDE {
2299 return kCondGT;
2300 }
2301
Dave Allison20dfc792014-06-16 20:44:29 -07002302 private:
2303 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
2304};
2305
2306class HGreaterThan : public HCondition {
2307 public:
2308 HGreaterThan(HInstruction* first, HInstruction* second)
2309 : HCondition(first, second) {}
2310
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002311 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002312 return x > y ? 1 : 0;
2313 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002314 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002315 return x > y ? 1 : 0;
2316 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002317
Dave Allison20dfc792014-06-16 20:44:29 -07002318 DECLARE_INSTRUCTION(GreaterThan);
2319
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002320 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002321 return kCondGT;
2322 }
2323
Mark Mendellc4701932015-04-10 13:18:51 -04002324 IfCondition GetOppositeCondition() const OVERRIDE {
2325 return kCondLE;
2326 }
2327
Dave Allison20dfc792014-06-16 20:44:29 -07002328 private:
2329 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
2330};
2331
2332class HGreaterThanOrEqual : public HCondition {
2333 public:
2334 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
2335 : HCondition(first, second) {}
2336
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002337 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002338 return x >= y ? 1 : 0;
2339 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002340 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002341 return x >= y ? 1 : 0;
2342 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002343
Dave Allison20dfc792014-06-16 20:44:29 -07002344 DECLARE_INSTRUCTION(GreaterThanOrEqual);
2345
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002346 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002347 return kCondGE;
2348 }
2349
Mark Mendellc4701932015-04-10 13:18:51 -04002350 IfCondition GetOppositeCondition() const OVERRIDE {
2351 return kCondLT;
2352 }
2353
Dave Allison20dfc792014-06-16 20:44:29 -07002354 private:
2355 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
2356};
2357
2358
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002359// Instruction to check how two inputs compare to each other.
2360// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
2361class HCompare : public HBinaryOperation {
2362 public:
Alexey Frunze4dda3372015-06-01 18:31:49 -07002363 HCompare(Primitive::Type type,
2364 HInstruction* first,
2365 HInstruction* second,
Mark Mendellc4701932015-04-10 13:18:51 -04002366 ComparisonBias bias,
Alexey Frunze4dda3372015-06-01 18:31:49 -07002367 uint32_t dex_pc)
2368 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias), dex_pc_(dex_pc) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002369 DCHECK_EQ(type, first->GetType());
2370 DCHECK_EQ(type, second->GetType());
2371 }
2372
Calin Juravleddb7df22014-11-25 20:56:51 +00002373 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002374 return
2375 x == y ? 0 :
2376 x > y ? 1 :
2377 -1;
2378 }
Calin Juravleddb7df22014-11-25 20:56:51 +00002379
2380 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002381 return
2382 x == y ? 0 :
2383 x > y ? 1 :
2384 -1;
2385 }
2386
Calin Juravleddb7df22014-11-25 20:56:51 +00002387 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2388 return bias_ == other->AsCompare()->bias_;
2389 }
2390
Mark Mendellc4701932015-04-10 13:18:51 -04002391 ComparisonBias GetBias() const { return bias_; }
2392
Calin Juravleddb7df22014-11-25 20:56:51 +00002393 bool IsGtBias() { return bias_ == kGtBias; }
2394
Alexey Frunze4dda3372015-06-01 18:31:49 -07002395 uint32_t GetDexPc() const { return dex_pc_; }
2396
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002397 DECLARE_INSTRUCTION(Compare);
2398
2399 private:
Mark Mendellc4701932015-04-10 13:18:51 -04002400 const ComparisonBias bias_;
Alexey Frunze4dda3372015-06-01 18:31:49 -07002401 const uint32_t dex_pc_;
Calin Juravleddb7df22014-11-25 20:56:51 +00002402
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002403 DISALLOW_COPY_AND_ASSIGN(HCompare);
2404};
2405
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002406// A local in the graph. Corresponds to a Dex register.
2407class HLocal : public HTemplateInstruction<0> {
2408 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002409 explicit HLocal(uint16_t reg_number)
2410 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002411
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002412 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002413
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002414 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002415
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002416 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002417 // The Dex register number.
2418 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002419
2420 DISALLOW_COPY_AND_ASSIGN(HLocal);
2421};
2422
2423// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07002424class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002425 public:
Roland Levillain5799fc02014-09-25 12:15:20 +01002426 HLoadLocal(HLocal* local, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002427 : HExpression(type, SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002428 SetRawInputAt(0, local);
2429 }
2430
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002431 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2432
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002433 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002434
2435 private:
2436 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
2437};
2438
2439// Store a value in a given local. This instruction has two inputs: the value
2440// and the local.
2441class HStoreLocal : public HTemplateInstruction<2> {
2442 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002443 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002444 SetRawInputAt(0, local);
2445 SetRawInputAt(1, value);
2446 }
2447
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002448 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2449
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002450 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002451
2452 private:
2453 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
2454};
2455
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002456class HConstant : public HExpression<0> {
2457 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002458 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
2459
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002460 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002461
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002462 virtual bool IsMinusOne() const { return false; }
2463 virtual bool IsZero() const { return false; }
2464 virtual bool IsOne() const { return false; }
2465
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002466 DECLARE_INSTRUCTION(Constant);
2467
2468 private:
2469 DISALLOW_COPY_AND_ASSIGN(HConstant);
2470};
2471
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002472class HFloatConstant : public HConstant {
2473 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002474 float GetValue() const { return value_; }
2475
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002476 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002477 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
2478 bit_cast<uint32_t, float>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002479 }
2480
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002481 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002482
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002483 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002484 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002485 }
2486 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002487 return value_ == 0.0f;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002488 }
2489 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002490 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
2491 }
2492 bool IsNaN() const {
2493 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002494 }
2495
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002496 DECLARE_INSTRUCTION(FloatConstant);
2497
2498 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002499 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002500 explicit HFloatConstant(int32_t value)
2501 : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002502
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002503 const float value_;
2504
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002505 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002506 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002507 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002508 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2509};
2510
2511class HDoubleConstant : public HConstant {
2512 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002513 double GetValue() const { return value_; }
2514
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002515 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002516 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
2517 bit_cast<uint64_t, double>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002518 }
2519
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002520 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002521
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002522 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002523 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002524 }
2525 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002526 return value_ == 0.0;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002527 }
2528 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002529 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
2530 }
2531 bool IsNaN() const {
2532 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002533 }
2534
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002535 DECLARE_INSTRUCTION(DoubleConstant);
2536
2537 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002538 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002539 explicit HDoubleConstant(int64_t value)
2540 : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002541
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002542 const double value_;
2543
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002544 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002545 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002546 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002547 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2548};
2549
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002550class HNullConstant : public HConstant {
2551 public:
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002552 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2553 return true;
2554 }
2555
2556 size_t ComputeHashCode() const OVERRIDE { return 0; }
2557
2558 DECLARE_INSTRUCTION(NullConstant);
2559
2560 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002561 HNullConstant() : HConstant(Primitive::kPrimNot) {}
2562
2563 friend class HGraph;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002564 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2565};
2566
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002567// Constants of the type int. Those can be from Dex instructions, or
2568// synthesized (for example with the if-eqz instruction).
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002569class HIntConstant : public HConstant {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002570 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002571 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002572
Calin Juravle61d544b2015-02-23 16:46:57 +00002573 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002574 return other->AsIntConstant()->value_ == value_;
2575 }
2576
Calin Juravle61d544b2015-02-23 16:46:57 +00002577 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2578
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002579 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2580 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2581 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2582
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002583 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002584
2585 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002586 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
2587
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002588 const int32_t value_;
2589
David Brazdil8d5b8b22015-03-24 10:51:52 +00002590 friend class HGraph;
2591 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
Zheng Xuad4450e2015-04-17 18:48:56 +08002592 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002593 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2594};
2595
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002596class HLongConstant : public HConstant {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002597 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002598 int64_t GetValue() const { return value_; }
2599
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002600 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002601 return other->AsLongConstant()->value_ == value_;
2602 }
2603
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002604 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002605
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002606 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2607 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2608 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2609
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002610 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002611
2612 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002613 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
2614
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002615 const int64_t value_;
2616
David Brazdil8d5b8b22015-03-24 10:51:52 +00002617 friend class HGraph;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002618 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2619};
2620
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002621enum class Intrinsics {
2622#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
2623#include "intrinsics_list.h"
2624 kNone,
2625 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
2626#undef INTRINSICS_LIST
2627#undef OPTIMIZING_INTRINSICS
2628};
2629std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
2630
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002631class HInvoke : public HInstruction {
2632 public:
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002633 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002634
2635 // Runtime needs to walk the stack, so Dex -> Dex calls need to
2636 // know their environment.
Calin Juravle77520bc2015-01-12 18:45:46 +00002637 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002638
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01002639 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002640 SetRawInputAt(index, argument);
2641 }
2642
Roland Levillain3e3d7332015-04-28 11:00:54 +01002643 // Return the number of arguments. This number can be lower than
2644 // the number of inputs returned by InputCount(), as some invoke
2645 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
2646 // inputs at the end of their list of inputs.
2647 uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
2648
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002649 Primitive::Type GetType() const OVERRIDE { return return_type_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002650
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002651 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002652
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002653 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002654 const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002655
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002656 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
2657
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01002658 Intrinsics GetIntrinsic() const {
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002659 return intrinsic_;
2660 }
2661
2662 void SetIntrinsic(Intrinsics intrinsic) {
2663 intrinsic_ = intrinsic;
2664 }
2665
Nicolas Geoffray78f4fa72015-06-12 09:35:05 +01002666 bool IsFromInlinedInvoke() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01002667 return GetEnvironment()->GetParent() != nullptr;
2668 }
2669
2670 bool CanThrow() const OVERRIDE { return true; }
2671
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002672 DECLARE_INSTRUCTION(Invoke);
2673
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002674 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002675 HInvoke(ArenaAllocator* arena,
2676 uint32_t number_of_arguments,
Roland Levillain3e3d7332015-04-28 11:00:54 +01002677 uint32_t number_of_other_inputs,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002678 Primitive::Type return_type,
2679 uint32_t dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002680 uint32_t dex_method_index,
2681 InvokeType original_invoke_type)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002682 : HInstruction(SideEffects::All()),
Roland Levillain3e3d7332015-04-28 11:00:54 +01002683 number_of_arguments_(number_of_arguments),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002684 inputs_(arena, number_of_arguments),
2685 return_type_(return_type),
2686 dex_pc_(dex_pc),
2687 dex_method_index_(dex_method_index),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002688 original_invoke_type_(original_invoke_type),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002689 intrinsic_(Intrinsics::kNone) {
Roland Levillain3e3d7332015-04-28 11:00:54 +01002690 uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
2691 inputs_.SetSize(number_of_inputs);
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002692 }
2693
David Brazdil1abb4192015-02-17 18:33:36 +00002694 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
2695 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2696 inputs_.Put(index, input);
2697 }
2698
Roland Levillain3e3d7332015-04-28 11:00:54 +01002699 uint32_t number_of_arguments_;
David Brazdil1abb4192015-02-17 18:33:36 +00002700 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002701 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002702 const uint32_t dex_pc_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002703 const uint32_t dex_method_index_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002704 const InvokeType original_invoke_type_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002705 Intrinsics intrinsic_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002706
2707 private:
2708 DISALLOW_COPY_AND_ASSIGN(HInvoke);
2709};
2710
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002711class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002712 public:
Roland Levillain4c0eb422015-04-24 16:43:49 +01002713 // Requirements of this method call regarding the class
2714 // initialization (clinit) check of its declaring class.
2715 enum class ClinitCheckRequirement {
2716 kNone, // Class already initialized.
2717 kExplicit, // Static call having explicit clinit check as last input.
2718 kImplicit, // Static call implicitly requiring a clinit check.
2719 };
2720
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002721 HInvokeStaticOrDirect(ArenaAllocator* arena,
2722 uint32_t number_of_arguments,
2723 Primitive::Type return_type,
2724 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002725 uint32_t dex_method_index,
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002726 bool is_recursive,
Jeff Hao848f70a2014-01-15 13:49:50 -08002727 int32_t string_init_offset,
Nicolas Geoffray79041292015-03-26 10:05:54 +00002728 InvokeType original_invoke_type,
Roland Levillain4c0eb422015-04-24 16:43:49 +01002729 InvokeType invoke_type,
2730 ClinitCheckRequirement clinit_check_requirement)
Roland Levillain3e3d7332015-04-28 11:00:54 +01002731 : HInvoke(arena,
2732 number_of_arguments,
Nicolas Geoffray38207af2015-06-01 15:46:22 +01002733 // There is one extra argument for the HCurrentMethod node, and
2734 // potentially one other if the clinit check is explicit.
2735 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 2u : 1u,
Roland Levillain3e3d7332015-04-28 11:00:54 +01002736 return_type,
2737 dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002738 dex_method_index,
2739 original_invoke_type),
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002740 invoke_type_(invoke_type),
Roland Levillain4c0eb422015-04-24 16:43:49 +01002741 is_recursive_(is_recursive),
Jeff Hao848f70a2014-01-15 13:49:50 -08002742 clinit_check_requirement_(clinit_check_requirement),
2743 string_init_offset_(string_init_offset) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002744
Calin Juravle641547a2015-04-21 22:08:51 +01002745 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2746 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00002747 // We access the method via the dex cache so we can't do an implicit null check.
2748 // TODO: for intrinsics we can generate implicit null checks.
2749 return false;
2750 }
2751
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002752 InvokeType GetInvokeType() const { return invoke_type_; }
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002753 bool IsRecursive() const { return is_recursive_; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002754 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
Jeff Hao848f70a2014-01-15 13:49:50 -08002755 bool IsStringInit() const { return string_init_offset_ != 0; }
2756 int32_t GetStringInitOffset() const { return string_init_offset_; }
Nicolas Geoffray38207af2015-06-01 15:46:22 +01002757 uint32_t GetCurrentMethodInputIndex() const { return GetNumberOfArguments(); }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002758
Roland Levillain4c0eb422015-04-24 16:43:49 +01002759 // Is this instruction a call to a static method?
2760 bool IsStatic() const {
2761 return GetInvokeType() == kStatic;
2762 }
2763
Roland Levillain3e3d7332015-04-28 11:00:54 +01002764 // Remove the art::HLoadClass instruction set as last input by
2765 // art::PrepareForRegisterAllocation::VisitClinitCheck in lieu of
2766 // the initial art::HClinitCheck instruction (only relevant for
2767 // static calls with explicit clinit check).
2768 void RemoveLoadClassAsLastInput() {
Roland Levillain4c0eb422015-04-24 16:43:49 +01002769 DCHECK(IsStaticWithExplicitClinitCheck());
2770 size_t last_input_index = InputCount() - 1;
2771 HInstruction* last_input = InputAt(last_input_index);
2772 DCHECK(last_input != nullptr);
Roland Levillain3e3d7332015-04-28 11:00:54 +01002773 DCHECK(last_input->IsLoadClass()) << last_input->DebugName();
Roland Levillain4c0eb422015-04-24 16:43:49 +01002774 RemoveAsUserOfInput(last_input_index);
2775 inputs_.DeleteAt(last_input_index);
2776 clinit_check_requirement_ = ClinitCheckRequirement::kImplicit;
2777 DCHECK(IsStaticWithImplicitClinitCheck());
2778 }
2779
2780 // Is this a call to a static method whose declaring class has an
2781 // explicit intialization check in the graph?
2782 bool IsStaticWithExplicitClinitCheck() const {
2783 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit);
2784 }
2785
2786 // Is this a call to a static method whose declaring class has an
2787 // implicit intialization check requirement?
2788 bool IsStaticWithImplicitClinitCheck() const {
2789 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit);
2790 }
2791
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002792 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002793
Roland Levillain4c0eb422015-04-24 16:43:49 +01002794 protected:
2795 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
2796 const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i);
2797 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) {
2798 HInstruction* input = input_record.GetInstruction();
2799 // `input` is the last input of a static invoke marked as having
2800 // an explicit clinit check. It must either be:
2801 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
2802 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
2803 DCHECK(input != nullptr);
2804 DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName();
2805 }
2806 return input_record;
2807 }
2808
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002809 private:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002810 const InvokeType invoke_type_;
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002811 const bool is_recursive_;
Roland Levillain4c0eb422015-04-24 16:43:49 +01002812 ClinitCheckRequirement clinit_check_requirement_;
Jeff Hao848f70a2014-01-15 13:49:50 -08002813 // Thread entrypoint offset for string init method if this is a string init invoke.
2814 // Note that there are multiple string init methods, each having its own offset.
2815 int32_t string_init_offset_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002816
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002817 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002818};
2819
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002820class HInvokeVirtual : public HInvoke {
2821 public:
2822 HInvokeVirtual(ArenaAllocator* arena,
2823 uint32_t number_of_arguments,
2824 Primitive::Type return_type,
2825 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002826 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002827 uint32_t vtable_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002828 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kVirtual),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002829 vtable_index_(vtable_index) {}
2830
Calin Juravle641547a2015-04-21 22:08:51 +01002831 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002832 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002833 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002834 }
2835
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002836 uint32_t GetVTableIndex() const { return vtable_index_; }
2837
2838 DECLARE_INSTRUCTION(InvokeVirtual);
2839
2840 private:
2841 const uint32_t vtable_index_;
2842
2843 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
2844};
2845
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002846class HInvokeInterface : public HInvoke {
2847 public:
2848 HInvokeInterface(ArenaAllocator* arena,
2849 uint32_t number_of_arguments,
2850 Primitive::Type return_type,
2851 uint32_t dex_pc,
2852 uint32_t dex_method_index,
2853 uint32_t imt_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002854 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kInterface),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002855 imt_index_(imt_index) {}
2856
Calin Juravle641547a2015-04-21 22:08:51 +01002857 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002858 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002859 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002860 }
2861
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002862 uint32_t GetImtIndex() const { return imt_index_; }
2863 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2864
2865 DECLARE_INSTRUCTION(InvokeInterface);
2866
2867 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002868 const uint32_t imt_index_;
2869
2870 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
2871};
2872
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002873class HNewInstance : public HExpression<1> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002874 public:
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002875 HNewInstance(HCurrentMethod* current_method,
2876 uint32_t dex_pc,
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002877 uint16_t type_index,
2878 const DexFile& dex_file,
2879 QuickEntrypointEnum entrypoint)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002880 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2881 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002882 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002883 dex_file_(dex_file),
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002884 entrypoint_(entrypoint) {
2885 SetRawInputAt(0, current_method);
2886 }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002887
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002888 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002889 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002890 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002891
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002892 // Calls runtime so needs an environment.
Calin Juravle92a6ed22014-12-02 18:58:03 +00002893 bool NeedsEnvironment() const OVERRIDE { return true; }
2894 // It may throw when called on:
2895 // - interfaces
2896 // - abstract/innaccessible/unknown classes
2897 // TODO: optimize when possible.
2898 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002899
Calin Juravle10e244f2015-01-26 18:54:32 +00002900 bool CanBeNull() const OVERRIDE { return false; }
2901
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002902 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2903
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002904 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002905
2906 private:
2907 const uint32_t dex_pc_;
2908 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002909 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002910 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002911
2912 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
2913};
2914
Roland Levillain88cb1752014-10-20 16:36:47 +01002915class HNeg : public HUnaryOperation {
2916 public:
2917 explicit HNeg(Primitive::Type result_type, HInstruction* input)
2918 : HUnaryOperation(result_type, input) {}
2919
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002920 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
2921 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
Roland Levillain9240d6a2014-10-20 16:47:04 +01002922
Roland Levillain88cb1752014-10-20 16:36:47 +01002923 DECLARE_INSTRUCTION(Neg);
2924
2925 private:
2926 DISALLOW_COPY_AND_ASSIGN(HNeg);
2927};
2928
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002929class HNewArray : public HExpression<2> {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002930 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002931 HNewArray(HInstruction* length,
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002932 HCurrentMethod* current_method,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002933 uint32_t dex_pc,
2934 uint16_t type_index,
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002935 const DexFile& dex_file,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002936 QuickEntrypointEnum entrypoint)
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002937 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2938 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002939 type_index_(type_index),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002940 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002941 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002942 SetRawInputAt(0, length);
Nicolas Geoffray69aa6012015-06-09 10:34:25 +01002943 SetRawInputAt(1, current_method);
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002944 }
2945
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002946 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002947 uint16_t GetTypeIndex() const { return type_index_; }
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002948 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002949
2950 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00002951 bool NeedsEnvironment() const OVERRIDE { return true; }
2952
Mingyao Yang0c365e62015-03-31 15:09:29 -07002953 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
2954 bool CanThrow() const OVERRIDE { return true; }
2955
Calin Juravle10e244f2015-01-26 18:54:32 +00002956 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002957
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002958 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2959
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002960 DECLARE_INSTRUCTION(NewArray);
2961
2962 private:
2963 const uint32_t dex_pc_;
2964 const uint16_t type_index_;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002965 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002966 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002967
2968 DISALLOW_COPY_AND_ASSIGN(HNewArray);
2969};
2970
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002971class HAdd : public HBinaryOperation {
2972 public:
2973 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2974 : HBinaryOperation(result_type, left, right) {}
2975
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002976 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002977
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002978 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002979 return x + y;
2980 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002981 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002982 return x + y;
2983 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002984
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002985 DECLARE_INSTRUCTION(Add);
2986
2987 private:
2988 DISALLOW_COPY_AND_ASSIGN(HAdd);
2989};
2990
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002991class HSub : public HBinaryOperation {
2992 public:
2993 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2994 : HBinaryOperation(result_type, left, right) {}
2995
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002996 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002997 return x - y;
2998 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002999 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01003000 return x - y;
3001 }
Roland Levillain556c3d12014-09-18 15:25:07 +01003002
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003003 DECLARE_INSTRUCTION(Sub);
3004
3005 private:
3006 DISALLOW_COPY_AND_ASSIGN(HSub);
3007};
3008
Calin Juravle34bacdf2014-10-07 20:23:36 +01003009class HMul : public HBinaryOperation {
3010 public:
3011 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3012 : HBinaryOperation(result_type, left, right) {}
3013
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003014 bool IsCommutative() const OVERRIDE { return true; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01003015
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003016 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
3017 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01003018
3019 DECLARE_INSTRUCTION(Mul);
3020
3021 private:
3022 DISALLOW_COPY_AND_ASSIGN(HMul);
3023};
3024
Calin Juravle7c4954d2014-10-28 16:57:40 +00003025class HDiv : public HBinaryOperation {
3026 public:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00003027 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
3028 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00003029
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003030 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00003031 // Our graph structure ensures we never have 0 for `y` during constant folding.
3032 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00003033 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00003034 return (y == -1) ? -x : x / y;
3035 }
Calin Juravlebacfec32014-11-14 15:54:36 +00003036
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003037 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00003038 DCHECK_NE(y, 0);
3039 // Special case -1 to avoid getting a SIGFPE on x86(_64).
3040 return (y == -1) ? -x : x / y;
3041 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00003042
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003043 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled6fb6cf2014-11-11 19:07:44 +00003044
Calin Juravle7c4954d2014-10-28 16:57:40 +00003045 DECLARE_INSTRUCTION(Div);
3046
3047 private:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00003048 const uint32_t dex_pc_;
3049
Calin Juravle7c4954d2014-10-28 16:57:40 +00003050 DISALLOW_COPY_AND_ASSIGN(HDiv);
3051};
3052
Calin Juravlebacfec32014-11-14 15:54:36 +00003053class HRem : public HBinaryOperation {
3054 public:
3055 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
3056 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
3057
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003058 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00003059 DCHECK_NE(y, 0);
3060 // Special case -1 to avoid getting a SIGFPE on x86(_64).
3061 return (y == -1) ? 0 : x % y;
3062 }
3063
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003064 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00003065 DCHECK_NE(y, 0);
3066 // Special case -1 to avoid getting a SIGFPE on x86(_64).
3067 return (y == -1) ? 0 : x % y;
3068 }
3069
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003070 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravlebacfec32014-11-14 15:54:36 +00003071
3072 DECLARE_INSTRUCTION(Rem);
3073
3074 private:
3075 const uint32_t dex_pc_;
3076
3077 DISALLOW_COPY_AND_ASSIGN(HRem);
3078};
3079
Calin Juravled0d48522014-11-04 16:40:20 +00003080class HDivZeroCheck : public HExpression<1> {
3081 public:
3082 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
3083 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
3084 SetRawInputAt(0, value);
3085 }
3086
3087 bool CanBeMoved() const OVERRIDE { return true; }
3088
3089 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3090 UNUSED(other);
3091 return true;
3092 }
3093
3094 bool NeedsEnvironment() const OVERRIDE { return true; }
3095 bool CanThrow() const OVERRIDE { return true; }
3096
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003097 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled0d48522014-11-04 16:40:20 +00003098
3099 DECLARE_INSTRUCTION(DivZeroCheck);
3100
3101 private:
3102 const uint32_t dex_pc_;
3103
3104 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
3105};
3106
Calin Juravle9aec02f2014-11-18 23:06:35 +00003107class HShl : public HBinaryOperation {
3108 public:
3109 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3110 : HBinaryOperation(result_type, left, right) {}
3111
3112 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
3113 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
3114
3115 DECLARE_INSTRUCTION(Shl);
3116
3117 private:
3118 DISALLOW_COPY_AND_ASSIGN(HShl);
3119};
3120
3121class HShr : public HBinaryOperation {
3122 public:
3123 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3124 : HBinaryOperation(result_type, left, right) {}
3125
3126 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
3127 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
3128
3129 DECLARE_INSTRUCTION(Shr);
3130
3131 private:
3132 DISALLOW_COPY_AND_ASSIGN(HShr);
3133};
3134
3135class HUShr : public HBinaryOperation {
3136 public:
3137 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3138 : HBinaryOperation(result_type, left, right) {}
3139
3140 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
3141 uint32_t ux = static_cast<uint32_t>(x);
3142 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
3143 return static_cast<int32_t>(ux >> uy);
3144 }
3145
3146 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
3147 uint64_t ux = static_cast<uint64_t>(x);
3148 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
3149 return static_cast<int64_t>(ux >> uy);
3150 }
3151
3152 DECLARE_INSTRUCTION(UShr);
3153
3154 private:
3155 DISALLOW_COPY_AND_ASSIGN(HUShr);
3156};
3157
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00003158class HAnd : public HBinaryOperation {
3159 public:
3160 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3161 : HBinaryOperation(result_type, left, right) {}
3162
Mingyao Yangdc5ac732015-02-25 11:28:05 -08003163 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00003164
3165 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
3166 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
3167
3168 DECLARE_INSTRUCTION(And);
3169
3170 private:
3171 DISALLOW_COPY_AND_ASSIGN(HAnd);
3172};
3173
3174class HOr : public HBinaryOperation {
3175 public:
3176 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3177 : HBinaryOperation(result_type, left, right) {}
3178
Mingyao Yangdc5ac732015-02-25 11:28:05 -08003179 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00003180
3181 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
3182 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
3183
3184 DECLARE_INSTRUCTION(Or);
3185
3186 private:
3187 DISALLOW_COPY_AND_ASSIGN(HOr);
3188};
3189
3190class HXor : public HBinaryOperation {
3191 public:
3192 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
3193 : HBinaryOperation(result_type, left, right) {}
3194
Mingyao Yangdc5ac732015-02-25 11:28:05 -08003195 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00003196
3197 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
3198 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
3199
3200 DECLARE_INSTRUCTION(Xor);
3201
3202 private:
3203 DISALLOW_COPY_AND_ASSIGN(HXor);
3204};
3205
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003206// The value of a parameter in this method. Its location depends on
3207// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07003208class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003209 public:
Calin Juravle10e244f2015-01-26 18:54:32 +00003210 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
3211 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003212
3213 uint8_t GetIndex() const { return index_; }
3214
Calin Juravle10e244f2015-01-26 18:54:32 +00003215 bool CanBeNull() const OVERRIDE { return !is_this_; }
3216
Calin Juravle3cd4fc82015-05-14 15:15:42 +01003217 bool IsThis() const { return is_this_; }
3218
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003219 DECLARE_INSTRUCTION(ParameterValue);
3220
3221 private:
3222 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00003223 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003224 const uint8_t index_;
3225
Calin Juravle10e244f2015-01-26 18:54:32 +00003226 // Whether or not the parameter value corresponds to 'this' argument.
3227 const bool is_this_;
3228
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003229 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
3230};
3231
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003232class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003233 public:
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003234 explicit HNot(Primitive::Type result_type, HInstruction* input)
3235 : HUnaryOperation(result_type, input) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003236
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003237 bool CanBeMoved() const OVERRIDE { return true; }
3238 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003239 UNUSED(other);
3240 return true;
3241 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003242
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003243 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
3244 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003245
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003246 DECLARE_INSTRUCTION(Not);
3247
3248 private:
3249 DISALLOW_COPY_AND_ASSIGN(HNot);
3250};
3251
David Brazdil66d126e2015-04-03 16:02:44 +01003252class HBooleanNot : public HUnaryOperation {
3253 public:
3254 explicit HBooleanNot(HInstruction* input)
3255 : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
3256
3257 bool CanBeMoved() const OVERRIDE { return true; }
3258 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3259 UNUSED(other);
3260 return true;
3261 }
3262
3263 int32_t Evaluate(int32_t x) const OVERRIDE {
3264 DCHECK(IsUint<1>(x));
3265 return !x;
3266 }
3267
3268 int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
3269 LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
3270 UNREACHABLE();
3271 }
3272
3273 DECLARE_INSTRUCTION(BooleanNot);
3274
3275 private:
3276 DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
3277};
3278
Roland Levillaindff1f282014-11-05 14:15:05 +00003279class HTypeConversion : public HExpression<1> {
3280 public:
3281 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00003282 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
3283 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00003284 SetRawInputAt(0, input);
3285 DCHECK_NE(input->GetType(), result_type);
3286 }
3287
3288 HInstruction* GetInput() const { return InputAt(0); }
3289 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
3290 Primitive::Type GetResultType() const { return GetType(); }
3291
Roland Levillain624279f2014-12-04 11:54:28 +00003292 // Required by the x86 and ARM code generators when producing calls
3293 // to the runtime.
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003294 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Roland Levillain624279f2014-12-04 11:54:28 +00003295
Roland Levillaindff1f282014-11-05 14:15:05 +00003296 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00003297 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00003298
Mark Mendelle82549b2015-05-06 10:55:34 -04003299 // Try to statically evaluate the conversion and return a HConstant
3300 // containing the result. If the input cannot be converted, return nullptr.
3301 HConstant* TryStaticEvaluation() const;
3302
Roland Levillaindff1f282014-11-05 14:15:05 +00003303 DECLARE_INSTRUCTION(TypeConversion);
3304
3305 private:
Roland Levillain624279f2014-12-04 11:54:28 +00003306 const uint32_t dex_pc_;
3307
Roland Levillaindff1f282014-11-05 14:15:05 +00003308 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
3309};
3310
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00003311static constexpr uint32_t kNoRegNumber = -1;
3312
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003313class HPhi : public HInstruction {
3314 public:
3315 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003316 : HInstruction(SideEffects::None()),
3317 inputs_(arena, number_of_inputs),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003318 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003319 type_(type),
Calin Juravle10e244f2015-01-26 18:54:32 +00003320 is_live_(false),
3321 can_be_null_(true) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003322 inputs_.SetSize(number_of_inputs);
3323 }
3324
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +00003325 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
3326 static Primitive::Type ToPhiType(Primitive::Type type) {
3327 switch (type) {
3328 case Primitive::kPrimBoolean:
3329 case Primitive::kPrimByte:
3330 case Primitive::kPrimShort:
3331 case Primitive::kPrimChar:
3332 return Primitive::kPrimInt;
3333 default:
3334 return type;
3335 }
3336 }
3337
Calin Juravle10e244f2015-01-26 18:54:32 +00003338 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003339
3340 void AddInput(HInstruction* input);
David Brazdil2d7352b2015-04-20 14:52:42 +01003341 void RemoveInputAt(size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003342
Calin Juravle10e244f2015-01-26 18:54:32 +00003343 Primitive::Type GetType() const OVERRIDE { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003344 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003345
Calin Juravle10e244f2015-01-26 18:54:32 +00003346 bool CanBeNull() const OVERRIDE { return can_be_null_; }
3347 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
3348
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003349 uint32_t GetRegNumber() const { return reg_number_; }
3350
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003351 void SetDead() { is_live_ = false; }
3352 void SetLive() { is_live_ = true; }
3353 bool IsDead() const { return !is_live_; }
3354 bool IsLive() const { return is_live_; }
3355
Calin Juravlea4f88312015-04-16 12:57:19 +01003356 // Returns the next equivalent phi (starting from the current one) or null if there is none.
3357 // An equivalent phi is a phi having the same dex register and type.
3358 // It assumes that phis with the same dex register are adjacent.
3359 HPhi* GetNextEquivalentPhiWithSameType() {
3360 HInstruction* next = GetNext();
3361 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
3362 if (next->GetType() == GetType()) {
3363 return next->AsPhi();
3364 }
3365 next = next->GetNext();
3366 }
3367 return nullptr;
3368 }
3369
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003370 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003371
David Brazdil1abb4192015-02-17 18:33:36 +00003372 protected:
3373 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
3374
3375 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
3376 inputs_.Put(index, input);
3377 }
3378
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01003379 private:
David Brazdil1abb4192015-02-17 18:33:36 +00003380 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003381 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003382 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003383 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00003384 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003385
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003386 DISALLOW_COPY_AND_ASSIGN(HPhi);
3387};
3388
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003389class HNullCheck : public HExpression<1> {
3390 public:
3391 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003392 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003393 SetRawInputAt(0, value);
3394 }
3395
Calin Juravle10e244f2015-01-26 18:54:32 +00003396 bool CanBeMoved() const OVERRIDE { return true; }
3397 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003398 UNUSED(other);
3399 return true;
3400 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003401
Calin Juravle10e244f2015-01-26 18:54:32 +00003402 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003403
Calin Juravle10e244f2015-01-26 18:54:32 +00003404 bool CanThrow() const OVERRIDE { return true; }
3405
3406 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003407
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003408 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003409
3410 DECLARE_INSTRUCTION(NullCheck);
3411
3412 private:
3413 const uint32_t dex_pc_;
3414
3415 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
3416};
3417
3418class FieldInfo : public ValueObject {
3419 public:
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003420 FieldInfo(MemberOffset field_offset,
3421 Primitive::Type field_type,
3422 bool is_volatile,
3423 uint32_t index,
3424 const DexFile& dex_file)
3425 : field_offset_(field_offset),
3426 field_type_(field_type),
3427 is_volatile_(is_volatile),
3428 index_(index),
3429 dex_file_(dex_file) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003430
3431 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003432 Primitive::Type GetFieldType() const { return field_type_; }
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003433 uint32_t GetFieldIndex() const { return index_; }
3434 const DexFile& GetDexFile() const { return dex_file_; }
Calin Juravle52c48962014-12-16 17:02:57 +00003435 bool IsVolatile() const { return is_volatile_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003436
3437 private:
3438 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01003439 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00003440 const bool is_volatile_;
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003441 uint32_t index_;
3442 const DexFile& dex_file_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003443};
3444
3445class HInstanceFieldGet : public HExpression<1> {
3446 public:
3447 HInstanceFieldGet(HInstruction* value,
3448 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003449 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003450 bool is_volatile,
3451 uint32_t field_idx,
3452 const DexFile& dex_file)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003453 : HExpression(field_type, SideEffects::DependsOnSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003454 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003455 SetRawInputAt(0, value);
3456 }
3457
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003458 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003459
3460 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3461 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
3462 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003463 }
3464
Calin Juravle641547a2015-04-21 22:08:51 +01003465 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3466 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003467 }
3468
3469 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01003470 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3471 }
3472
Calin Juravle52c48962014-12-16 17:02:57 +00003473 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003474 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003475 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003476 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003477
3478 DECLARE_INSTRUCTION(InstanceFieldGet);
3479
3480 private:
3481 const FieldInfo field_info_;
3482
3483 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
3484};
3485
3486class HInstanceFieldSet : public HTemplateInstruction<2> {
3487 public:
3488 HInstanceFieldSet(HInstruction* object,
3489 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01003490 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003491 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003492 bool is_volatile,
3493 uint32_t field_idx,
3494 const DexFile& dex_file)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003495 : HTemplateInstruction(SideEffects::ChangesSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003496 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003497 value_can_be_null_(true) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003498 SetRawInputAt(0, object);
3499 SetRawInputAt(1, value);
3500 }
3501
Calin Juravle641547a2015-04-21 22:08:51 +01003502 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3503 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003504 }
3505
Calin Juravle52c48962014-12-16 17:02:57 +00003506 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003507 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003508 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003509 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003510 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003511 bool GetValueCanBeNull() const { return value_can_be_null_; }
3512 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003513
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003514 DECLARE_INSTRUCTION(InstanceFieldSet);
3515
3516 private:
3517 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003518 bool value_can_be_null_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003519
3520 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
3521};
3522
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003523class HArrayGet : public HExpression<2> {
3524 public:
3525 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003526 : HExpression(type, SideEffects::DependsOnSomething()) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003527 SetRawInputAt(0, array);
3528 SetRawInputAt(1, index);
3529 }
3530
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003531 bool CanBeMoved() const OVERRIDE { return true; }
3532 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003533 UNUSED(other);
3534 return true;
3535 }
Calin Juravle641547a2015-04-21 22:08:51 +01003536 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3537 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003538 // TODO: We can be smarter here.
3539 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
3540 // which generates the implicit null check. There are cases when these can be removed
3541 // to produce better code. If we ever add optimizations to do so we should allow an
3542 // implicit check here (as long as the address falls in the first page).
3543 return false;
3544 }
3545
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003546 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003547
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003548 HInstruction* GetArray() const { return InputAt(0); }
3549 HInstruction* GetIndex() const { return InputAt(1); }
3550
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003551 DECLARE_INSTRUCTION(ArrayGet);
3552
3553 private:
3554 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
3555};
3556
3557class HArraySet : public HTemplateInstruction<3> {
3558 public:
3559 HArraySet(HInstruction* array,
3560 HInstruction* index,
3561 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003562 Primitive::Type expected_component_type,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003563 uint32_t dex_pc)
3564 : HTemplateInstruction(SideEffects::ChangesSomething()),
3565 dex_pc_(dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003566 expected_component_type_(expected_component_type),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003567 needs_type_check_(value->GetType() == Primitive::kPrimNot),
3568 value_can_be_null_(true) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003569 SetRawInputAt(0, array);
3570 SetRawInputAt(1, index);
3571 SetRawInputAt(2, value);
3572 }
3573
Calin Juravle77520bc2015-01-12 18:45:46 +00003574 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003575 // We currently always call a runtime method to catch array store
3576 // exceptions.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003577 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003578 }
3579
Mingyao Yang81014cb2015-06-02 03:16:27 -07003580 // Can throw ArrayStoreException.
3581 bool CanThrow() const OVERRIDE { return needs_type_check_; }
3582
Calin Juravle641547a2015-04-21 22:08:51 +01003583 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3584 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003585 // TODO: Same as for ArrayGet.
3586 return false;
3587 }
3588
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003589 void ClearNeedsTypeCheck() {
3590 needs_type_check_ = false;
3591 }
3592
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003593 void ClearValueCanBeNull() {
3594 value_can_be_null_ = false;
3595 }
3596
3597 bool GetValueCanBeNull() const { return value_can_be_null_; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003598 bool NeedsTypeCheck() const { return needs_type_check_; }
3599
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003600 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003601
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003602 HInstruction* GetArray() const { return InputAt(0); }
3603 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003604 HInstruction* GetValue() const { return InputAt(2); }
3605
3606 Primitive::Type GetComponentType() const {
3607 // The Dex format does not type floating point index operations. Since the
3608 // `expected_component_type_` is set during building and can therefore not
3609 // be correct, we also check what is the value type. If it is a floating
3610 // point type, we must use that type.
3611 Primitive::Type value_type = GetValue()->GetType();
3612 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
3613 ? value_type
3614 : expected_component_type_;
3615 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003616
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003617 DECLARE_INSTRUCTION(ArraySet);
3618
3619 private:
3620 const uint32_t dex_pc_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003621 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003622 bool needs_type_check_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003623 bool value_can_be_null_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003624
3625 DISALLOW_COPY_AND_ASSIGN(HArraySet);
3626};
3627
3628class HArrayLength : public HExpression<1> {
3629 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003630 explicit HArrayLength(HInstruction* array)
3631 : HExpression(Primitive::kPrimInt, SideEffects::None()) {
3632 // Note that arrays do not change length, so the instruction does not
3633 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003634 SetRawInputAt(0, array);
3635 }
3636
Calin Juravle77520bc2015-01-12 18:45:46 +00003637 bool CanBeMoved() const OVERRIDE { return true; }
3638 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003639 UNUSED(other);
3640 return true;
3641 }
Calin Juravle641547a2015-04-21 22:08:51 +01003642 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3643 return obj == InputAt(0);
3644 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003645
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003646 DECLARE_INSTRUCTION(ArrayLength);
3647
3648 private:
3649 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
3650};
3651
3652class HBoundsCheck : public HExpression<2> {
3653 public:
3654 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003655 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003656 DCHECK(index->GetType() == Primitive::kPrimInt);
3657 SetRawInputAt(0, index);
3658 SetRawInputAt(1, length);
3659 }
3660
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003661 bool CanBeMoved() const OVERRIDE { return true; }
3662 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003663 UNUSED(other);
3664 return true;
3665 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003666
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003667 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003668
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003669 bool CanThrow() const OVERRIDE { return true; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003670
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003671 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003672
3673 DECLARE_INSTRUCTION(BoundsCheck);
3674
3675 private:
3676 const uint32_t dex_pc_;
3677
3678 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
3679};
3680
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003681/**
3682 * Some DEX instructions are folded into multiple HInstructions that need
3683 * to stay live until the last HInstruction. This class
3684 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00003685 * HInstruction stays live. `index` represents the stack location index of the
3686 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003687 */
3688class HTemporary : public HTemplateInstruction<0> {
3689 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003690 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003691
3692 size_t GetIndex() const { return index_; }
3693
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00003694 Primitive::Type GetType() const OVERRIDE {
3695 // The previous instruction is the one that will be stored in the temporary location.
3696 DCHECK(GetPrevious() != nullptr);
3697 return GetPrevious()->GetType();
3698 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00003699
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003700 DECLARE_INSTRUCTION(Temporary);
3701
3702 private:
3703 const size_t index_;
3704
3705 DISALLOW_COPY_AND_ASSIGN(HTemporary);
3706};
3707
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003708class HSuspendCheck : public HTemplateInstruction<0> {
3709 public:
3710 explicit HSuspendCheck(uint32_t dex_pc)
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003711 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003712
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003713 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003714 return true;
3715 }
3716
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003717 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003718 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
3719 SlowPathCode* GetSlowPath() const { return slow_path_; }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003720
3721 DECLARE_INSTRUCTION(SuspendCheck);
3722
3723 private:
3724 const uint32_t dex_pc_;
3725
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003726 // Only used for code generation, in order to share the same slow path between back edges
3727 // of a same loop.
3728 SlowPathCode* slow_path_;
3729
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003730 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
3731};
3732
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003733/**
3734 * Instruction to load a Class object.
3735 */
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003736class HLoadClass : public HExpression<1> {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003737 public:
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003738 HLoadClass(HCurrentMethod* current_method,
3739 uint16_t type_index,
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003740 const DexFile& dex_file,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003741 bool is_referrers_class,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003742 uint32_t dex_pc)
3743 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3744 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003745 dex_file_(dex_file),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003746 is_referrers_class_(is_referrers_class),
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003747 dex_pc_(dex_pc),
Calin Juravleb1498f62015-02-16 13:13:29 +00003748 generate_clinit_check_(false),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003749 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
3750 SetRawInputAt(0, current_method);
3751 }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003752
3753 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003754
3755 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3756 return other->AsLoadClass()->type_index_ == type_index_;
3757 }
3758
3759 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
3760
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003761 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003762 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003763 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray7d5ea032015-07-02 15:48:27 +01003764 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003765
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003766 bool NeedsEnvironment() const OVERRIDE {
3767 // Will call runtime and load the class if the class is not loaded yet.
3768 // TODO: finer grain decision.
3769 return !is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003770 }
3771
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003772 bool MustGenerateClinitCheck() const {
3773 return generate_clinit_check_;
3774 }
3775
Calin Juravle0ba218d2015-05-19 18:46:01 +01003776 void SetMustGenerateClinitCheck(bool generate_clinit_check) {
3777 generate_clinit_check_ = generate_clinit_check;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003778 }
3779
3780 bool CanCallRuntime() const {
3781 return MustGenerateClinitCheck() || !is_referrers_class_;
3782 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003783
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003784 bool CanThrow() const OVERRIDE {
3785 // May call runtime and and therefore can throw.
3786 // TODO: finer grain decision.
Nicolas Geoffray78f4fa72015-06-12 09:35:05 +01003787 return CanCallRuntime();
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003788 }
3789
Calin Juravleacf735c2015-02-12 15:25:22 +00003790 ReferenceTypeInfo GetLoadedClassRTI() {
3791 return loaded_class_rti_;
3792 }
3793
3794 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
3795 // Make sure we only set exact types (the loaded class should never be merged).
3796 DCHECK(rti.IsExact());
3797 loaded_class_rti_ = rti;
3798 }
3799
3800 bool IsResolved() {
3801 return loaded_class_rti_.IsExact();
3802 }
3803
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003804 const DexFile& GetDexFile() { return dex_file_; }
3805
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003806 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
3807
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003808 DECLARE_INSTRUCTION(LoadClass);
3809
3810 private:
3811 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003812 const DexFile& dex_file_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003813 const bool is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003814 const uint32_t dex_pc_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003815 // Whether this instruction must generate the initialization check.
3816 // Used for code generation.
3817 bool generate_clinit_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003818
Calin Juravleacf735c2015-02-12 15:25:22 +00003819 ReferenceTypeInfo loaded_class_rti_;
3820
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003821 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
3822};
3823
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003824class HLoadString : public HExpression<1> {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003825 public:
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003826 HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003827 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3828 string_index_(string_index),
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003829 dex_pc_(dex_pc) {
3830 SetRawInputAt(0, current_method);
3831 }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003832
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003833 bool CanBeMoved() const OVERRIDE { return true; }
3834
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003835 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3836 return other->AsLoadString()->string_index_ == string_index_;
3837 }
3838
3839 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
3840
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003841 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003842 uint32_t GetStringIndex() const { return string_index_; }
3843
3844 // TODO: Can we deopt or debug when we resolve a string?
3845 bool NeedsEnvironment() const OVERRIDE { return false; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003846 bool NeedsDexCache() const OVERRIDE { return true; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003847
3848 DECLARE_INSTRUCTION(LoadString);
3849
3850 private:
3851 const uint32_t string_index_;
3852 const uint32_t dex_pc_;
3853
3854 DISALLOW_COPY_AND_ASSIGN(HLoadString);
3855};
3856
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003857/**
3858 * Performs an initialization check on its Class object input.
3859 */
3860class HClinitCheck : public HExpression<1> {
3861 public:
3862 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
Nicolas Geoffraya0466e12015-03-27 15:00:40 +00003863 : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003864 dex_pc_(dex_pc) {
3865 SetRawInputAt(0, constant);
3866 }
3867
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003868 bool CanBeMoved() const OVERRIDE { return true; }
3869 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3870 UNUSED(other);
3871 return true;
3872 }
3873
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003874 bool NeedsEnvironment() const OVERRIDE {
3875 // May call runtime to initialize the class.
3876 return true;
3877 }
3878
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003879 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003880
3881 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
3882
3883 DECLARE_INSTRUCTION(ClinitCheck);
3884
3885 private:
3886 const uint32_t dex_pc_;
3887
3888 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
3889};
3890
3891class HStaticFieldGet : public HExpression<1> {
3892 public:
3893 HStaticFieldGet(HInstruction* cls,
3894 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003895 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003896 bool is_volatile,
3897 uint32_t field_idx,
3898 const DexFile& dex_file)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003899 : HExpression(field_type, SideEffects::DependsOnSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003900 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003901 SetRawInputAt(0, cls);
3902 }
3903
Calin Juravle52c48962014-12-16 17:02:57 +00003904
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003905 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003906
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003907 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00003908 HStaticFieldGet* other_get = other->AsStaticFieldGet();
3909 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003910 }
3911
3912 size_t ComputeHashCode() const OVERRIDE {
3913 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3914 }
3915
Calin Juravle52c48962014-12-16 17:02:57 +00003916 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003917 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3918 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003919 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003920
3921 DECLARE_INSTRUCTION(StaticFieldGet);
3922
3923 private:
3924 const FieldInfo field_info_;
3925
3926 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
3927};
3928
3929class HStaticFieldSet : public HTemplateInstruction<2> {
3930 public:
3931 HStaticFieldSet(HInstruction* cls,
3932 HInstruction* value,
3933 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003934 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003935 bool is_volatile,
3936 uint32_t field_idx,
3937 const DexFile& dex_file)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003938 : HTemplateInstruction(SideEffects::ChangesSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003939 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003940 value_can_be_null_(true) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003941 SetRawInputAt(0, cls);
3942 SetRawInputAt(1, value);
3943 }
3944
Calin Juravle52c48962014-12-16 17:02:57 +00003945 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003946 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3947 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003948 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003949
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003950 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003951 bool GetValueCanBeNull() const { return value_can_be_null_; }
3952 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003953
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003954 DECLARE_INSTRUCTION(StaticFieldSet);
3955
3956 private:
3957 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003958 bool value_can_be_null_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003959
3960 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
3961};
3962
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003963// Implement the move-exception DEX instruction.
3964class HLoadException : public HExpression<0> {
3965 public:
3966 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
3967
3968 DECLARE_INSTRUCTION(LoadException);
3969
3970 private:
3971 DISALLOW_COPY_AND_ASSIGN(HLoadException);
3972};
3973
3974class HThrow : public HTemplateInstruction<1> {
3975 public:
3976 HThrow(HInstruction* exception, uint32_t dex_pc)
3977 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
3978 SetRawInputAt(0, exception);
3979 }
3980
3981 bool IsControlFlow() const OVERRIDE { return true; }
3982
3983 bool NeedsEnvironment() const OVERRIDE { return true; }
3984
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003985 bool CanThrow() const OVERRIDE { return true; }
3986
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003987 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003988
3989 DECLARE_INSTRUCTION(Throw);
3990
3991 private:
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003992 const uint32_t dex_pc_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003993
3994 DISALLOW_COPY_AND_ASSIGN(HThrow);
3995};
3996
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003997class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003998 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003999 HInstanceOf(HInstruction* object,
4000 HLoadClass* constant,
4001 bool class_is_final,
4002 uint32_t dex_pc)
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004003 : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
4004 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004005 must_do_null_check_(true),
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004006 dex_pc_(dex_pc) {
4007 SetRawInputAt(0, object);
4008 SetRawInputAt(1, constant);
4009 }
4010
4011 bool CanBeMoved() const OVERRIDE { return true; }
4012
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004013 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004014 return true;
4015 }
4016
4017 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004018 return false;
4019 }
4020
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01004021 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004022
4023 bool IsClassFinal() const { return class_is_final_; }
4024
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004025 // Used only in code generation.
4026 bool MustDoNullCheck() const { return must_do_null_check_; }
4027 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
4028
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004029 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004030
4031 private:
4032 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004033 bool must_do_null_check_;
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004034 const uint32_t dex_pc_;
4035
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004036 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
4037};
4038
Calin Juravleb1498f62015-02-16 13:13:29 +00004039class HBoundType : public HExpression<1> {
4040 public:
4041 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type)
4042 : HExpression(Primitive::kPrimNot, SideEffects::None()),
4043 bound_type_(bound_type) {
Calin Juravle61d544b2015-02-23 16:46:57 +00004044 DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
Calin Juravleb1498f62015-02-16 13:13:29 +00004045 SetRawInputAt(0, input);
4046 }
4047
4048 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; }
4049
4050 bool CanBeNull() const OVERRIDE {
4051 // `null instanceof ClassX` always return false so we can't be null.
4052 return false;
4053 }
4054
4055 DECLARE_INSTRUCTION(BoundType);
4056
4057 private:
4058 // Encodes the most upper class that this instruction can have. In other words
4059 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()).
4060 // It is used to bound the type in cases like `if (x instanceof ClassX) {}`
4061 const ReferenceTypeInfo bound_type_;
4062
4063 DISALLOW_COPY_AND_ASSIGN(HBoundType);
4064};
4065
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004066class HCheckCast : public HTemplateInstruction<2> {
4067 public:
4068 HCheckCast(HInstruction* object,
4069 HLoadClass* constant,
4070 bool class_is_final,
4071 uint32_t dex_pc)
4072 : HTemplateInstruction(SideEffects::None()),
4073 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004074 must_do_null_check_(true),
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004075 dex_pc_(dex_pc) {
4076 SetRawInputAt(0, object);
4077 SetRawInputAt(1, constant);
4078 }
4079
4080 bool CanBeMoved() const OVERRIDE { return true; }
4081
4082 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
4083 return true;
4084 }
4085
4086 bool NeedsEnvironment() const OVERRIDE {
4087 // Instruction may throw a CheckCastError.
4088 return true;
4089 }
4090
4091 bool CanThrow() const OVERRIDE { return true; }
4092
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004093 bool MustDoNullCheck() const { return must_do_null_check_; }
4094 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
4095
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01004096 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004097
4098 bool IsClassFinal() const { return class_is_final_; }
4099
4100 DECLARE_INSTRUCTION(CheckCast);
4101
4102 private:
4103 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01004104 bool must_do_null_check_;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00004105 const uint32_t dex_pc_;
4106
4107 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00004108};
4109
Calin Juravle27df7582015-04-17 19:12:31 +01004110class HMemoryBarrier : public HTemplateInstruction<0> {
4111 public:
4112 explicit HMemoryBarrier(MemBarrierKind barrier_kind)
4113 : HTemplateInstruction(SideEffects::None()),
4114 barrier_kind_(barrier_kind) {}
4115
4116 MemBarrierKind GetBarrierKind() { return barrier_kind_; }
4117
4118 DECLARE_INSTRUCTION(MemoryBarrier);
4119
4120 private:
4121 const MemBarrierKind barrier_kind_;
4122
4123 DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier);
4124};
4125
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00004126class HMonitorOperation : public HTemplateInstruction<1> {
4127 public:
4128 enum OperationKind {
4129 kEnter,
4130 kExit,
4131 };
4132
4133 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
David Brazdilbff75032015-07-08 17:26:51 +00004134 : HTemplateInstruction(SideEffects::ChangesSomething()), kind_(kind), dex_pc_(dex_pc) {
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00004135 SetRawInputAt(0, object);
4136 }
4137
4138 // Instruction may throw a Java exception, so we need an environment.
David Brazdilbff75032015-07-08 17:26:51 +00004139 bool NeedsEnvironment() const OVERRIDE { return CanThrow(); }
4140
4141 bool CanThrow() const OVERRIDE {
4142 // Verifier guarantees that monitor-exit cannot throw.
4143 // This is important because it allows the HGraphBuilder to remove
4144 // a dead throw-catch loop generated for `synchronized` blocks/methods.
4145 return IsEnter();
4146 }
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00004147
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01004148 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00004149
4150 bool IsEnter() const { return kind_ == kEnter; }
4151
4152 DECLARE_INSTRUCTION(MonitorOperation);
4153
Calin Juravle52c48962014-12-16 17:02:57 +00004154 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00004155 const OperationKind kind_;
4156 const uint32_t dex_pc_;
4157
4158 private:
4159 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
4160};
4161
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004162class MoveOperands : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004163 public:
Nicolas Geoffray90218252015-04-15 11:56:51 +01004164 MoveOperands(Location source,
4165 Location destination,
4166 Primitive::Type type,
4167 HInstruction* instruction)
4168 : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004169
4170 Location GetSource() const { return source_; }
4171 Location GetDestination() const { return destination_; }
4172
4173 void SetSource(Location value) { source_ = value; }
4174 void SetDestination(Location value) { destination_ = value; }
4175
4176 // The parallel move resolver marks moves as "in-progress" by clearing the
4177 // destination (but not the source).
4178 Location MarkPending() {
4179 DCHECK(!IsPending());
4180 Location dest = destination_;
4181 destination_ = Location::NoLocation();
4182 return dest;
4183 }
4184
4185 void ClearPending(Location dest) {
4186 DCHECK(IsPending());
4187 destination_ = dest;
4188 }
4189
4190 bool IsPending() const {
4191 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
4192 return destination_.IsInvalid() && !source_.IsInvalid();
4193 }
4194
4195 // True if this blocks a move from the given location.
4196 bool Blocks(Location loc) const {
Zheng Xuad4450e2015-04-17 18:48:56 +08004197 return !IsEliminated() && source_.OverlapsWith(loc);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004198 }
4199
4200 // A move is redundant if it's been eliminated, if its source and
4201 // destination are the same, or if its destination is unneeded.
4202 bool IsRedundant() const {
4203 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
4204 }
4205
4206 // We clear both operands to indicate move that's been eliminated.
4207 void Eliminate() {
4208 source_ = destination_ = Location::NoLocation();
4209 }
4210
4211 bool IsEliminated() const {
4212 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
4213 return source_.IsInvalid();
4214 }
4215
Alexey Frunze4dda3372015-06-01 18:31:49 -07004216 Primitive::Type GetType() const { return type_; }
4217
Nicolas Geoffray90218252015-04-15 11:56:51 +01004218 bool Is64BitMove() const {
4219 return Primitive::Is64BitType(type_);
4220 }
4221
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004222 HInstruction* GetInstruction() const { return instruction_; }
4223
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004224 private:
4225 Location source_;
4226 Location destination_;
Nicolas Geoffray90218252015-04-15 11:56:51 +01004227 // The type this move is for.
4228 Primitive::Type type_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004229 // The instruction this move is assocatied with. Null when this move is
4230 // for moving an input in the expected locations of user (including a phi user).
4231 // This is only used in debug mode, to ensure we do not connect interval siblings
4232 // in the same parallel move.
4233 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004234};
4235
4236static constexpr size_t kDefaultNumberOfMoves = 4;
4237
4238class HParallelMove : public HTemplateInstruction<0> {
4239 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004240 explicit HParallelMove(ArenaAllocator* arena)
4241 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004242
Nicolas Geoffray90218252015-04-15 11:56:51 +01004243 void AddMove(Location source,
4244 Location destination,
4245 Primitive::Type type,
4246 HInstruction* instruction) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004247 DCHECK(source.IsValid());
4248 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004249 if (kIsDebugBuild) {
4250 if (instruction != nullptr) {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004251 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00004252 if (moves_.Get(i).GetInstruction() == instruction) {
4253 // Special case the situation where the move is for the spill slot
4254 // of the instruction.
4255 if ((GetPrevious() == instruction)
4256 || ((GetPrevious() == nullptr)
4257 && instruction->IsPhi()
4258 && instruction->GetBlock() == GetBlock())) {
4259 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind())
4260 << "Doing parallel moves for the same instruction.";
4261 } else {
4262 DCHECK(false) << "Doing parallel moves for the same instruction.";
4263 }
4264 }
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004265 }
4266 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004267 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Zheng Xuad4450e2015-04-17 18:48:56 +08004268 DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination()))
Guillaume "Vermeille" Sanchez8909baf2015-04-23 21:35:11 +01004269 << "Overlapped destination for two moves in a parallel move: "
4270 << moves_.Get(i).GetSource() << " ==> " << moves_.Get(i).GetDestination() << " and "
4271 << source << " ==> " << destination;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004272 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004273 }
Nicolas Geoffray90218252015-04-15 11:56:51 +01004274 moves_.Add(MoveOperands(source, destination, type, instruction));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004275 }
4276
4277 MoveOperands* MoveOperandsAt(size_t index) const {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004278 return moves_.GetRawStorage() + index;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004279 }
4280
4281 size_t NumMoves() const { return moves_.Size(); }
4282
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01004283 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004284
4285 private:
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004286 GrowableArray<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004287
4288 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
4289};
4290
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004291class HGraphVisitor : public ValueObject {
4292 public:
Dave Allison20dfc792014-06-16 20:44:29 -07004293 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
4294 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004295
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004296 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004297 virtual void VisitBasicBlock(HBasicBlock* block);
4298
Roland Levillain633021e2014-10-01 14:12:25 +01004299 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004300 void VisitInsertionOrder();
4301
Roland Levillain633021e2014-10-01 14:12:25 +01004302 // Visit the graph following dominator tree reverse post-order.
4303 void VisitReversePostOrder();
4304
Nicolas Geoffray787c3072014-03-17 10:20:19 +00004305 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00004306
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004307 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004308#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004309 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
4310
4311 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4312
4313#undef DECLARE_VISIT_INSTRUCTION
4314
4315 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07004316 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004317
4318 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
4319};
4320
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004321class HGraphDelegateVisitor : public HGraphVisitor {
4322 public:
4323 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
4324 virtual ~HGraphDelegateVisitor() {}
4325
4326 // Visit functions that delegate to to super class.
4327#define DECLARE_VISIT_INSTRUCTION(name, super) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004328 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004329
4330 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4331
4332#undef DECLARE_VISIT_INSTRUCTION
4333
4334 private:
4335 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
4336};
4337
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004338class HInsertionOrderIterator : public ValueObject {
4339 public:
4340 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
4341
4342 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
4343 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
4344 void Advance() { ++index_; }
4345
4346 private:
4347 const HGraph& graph_;
4348 size_t index_;
4349
4350 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
4351};
4352
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004353class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004354 public:
David Brazdil10f56cb2015-03-24 18:49:14 +00004355 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
4356 // Check that reverse post order of the graph has been built.
4357 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4358 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004359
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004360 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
4361 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004362 void Advance() { ++index_; }
4363
4364 private:
4365 const HGraph& graph_;
4366 size_t index_;
4367
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004368 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004369};
4370
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004371class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004372 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004373 explicit HPostOrderIterator(const HGraph& graph)
David Brazdil10f56cb2015-03-24 18:49:14 +00004374 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {
4375 // Check that reverse post order of the graph has been built.
4376 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4377 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004378
4379 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004380 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004381 void Advance() { --index_; }
4382
4383 private:
4384 const HGraph& graph_;
4385 size_t index_;
4386
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004387 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004388};
4389
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01004390class HLinearPostOrderIterator : public ValueObject {
4391 public:
4392 explicit HLinearPostOrderIterator(const HGraph& graph)
4393 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {}
4394
4395 bool Done() const { return index_ == 0; }
4396
4397 HBasicBlock* Current() const { return order_.Get(index_ -1); }
4398
4399 void Advance() {
4400 --index_;
4401 DCHECK_GE(index_, 0U);
4402 }
4403
4404 private:
4405 const GrowableArray<HBasicBlock*>& order_;
4406 size_t index_;
4407
4408 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
4409};
4410
4411class HLinearOrderIterator : public ValueObject {
4412 public:
4413 explicit HLinearOrderIterator(const HGraph& graph)
4414 : order_(graph.GetLinearOrder()), index_(0) {}
4415
4416 bool Done() const { return index_ == order_.Size(); }
4417 HBasicBlock* Current() const { return order_.Get(index_); }
4418 void Advance() { ++index_; }
4419
4420 private:
4421 const GrowableArray<HBasicBlock*>& order_;
4422 size_t index_;
4423
4424 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
4425};
4426
Nicolas Geoffray82091da2015-01-26 10:02:45 +00004427// Iterator over the blocks that art part of the loop. Includes blocks part
4428// of an inner loop. The order in which the blocks are iterated is on their
4429// block id.
4430class HBlocksInLoopIterator : public ValueObject {
4431 public:
4432 explicit HBlocksInLoopIterator(const HLoopInformation& info)
4433 : blocks_in_loop_(info.GetBlocks()),
4434 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
4435 index_(0) {
4436 if (!blocks_in_loop_.IsBitSet(index_)) {
4437 Advance();
4438 }
4439 }
4440
4441 bool Done() const { return index_ == blocks_.Size(); }
4442 HBasicBlock* Current() const { return blocks_.Get(index_); }
4443 void Advance() {
4444 ++index_;
4445 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4446 if (blocks_in_loop_.IsBitSet(index_)) {
4447 break;
4448 }
4449 }
4450 }
4451
4452 private:
4453 const BitVector& blocks_in_loop_;
4454 const GrowableArray<HBasicBlock*>& blocks_;
4455 size_t index_;
4456
4457 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
4458};
4459
Mingyao Yang3584bce2015-05-19 16:01:59 -07004460// Iterator over the blocks that art part of the loop. Includes blocks part
4461// of an inner loop. The order in which the blocks are iterated is reverse
4462// post order.
4463class HBlocksInLoopReversePostOrderIterator : public ValueObject {
4464 public:
4465 explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info)
4466 : blocks_in_loop_(info.GetBlocks()),
4467 blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
4468 index_(0) {
4469 if (!blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
4470 Advance();
4471 }
4472 }
4473
4474 bool Done() const { return index_ == blocks_.Size(); }
4475 HBasicBlock* Current() const { return blocks_.Get(index_); }
4476 void Advance() {
4477 ++index_;
4478 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4479 if (blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
4480 break;
4481 }
4482 }
4483 }
4484
4485 private:
4486 const BitVector& blocks_in_loop_;
4487 const GrowableArray<HBasicBlock*>& blocks_;
4488 size_t index_;
4489
4490 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
4491};
4492
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00004493inline int64_t Int64FromConstant(HConstant* constant) {
4494 DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
4495 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
4496 : constant->AsLongConstant()->GetValue();
4497}
4498
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004499} // namespace art
4500
4501#endif // ART_COMPILER_OPTIMIZING_NODES_H_