blob: 6c2506e454bff8d2d876098fa6077f3e21f9780e [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;
42class HGraphVisitor;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000043class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000044class HIntConstant;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000045class HInvoke;
David Brazdil8d5b8b22015-03-24 10:51:52 +000046class HLongConstant;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +000047class HNullConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010048class HPhi;
Nicolas Geoffray3c049742014-09-24 18:10:46 +010049class HSuspendCheck;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010050class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000051class LocationSummary;
Nicolas Geoffraydb216f42015-05-05 17:02:20 +010052class SlowPathCode;
David Brazdil8d5b8b22015-03-24 10:51:52 +000053class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000054
55static const int kDefaultNumberOfBlocks = 8;
56static const int kDefaultNumberOfSuccessors = 2;
57static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010058static const int kDefaultNumberOfDominatedBlocks = 1;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000059static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000060
Calin Juravle9aec02f2014-11-18 23:06:35 +000061static constexpr uint32_t kMaxIntShiftValue = 0x1f;
62static constexpr uint64_t kMaxLongShiftValue = 0x3f;
63
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010064static constexpr uint32_t kUnknownFieldIndex = static_cast<uint32_t>(-1);
65
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +010066static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
67
Dave Allison20dfc792014-06-16 20:44:29 -070068enum IfCondition {
69 kCondEQ,
70 kCondNE,
71 kCondLT,
72 kCondLE,
73 kCondGT,
74 kCondGE,
75};
76
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010077class HInstructionList {
78 public:
79 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
80
81 void AddInstruction(HInstruction* instruction);
82 void RemoveInstruction(HInstruction* instruction);
83
David Brazdilc3d743f2015-04-22 13:40:50 +010084 // Insert `instruction` before/after an existing instruction `cursor`.
85 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
86 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
87
Roland Levillain6b469232014-09-25 10:10:38 +010088 // Return true if this list contains `instruction`.
89 bool Contains(HInstruction* instruction) const;
90
Roland Levillainccc07a92014-09-16 14:48:16 +010091 // Return true if `instruction1` is found before `instruction2` in
92 // this instruction list and false otherwise. Abort if none
93 // of these instructions is found.
94 bool FoundBefore(const HInstruction* instruction1,
95 const HInstruction* instruction2) const;
96
Nicolas Geoffray276d9da2015-02-02 18:24:11 +000097 bool IsEmpty() const { return first_instruction_ == nullptr; }
98 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
99
100 // Update the block of all instructions to be `block`.
101 void SetBlockOfInstructions(HBasicBlock* block) const;
102
103 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
104 void Add(const HInstructionList& instruction_list);
105
David Brazdil2d7352b2015-04-20 14:52:42 +0100106 // Return the number of instructions in the list. This is an expensive operation.
107 size_t CountSize() const;
108
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100109 private:
110 HInstruction* first_instruction_;
111 HInstruction* last_instruction_;
112
113 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000114 friend class HGraph;
115 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100116 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100117 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100118
119 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
120};
121
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000122// Control-flow graph of a method. Contains a list of basic blocks.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700123class HGraph : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000124 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100125 HGraph(ArenaAllocator* arena,
126 const DexFile& dex_file,
127 uint32_t method_idx,
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100128 bool should_generate_constructor_barrier,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100129 InvokeType invoke_type = kInvalidInvokeType,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100130 bool debuggable = false,
131 int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000132 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000133 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100134 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100135 linear_order_(arena, kDefaultNumberOfBlocks),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700136 entry_block_(nullptr),
137 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100138 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100139 number_of_vregs_(0),
140 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000141 temporaries_vreg_slots_(0),
Mark Mendell1152c922015-04-24 17:06:35 -0400142 has_bounds_checks_(false),
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000143 debuggable_(debuggable),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000144 current_instruction_id_(start_instruction_id),
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100145 dex_file_(dex_file),
146 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100147 invoke_type_(invoke_type),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100148 in_ssa_form_(false),
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100149 should_generate_constructor_barrier_(should_generate_constructor_barrier),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000150 cached_null_constant_(nullptr),
151 cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000152 cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
153 cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100154 cached_double_constants_(std::less<int64_t>(), arena->Adapter()),
155 cached_current_method_(nullptr) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000156
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000157 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100158 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Roland Levillain93445682014-10-06 19:24:02 +0100159 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000160
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000161 HBasicBlock* GetEntryBlock() const { return entry_block_; }
162 HBasicBlock* GetExitBlock() const { return exit_block_; }
David Brazdilc7af85d2015-05-26 12:05:55 +0100163 bool HasExitBlock() const { return exit_block_ != nullptr; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000164
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000165 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
166 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000167
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000168 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100169
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000170 // Try building the SSA form of this graph, with dominance computation and loop
171 // recognition. Returns whether it was successful in doing all these steps.
172 bool TryBuildingSsa() {
173 BuildDominatorTree();
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000174 // The SSA builder requires loops to all be natural. Specifically, the dead phi
175 // elimination phase checks the consistency of the graph when doing a post-order
176 // visit for eliminating dead phis: a dead phi can only have loop header phi
177 // users remaining when being visited.
178 if (!AnalyzeNaturalLoops()) return false;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000179 TransformToSsa();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100180 in_ssa_form_ = true;
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000181 return true;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000182 }
183
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000184 void BuildDominatorTree();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000185 void TransformToSsa();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100186 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000187
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000188 // Analyze all natural loops in this graph. Returns false if one
189 // loop is not natural, that is the header does not dominate the
190 // back edge.
191 bool AnalyzeNaturalLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100192
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000193 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
194 void InlineInto(HGraph* outer_graph, HInvoke* invoke);
195
David Brazdil2d7352b2015-04-20 14:52:42 +0100196 // Removes `block` from the graph.
197 void DeleteDeadBlock(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000198
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100199 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
200 void SimplifyLoop(HBasicBlock* header);
201
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000202 int32_t GetNextInstructionId() {
203 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000204 return current_instruction_id_++;
205 }
206
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000207 int32_t GetCurrentInstructionId() const {
208 return current_instruction_id_;
209 }
210
211 void SetCurrentInstructionId(int32_t id) {
212 current_instruction_id_ = id;
213 }
214
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100215 uint16_t GetMaximumNumberOfOutVRegs() const {
216 return maximum_number_of_out_vregs_;
217 }
218
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000219 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
220 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100221 }
222
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100223 void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
224 maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
225 }
226
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000227 void UpdateTemporariesVRegSlots(size_t slots) {
228 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100229 }
230
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000231 size_t GetTemporariesVRegSlots() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100232 DCHECK(!in_ssa_form_);
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000233 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100234 }
235
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100236 void SetNumberOfVRegs(uint16_t number_of_vregs) {
237 number_of_vregs_ = number_of_vregs;
238 }
239
240 uint16_t GetNumberOfVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100241 DCHECK(!in_ssa_form_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100242 return number_of_vregs_;
243 }
244
245 void SetNumberOfInVRegs(uint16_t value) {
246 number_of_in_vregs_ = value;
247 }
248
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100249 uint16_t GetNumberOfLocalVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100250 DCHECK(!in_ssa_form_);
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100251 return number_of_vregs_ - number_of_in_vregs_;
252 }
253
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100254 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
255 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100256 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100257
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100258 const GrowableArray<HBasicBlock*>& GetLinearOrder() const {
259 return linear_order_;
260 }
261
Mark Mendell1152c922015-04-24 17:06:35 -0400262 bool HasBoundsChecks() const {
263 return has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800264 }
265
Mark Mendell1152c922015-04-24 17:06:35 -0400266 void SetHasBoundsChecks(bool value) {
267 has_bounds_checks_ = value;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800268 }
269
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100270 bool ShouldGenerateConstructorBarrier() const {
271 return should_generate_constructor_barrier_;
272 }
273
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000274 bool IsDebuggable() const { return debuggable_; }
275
David Brazdil8d5b8b22015-03-24 10:51:52 +0000276 // Returns a constant of the given type and value. If it does not exist
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000277 // already, it is created and inserted into the graph. This method is only for
278 // integral types.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000279 HConstant* GetConstant(Primitive::Type type, int64_t value);
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000280 HNullConstant* GetNullConstant();
David Brazdil8d5b8b22015-03-24 10:51:52 +0000281 HIntConstant* GetIntConstant(int32_t value) {
282 return CreateConstant(value, &cached_int_constants_);
283 }
284 HLongConstant* GetLongConstant(int64_t value) {
285 return CreateConstant(value, &cached_long_constants_);
286 }
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000287 HFloatConstant* GetFloatConstant(float value) {
288 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_);
289 }
290 HDoubleConstant* GetDoubleConstant(double value) {
291 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
292 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000293
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100294 HCurrentMethod* GetCurrentMethod();
295
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000296 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
David Brazdil2d7352b2015-04-20 14:52:42 +0100297
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100298 const DexFile& GetDexFile() const {
299 return dex_file_;
300 }
301
302 uint32_t GetMethodIdx() const {
303 return method_idx_;
304 }
305
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100306 InvokeType GetInvokeType() const {
307 return invoke_type_;
308 }
309
David Brazdil2d7352b2015-04-20 14:52:42 +0100310 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000311 void VisitBlockForDominatorTree(HBasicBlock* block,
312 HBasicBlock* predecessor,
313 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100314 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000315 void VisitBlockForBackEdges(HBasicBlock* block,
316 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100317 ArenaBitVector* visiting);
Roland Levillainfc600dc2014-12-02 17:16:31 +0000318 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100319 void RemoveDeadBlocks(const ArenaBitVector& visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000320
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000321 template <class InstructionType, typename ValueType>
322 InstructionType* CreateConstant(ValueType value,
323 ArenaSafeMap<ValueType, InstructionType*>* cache) {
324 // Try to find an existing constant of the given value.
325 InstructionType* constant = nullptr;
326 auto cached_constant = cache->find(value);
327 if (cached_constant != cache->end()) {
328 constant = cached_constant->second;
329 }
330
331 // If not found or previously deleted, create and cache a new instruction.
332 if (constant == nullptr || constant->GetBlock() == nullptr) {
333 constant = new (arena_) InstructionType(value);
334 cache->Overwrite(value, constant);
335 InsertConstant(constant);
336 }
337 return constant;
338 }
339
David Brazdil8d5b8b22015-03-24 10:51:52 +0000340 void InsertConstant(HConstant* instruction);
341
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000342 // Cache a float constant into the graph. This method should only be
343 // called by the SsaBuilder when creating "equivalent" instructions.
344 void CacheFloatConstant(HFloatConstant* constant);
345
346 // See CacheFloatConstant comment.
347 void CacheDoubleConstant(HDoubleConstant* constant);
348
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000349 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000350
351 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000352 GrowableArray<HBasicBlock*> blocks_;
353
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100354 // List of blocks to perform a reverse post order tree traversal.
355 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000356
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100357 // List of blocks to perform a linear order tree traversal.
358 GrowableArray<HBasicBlock*> linear_order_;
359
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000360 HBasicBlock* entry_block_;
361 HBasicBlock* exit_block_;
362
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100363 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100364 uint16_t maximum_number_of_out_vregs_;
365
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100366 // The number of virtual registers in this method. Contains the parameters.
367 uint16_t number_of_vregs_;
368
369 // The number of virtual registers used by parameters of this method.
370 uint16_t number_of_in_vregs_;
371
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000372 // Number of vreg size slots that the temporaries use (used in baseline compiler).
373 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100374
Mark Mendell1152c922015-04-24 17:06:35 -0400375 // Has bounds checks. We can totally skip BCE if it's false.
376 bool has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800377
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000378 // Indicates whether the graph should be compiled in a way that
379 // ensures full debuggability. If false, we can apply more
380 // aggressive optimizations that may limit the level of debugging.
381 const bool debuggable_;
382
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000383 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000384 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000385
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100386 // The dex file from which the method is from.
387 const DexFile& dex_file_;
388
389 // The method index in the dex file.
390 const uint32_t method_idx_;
391
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100392 // If inlined, this encodes how the callee is being invoked.
393 const InvokeType invoke_type_;
394
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100395 // Whether the graph has been transformed to SSA form. Only used
396 // in debug mode to ensure we are not using properties only valid
397 // for non-SSA form (like the number of temporaries).
398 bool in_ssa_form_;
399
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100400 const bool should_generate_constructor_barrier_;
401
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000402 // Cached constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000403 HNullConstant* cached_null_constant_;
404 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000405 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
David Brazdil8d5b8b22015-03-24 10:51:52 +0000406 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000407 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
David Brazdil46e2a392015-03-16 17:31:52 +0000408
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100409 HCurrentMethod* cached_current_method_;
410
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000411 friend class SsaBuilder; // For caching constants.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100412 friend class SsaLivenessAnalysis; // For the linear order.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000413 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000414 DISALLOW_COPY_AND_ASSIGN(HGraph);
415};
416
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700417class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000418 public:
419 HLoopInformation(HBasicBlock* header, HGraph* graph)
420 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100421 suspend_check_(nullptr),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100422 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100423 // Make bit vector growable, as the number of blocks may change.
424 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100425
426 HBasicBlock* GetHeader() const {
427 return header_;
428 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000429
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000430 void SetHeader(HBasicBlock* block) {
431 header_ = block;
432 }
433
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100434 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
435 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
436 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
437
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000438 void AddBackEdge(HBasicBlock* back_edge) {
439 back_edges_.Add(back_edge);
440 }
441
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100442 void RemoveBackEdge(HBasicBlock* back_edge) {
443 back_edges_.Delete(back_edge);
444 }
445
David Brazdil46e2a392015-03-16 17:31:52 +0000446 bool IsBackEdge(const HBasicBlock& block) const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100447 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
David Brazdil46e2a392015-03-16 17:31:52 +0000448 if (back_edges_.Get(i) == &block) return true;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100449 }
450 return false;
451 }
452
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000453 size_t NumberOfBackEdges() const {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000454 return back_edges_.Size();
455 }
456
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100457 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100458
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100459 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
460 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100461 }
462
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100463 // Returns the lifetime position of the back edge that has the
464 // greatest lifetime position.
465 size_t GetLifetimeEnd() const;
466
467 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
468 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
469 if (back_edges_.Get(i) == existing) {
470 back_edges_.Put(i, new_back_edge);
471 return;
472 }
473 }
474 UNREACHABLE();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100475 }
476
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100477 // Finds blocks that are part of this loop. Returns whether the loop is a natural loop,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100478 // that is the header dominates the back edge.
479 bool Populate();
480
David Brazdila4b8c212015-05-07 09:59:30 +0100481 // Reanalyzes the loop by removing loop info from its blocks and re-running
482 // Populate(). If there are no back edges left, the loop info is completely
483 // removed as well as its SuspendCheck instruction. It must be run on nested
484 // inner loops first.
485 void Update();
486
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100487 // Returns whether this loop information contains `block`.
488 // Note that this loop information *must* be populated before entering this function.
489 bool Contains(const HBasicBlock& block) const;
490
491 // Returns whether this loop information is an inner loop of `other`.
492 // Note that `other` *must* be populated before entering this function.
493 bool IsIn(const HLoopInformation& other) const;
494
495 const ArenaBitVector& GetBlocks() const { return blocks_; }
496
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000497 void Add(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000498 void Remove(HBasicBlock* block);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000499
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000500 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100501 // Internal recursive implementation of `Populate`.
502 void PopulateRecursive(HBasicBlock* block);
503
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000504 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100505 HSuspendCheck* suspend_check_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000506 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100507 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000508
509 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
510};
511
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100512static constexpr size_t kNoLifetime = -1;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100513static constexpr uint32_t kNoDexPc = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100514
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000515// A block in a method. Contains the list of instructions represented
516// as a double linked list. Each block knows its predecessors and
517// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100518
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700519class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000520 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100521 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000522 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000523 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
524 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000525 loop_information_(nullptr),
526 dominator_(nullptr),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100527 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100528 block_id_(-1),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100529 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100530 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000531 lifetime_end_(kNoLifetime),
532 is_catch_block_(false) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000533
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100534 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
535 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000536 }
537
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100538 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
539 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000540 }
541
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100542 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
543 return dominated_blocks_;
544 }
545
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100546 bool IsEntryBlock() const {
547 return graph_->GetEntryBlock() == this;
548 }
549
550 bool IsExitBlock() const {
551 return graph_->GetExitBlock() == this;
552 }
553
David Brazdil46e2a392015-03-16 17:31:52 +0000554 bool IsSingleGoto() const;
555
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000556 void AddBackEdge(HBasicBlock* back_edge) {
557 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000558 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000559 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100560 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000561 loop_information_->AddBackEdge(back_edge);
562 }
563
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000564 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000565 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000566
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000567 int GetBlockId() const { return block_id_; }
568 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000569
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000570 HBasicBlock* GetDominator() const { return dominator_; }
571 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100572 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
David Brazdil2d7352b2015-04-20 14:52:42 +0100573 void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000574 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
575 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
576 if (dominated_blocks_.Get(i) == existing) {
577 dominated_blocks_.Put(i, new_block);
578 return;
579 }
580 }
581 LOG(FATAL) << "Unreachable";
582 UNREACHABLE();
583 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000584
585 int NumberOfBackEdges() const {
586 return loop_information_ == nullptr
587 ? 0
588 : loop_information_->NumberOfBackEdges();
589 }
590
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100591 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
592 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100593 const HInstructionList& GetInstructions() const { return instructions_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100594 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
David Brazdilc3d743f2015-04-22 13:40:50 +0100595 HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
596 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000597
598 void AddSuccessor(HBasicBlock* block) {
599 successors_.Add(block);
600 block->predecessors_.Add(this);
601 }
602
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100603 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
604 size_t successor_index = GetSuccessorIndexOf(existing);
605 DCHECK_NE(successor_index, static_cast<size_t>(-1));
606 existing->RemovePredecessor(this);
607 new_block->predecessors_.Add(this);
608 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000609 }
610
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000611 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
612 size_t predecessor_index = GetPredecessorIndexOf(existing);
613 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
614 existing->RemoveSuccessor(this);
615 new_block->successors_.Add(this);
616 predecessors_.Put(predecessor_index, new_block);
617 }
618
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100619 void RemovePredecessor(HBasicBlock* block) {
620 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100621 }
622
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000623 void RemoveSuccessor(HBasicBlock* block) {
624 successors_.Delete(block);
625 }
626
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100627 void ClearAllPredecessors() {
628 predecessors_.Reset();
629 }
630
631 void AddPredecessor(HBasicBlock* block) {
632 predecessors_.Add(block);
633 block->successors_.Add(this);
634 }
635
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100636 void SwapPredecessors() {
Nicolas Geoffrayc83d4412014-09-18 16:46:20 +0100637 DCHECK_EQ(predecessors_.Size(), 2u);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100638 HBasicBlock* temp = predecessors_.Get(0);
639 predecessors_.Put(0, predecessors_.Get(1));
640 predecessors_.Put(1, temp);
641 }
642
David Brazdil769c9e52015-04-27 13:54:09 +0100643 void SwapSuccessors() {
644 DCHECK_EQ(successors_.Size(), 2u);
645 HBasicBlock* temp = successors_.Get(0);
646 successors_.Put(0, successors_.Get(1));
647 successors_.Put(1, temp);
648 }
649
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100650 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
651 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
652 if (predecessors_.Get(i) == predecessor) {
653 return i;
654 }
655 }
656 return -1;
657 }
658
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100659 size_t GetSuccessorIndexOf(HBasicBlock* successor) {
660 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
661 if (successors_.Get(i) == successor) {
662 return i;
663 }
664 }
665 return -1;
666 }
667
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000668 // Split the block into two blocks just after `cursor`. Returns the newly
669 // created block. Note that this method just updates raw block information,
670 // like predecessors, successors, dominators, and instruction list. It does not
671 // update the graph, reverse post order, loop information, nor make sure the
672 // blocks are consistent (for example ending with a control flow instruction).
673 HBasicBlock* SplitAfter(HInstruction* cursor);
674
675 // Merge `other` at the end of `this`. Successors and dominated blocks of
676 // `other` are changed to be successors and dominated blocks of `this`. Note
677 // that this method does not update the graph, reverse post order, loop
678 // information, nor make sure the blocks are consistent (for example ending
679 // with a control flow instruction).
David Brazdil2d7352b2015-04-20 14:52:42 +0100680 void MergeWithInlined(HBasicBlock* other);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000681
682 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
683 // of `this` are moved to `other`.
684 // Note that this method does not update the graph, reverse post order, loop
685 // information, nor make sure the blocks are consistent (for example ending
David Brazdil46e2a392015-03-16 17:31:52 +0000686 // with a control flow instruction).
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000687 void ReplaceWith(HBasicBlock* other);
688
David Brazdil2d7352b2015-04-20 14:52:42 +0100689 // Merge `other` at the end of `this`. This method updates loops, reverse post
690 // order, links to predecessors, successors, dominators and deletes the block
691 // from the graph. The two blocks must be successive, i.e. `this` the only
692 // predecessor of `other` and vice versa.
693 void MergeWith(HBasicBlock* other);
694
695 // Disconnects `this` from all its predecessors, successors and dominator,
696 // removes it from all loops it is included in and eventually from the graph.
697 // The block must not dominate any other block. Predecessors and successors
698 // are safely updated.
699 void DisconnectAndDelete();
David Brazdil46e2a392015-03-16 17:31:52 +0000700
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000701 void AddInstruction(HInstruction* instruction);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100702 // Insert `instruction` before/after an existing instruction `cursor`.
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100703 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100704 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +0100705 // Replace instruction `initial` with `replacement` within this block.
706 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
707 HInstruction* replacement);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100708 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100709 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
David Brazdil1abb4192015-02-17 18:33:36 +0000710 // RemoveInstruction and RemovePhi delete a given instruction from the respective
711 // instruction list. With 'ensure_safety' set to true, it verifies that the
712 // instruction is not in use and removes it from the use lists of its inputs.
713 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
714 void RemovePhi(HPhi* phi, bool ensure_safety = true);
David Brazdilc7508e92015-04-27 13:28:57 +0100715 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100716
717 bool IsLoopHeader() const {
David Brazdil69a28042015-04-29 17:16:07 +0100718 return IsInLoop() && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100719 }
720
Roland Levillain6b879dd2014-09-22 17:13:44 +0100721 bool IsLoopPreHeaderFirstPredecessor() const {
722 DCHECK(IsLoopHeader());
723 DCHECK(!GetPredecessors().IsEmpty());
724 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
725 }
726
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100727 HLoopInformation* GetLoopInformation() const {
728 return loop_information_;
729 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000730
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000731 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100732 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000733 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100734 void SetInLoop(HLoopInformation* info) {
735 if (IsLoopHeader()) {
736 // Nothing to do. This just means `info` is an outer loop.
David Brazdil69a28042015-04-29 17:16:07 +0100737 } else if (!IsInLoop()) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100738 loop_information_ = info;
739 } else if (loop_information_->Contains(*info->GetHeader())) {
740 // Block is currently part of an outer loop. Make it part of this inner loop.
741 // Note that a non loop header having a loop information means this loop information
742 // has already been populated
743 loop_information_ = info;
744 } else {
745 // Block is part of an inner loop. Do not update the loop information.
746 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
747 // at this point, because this method is being called while populating `info`.
748 }
749 }
750
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000751 // Raw update of the loop information.
752 void SetLoopInformation(HLoopInformation* info) {
753 loop_information_ = info;
754 }
755
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100756 bool IsInLoop() const { return loop_information_ != nullptr; }
757
David Brazdila4b8c212015-05-07 09:59:30 +0100758 // Returns whether this block dominates the blocked passed as parameter.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100759 bool Dominates(HBasicBlock* block) const;
760
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100761 size_t GetLifetimeStart() const { return lifetime_start_; }
762 size_t GetLifetimeEnd() const { return lifetime_end_; }
763
764 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
765 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
766
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100767 uint32_t GetDexPc() const { return dex_pc_; }
768
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000769 bool IsCatchBlock() const { return is_catch_block_; }
770 void SetIsCatchBlock() { is_catch_block_ = true; }
771
David Brazdil8d5b8b22015-03-24 10:51:52 +0000772 bool EndsWithControlFlowInstruction() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +0000773 bool EndsWithIf() const;
774 bool HasSinglePhi() const;
775
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000776 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000777 HGraph* graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000778 GrowableArray<HBasicBlock*> predecessors_;
779 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100780 HInstructionList instructions_;
781 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000782 HLoopInformation* loop_information_;
783 HBasicBlock* dominator_;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100784 GrowableArray<HBasicBlock*> dominated_blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000785 int block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100786 // The dex program counter of the first instruction of this block.
787 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100788 size_t lifetime_start_;
789 size_t lifetime_end_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000790 bool is_catch_block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000791
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000792 friend class HGraph;
793 friend class HInstruction;
794
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000795 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
796};
797
David Brazdilb2bd1c52015-03-25 11:17:37 +0000798// Iterates over the LoopInformation of all loops which contain 'block'
799// from the innermost to the outermost.
800class HLoopInformationOutwardIterator : public ValueObject {
801 public:
802 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
803 : current_(block.GetLoopInformation()) {}
804
805 bool Done() const { return current_ == nullptr; }
806
807 void Advance() {
808 DCHECK(!Done());
David Brazdil69a28042015-04-29 17:16:07 +0100809 current_ = current_->GetPreHeader()->GetLoopInformation();
David Brazdilb2bd1c52015-03-25 11:17:37 +0000810 }
811
812 HLoopInformation* Current() const {
813 DCHECK(!Done());
814 return current_;
815 }
816
817 private:
818 HLoopInformation* current_;
819
820 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
821};
822
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100823#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
824 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000825 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000826 M(ArrayGet, Instruction) \
827 M(ArrayLength, Instruction) \
828 M(ArraySet, Instruction) \
David Brazdil66d126e2015-04-03 16:02:44 +0100829 M(BooleanNot, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000830 M(BoundsCheck, Instruction) \
Calin Juravleb1498f62015-02-16 13:13:29 +0000831 M(BoundType, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000832 M(CheckCast, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100833 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000834 M(Compare, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100835 M(Condition, BinaryOperation) \
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100836 M(CurrentMethod, Instruction) \
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700837 M(Deoptimize, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000838 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +0000839 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000840 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100841 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000842 M(Exit, Instruction) \
843 M(FloatConstant, Constant) \
844 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100845 M(GreaterThan, Condition) \
846 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100847 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000848 M(InstanceFieldGet, Instruction) \
849 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000850 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100851 M(IntConstant, Constant) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000852 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000853 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100854 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000855 M(LessThan, Condition) \
856 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000857 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000858 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100859 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000860 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100861 M(Local, Instruction) \
862 M(LongConstant, Constant) \
Calin Juravle27df7582015-04-17 19:12:31 +0100863 M(MemoryBarrier, Instruction) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +0000864 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000865 M(Mul, BinaryOperation) \
866 M(Neg, UnaryOperation) \
867 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100868 M(NewInstance, Instruction) \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100869 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000870 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000871 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000872 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000873 M(Or, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100874 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000875 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100876 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000877 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100878 M(Return, Instruction) \
879 M(ReturnVoid, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000880 M(Shl, BinaryOperation) \
881 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100882 M(StaticFieldGet, Instruction) \
883 M(StaticFieldSet, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100884 M(StoreLocal, Instruction) \
885 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100886 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000887 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000888 M(Throw, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +0000889 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000890 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000891 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000892
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100893#define FOR_EACH_INSTRUCTION(M) \
894 FOR_EACH_CONCRETE_INSTRUCTION(M) \
895 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +0100896 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +0100897 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100898 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -0700899
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100900#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000901FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
902#undef FORWARD_DECLARATION
903
Roland Levillainccc07a92014-09-16 14:48:16 +0100904#define DECLARE_INSTRUCTION(type) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000905 InstructionKind GetKind() const OVERRIDE { return k##type; } \
906 const char* DebugName() const OVERRIDE { return #type; } \
907 const H##type* As##type() const OVERRIDE { return this; } \
908 H##type* As##type() OVERRIDE { return this; } \
909 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \
Roland Levillainccc07a92014-09-16 14:48:16 +0100910 return other->Is##type(); \
911 } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000912 void Accept(HGraphVisitor* visitor) OVERRIDE
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000913
David Brazdiled596192015-01-23 10:39:45 +0000914template <typename T> class HUseList;
915
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100916template <typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700917class HUseListNode : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000918 public:
David Brazdiled596192015-01-23 10:39:45 +0000919 HUseListNode* GetPrevious() const { return prev_; }
920 HUseListNode* GetNext() const { return next_; }
921 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100922 size_t GetIndex() const { return index_; }
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100923 void SetIndex(size_t index) { index_ = index; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100924
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000925 private:
David Brazdiled596192015-01-23 10:39:45 +0000926 HUseListNode(T user, size_t index)
927 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
928
929 T const user_;
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100930 size_t index_;
David Brazdiled596192015-01-23 10:39:45 +0000931 HUseListNode<T>* prev_;
932 HUseListNode<T>* next_;
933
934 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000935
936 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
937};
938
David Brazdiled596192015-01-23 10:39:45 +0000939template <typename T>
940class HUseList : public ValueObject {
941 public:
942 HUseList() : first_(nullptr) {}
943
944 void Clear() {
945 first_ = nullptr;
946 }
947
948 // Adds a new entry at the beginning of the use list and returns
949 // the newly created node.
950 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +0000951 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +0000952 if (IsEmpty()) {
953 first_ = new_node;
954 } else {
955 first_->prev_ = new_node;
956 new_node->next_ = first_;
957 first_ = new_node;
958 }
959 return new_node;
960 }
961
962 HUseListNode<T>* GetFirst() const {
963 return first_;
964 }
965
966 void Remove(HUseListNode<T>* node) {
David Brazdil1abb4192015-02-17 18:33:36 +0000967 DCHECK(node != nullptr);
968 DCHECK(Contains(node));
969
David Brazdiled596192015-01-23 10:39:45 +0000970 if (node->prev_ != nullptr) {
971 node->prev_->next_ = node->next_;
972 }
973 if (node->next_ != nullptr) {
974 node->next_->prev_ = node->prev_;
975 }
976 if (node == first_) {
977 first_ = node->next_;
978 }
979 }
980
David Brazdil1abb4192015-02-17 18:33:36 +0000981 bool Contains(const HUseListNode<T>* node) const {
982 if (node == nullptr) {
983 return false;
984 }
985 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
986 if (current == node) {
987 return true;
988 }
989 }
990 return false;
991 }
992
David Brazdiled596192015-01-23 10:39:45 +0000993 bool IsEmpty() const {
994 return first_ == nullptr;
995 }
996
997 bool HasOnlyOneUse() const {
998 return first_ != nullptr && first_->next_ == nullptr;
999 }
1000
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001001 size_t SizeSlow() const {
1002 size_t count = 0;
1003 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1004 ++count;
1005 }
1006 return count;
1007 }
1008
David Brazdiled596192015-01-23 10:39:45 +00001009 private:
1010 HUseListNode<T>* first_;
1011};
1012
1013template<typename T>
1014class HUseIterator : public ValueObject {
1015 public:
1016 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
1017
1018 bool Done() const { return current_ == nullptr; }
1019
1020 void Advance() {
1021 DCHECK(!Done());
1022 current_ = current_->GetNext();
1023 }
1024
1025 HUseListNode<T>* Current() const {
1026 DCHECK(!Done());
1027 return current_;
1028 }
1029
1030 private:
1031 HUseListNode<T>* current_;
1032
1033 friend class HValue;
1034};
1035
David Brazdil1abb4192015-02-17 18:33:36 +00001036// This class is used by HEnvironment and HInstruction classes to record the
1037// instructions they use and pointers to the corresponding HUseListNodes kept
1038// by the used instructions.
1039template <typename T>
1040class HUserRecord : public ValueObject {
1041 public:
1042 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
1043 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
1044
1045 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
1046 : instruction_(old_record.instruction_), use_node_(use_node) {
1047 DCHECK(instruction_ != nullptr);
1048 DCHECK(use_node_ != nullptr);
1049 DCHECK(old_record.use_node_ == nullptr);
1050 }
1051
1052 HInstruction* GetInstruction() const { return instruction_; }
1053 HUseListNode<T>* GetUseNode() const { return use_node_; }
1054
1055 private:
1056 // Instruction used by the user.
1057 HInstruction* instruction_;
1058
1059 // Corresponding entry in the use list kept by 'instruction_'.
1060 HUseListNode<T>* use_node_;
1061};
1062
Calin Juravle27df7582015-04-17 19:12:31 +01001063// TODO: Add better documentation to this class and maybe refactor with more suggestive names.
1064// - Has(All)SideEffects suggests that all the side effects are present but only ChangesSomething
1065// flag is consider.
1066// - DependsOn suggests that there is a real dependency between side effects but it only
1067// checks DependendsOnSomething flag.
1068//
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001069// Represents the side effects an instruction may have.
1070class SideEffects : public ValueObject {
1071 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001072 SideEffects() : flags_(0) {}
1073
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001074 static SideEffects None() {
1075 return SideEffects(0);
1076 }
1077
1078 static SideEffects All() {
1079 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
1080 }
1081
1082 static SideEffects ChangesSomething() {
1083 return SideEffects((1 << kFlagChangesCount) - 1);
1084 }
1085
1086 static SideEffects DependsOnSomething() {
1087 int count = kFlagDependsOnCount - kFlagChangesCount;
1088 return SideEffects(((1 << count) - 1) << kFlagChangesCount);
1089 }
1090
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001091 SideEffects Union(SideEffects other) const {
1092 return SideEffects(flags_ | other.flags_);
1093 }
1094
Roland Levillain72bceff2014-09-15 18:29:00 +01001095 bool HasSideEffects() const {
1096 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1097 return (flags_ & all_bits_set) != 0;
1098 }
1099
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001100 bool HasAllSideEffects() const {
1101 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1102 return all_bits_set == (flags_ & all_bits_set);
1103 }
1104
1105 bool DependsOn(SideEffects other) const {
1106 size_t depends_flags = other.ComputeDependsFlags();
1107 return (flags_ & depends_flags) != 0;
1108 }
1109
1110 bool HasDependencies() const {
1111 int count = kFlagDependsOnCount - kFlagChangesCount;
1112 size_t all_bits_set = (1 << count) - 1;
1113 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
1114 }
1115
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001116 private:
1117 static constexpr int kFlagChangesSomething = 0;
1118 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
1119
1120 static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
1121 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
1122
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001123 explicit SideEffects(size_t flags) : flags_(flags) {}
1124
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001125 size_t ComputeDependsFlags() const {
1126 return flags_ << kFlagChangesCount;
1127 }
1128
1129 size_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001130};
1131
David Brazdiled596192015-01-23 10:39:45 +00001132// A HEnvironment object contains the values of virtual registers at a given location.
1133class HEnvironment : public ArenaObject<kArenaAllocMisc> {
1134 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001135 HEnvironment(ArenaAllocator* arena,
1136 size_t number_of_vregs,
1137 const DexFile& dex_file,
1138 uint32_t method_idx,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001139 uint32_t dex_pc,
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001140 InvokeType invoke_type,
1141 HInstruction* holder)
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001142 : vregs_(arena, number_of_vregs),
1143 locations_(arena, number_of_vregs),
1144 parent_(nullptr),
1145 dex_file_(dex_file),
1146 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001147 dex_pc_(dex_pc),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001148 invoke_type_(invoke_type),
1149 holder_(holder) {
David Brazdiled596192015-01-23 10:39:45 +00001150 vregs_.SetSize(number_of_vregs);
1151 for (size_t i = 0; i < number_of_vregs; i++) {
David Brazdil1abb4192015-02-17 18:33:36 +00001152 vregs_.Put(i, HUserRecord<HEnvironment*>());
David Brazdiled596192015-01-23 10:39:45 +00001153 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001154
1155 locations_.SetSize(number_of_vregs);
1156 for (size_t i = 0; i < number_of_vregs; ++i) {
1157 locations_.Put(i, Location());
1158 }
1159 }
1160
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001161 HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001162 : HEnvironment(arena,
1163 to_copy.Size(),
1164 to_copy.GetDexFile(),
1165 to_copy.GetMethodIdx(),
1166 to_copy.GetDexPc(),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001167 to_copy.GetInvokeType(),
1168 holder) {}
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001169
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001170 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001171 if (parent_ != nullptr) {
1172 parent_->SetAndCopyParentChain(allocator, parent);
1173 } else {
1174 parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
1175 parent_->CopyFrom(parent);
1176 if (parent->GetParent() != nullptr) {
1177 parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1178 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001179 }
David Brazdiled596192015-01-23 10:39:45 +00001180 }
1181
Nicolas Geoffray8c0c91a2015-05-07 11:46:05 +01001182 void CopyFrom(const GrowableArray<HInstruction*>& locals);
1183 void CopyFrom(HEnvironment* environment);
1184
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001185 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1186 // input to the loop phi instead. This is for inserting instructions that
1187 // require an environment (like HDeoptimization) in the loop pre-header.
1188 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
David Brazdiled596192015-01-23 10:39:45 +00001189
1190 void SetRawEnvAt(size_t index, HInstruction* instruction) {
David Brazdil1abb4192015-02-17 18:33:36 +00001191 vregs_.Put(index, HUserRecord<HEnvironment*>(instruction));
David Brazdiled596192015-01-23 10:39:45 +00001192 }
1193
1194 HInstruction* GetInstructionAt(size_t index) const {
David Brazdil1abb4192015-02-17 18:33:36 +00001195 return vregs_.Get(index).GetInstruction();
David Brazdiled596192015-01-23 10:39:45 +00001196 }
1197
David Brazdil1abb4192015-02-17 18:33:36 +00001198 void RemoveAsUserOfInput(size_t index) const;
David Brazdiled596192015-01-23 10:39:45 +00001199
1200 size_t Size() const { return vregs_.Size(); }
1201
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001202 HEnvironment* GetParent() const { return parent_; }
1203
1204 void SetLocationAt(size_t index, Location location) {
1205 locations_.Put(index, location);
1206 }
1207
1208 Location GetLocationAt(size_t index) const {
1209 return locations_.Get(index);
1210 }
1211
1212 uint32_t GetDexPc() const {
1213 return dex_pc_;
1214 }
1215
1216 uint32_t GetMethodIdx() const {
1217 return method_idx_;
1218 }
1219
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001220 InvokeType GetInvokeType() const {
1221 return invoke_type_;
1222 }
1223
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001224 const DexFile& GetDexFile() const {
1225 return dex_file_;
1226 }
1227
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001228 HInstruction* GetHolder() const {
1229 return holder_;
1230 }
1231
David Brazdiled596192015-01-23 10:39:45 +00001232 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001233 // Record instructions' use entries of this environment for constant-time removal.
1234 // It should only be called by HInstruction when a new environment use is added.
1235 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1236 DCHECK(env_use->GetUser() == this);
1237 size_t index = env_use->GetIndex();
1238 vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use));
1239 }
David Brazdiled596192015-01-23 10:39:45 +00001240
David Brazdil1abb4192015-02-17 18:33:36 +00001241 GrowableArray<HUserRecord<HEnvironment*> > vregs_;
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001242 GrowableArray<Location> locations_;
1243 HEnvironment* parent_;
1244 const DexFile& dex_file_;
1245 const uint32_t method_idx_;
1246 const uint32_t dex_pc_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001247 const InvokeType invoke_type_;
David Brazdiled596192015-01-23 10:39:45 +00001248
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001249 // The instruction that holds this environment. Only used in debug mode
1250 // to ensure the graph is consistent.
1251 HInstruction* const holder_;
1252
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001253 friend class HInstruction;
David Brazdiled596192015-01-23 10:39:45 +00001254
1255 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1256};
1257
Calin Juravleacf735c2015-02-12 15:25:22 +00001258class ReferenceTypeInfo : ValueObject {
1259 public:
Calin Juravleb1498f62015-02-16 13:13:29 +00001260 typedef Handle<mirror::Class> TypeHandle;
1261
1262 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
1263 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1264 if (type_handle->IsObjectClass()) {
1265 // Override the type handle to be consistent with the case when we get to
1266 // Top but don't have the Object class available. It avoids having to guess
1267 // what value the type_handle has when it's Top.
1268 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1269 } else {
1270 return ReferenceTypeInfo(type_handle, is_exact, false);
1271 }
1272 }
1273
1274 static ReferenceTypeInfo CreateTop(bool is_exact) {
1275 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
Calin Juravleacf735c2015-02-12 15:25:22 +00001276 }
1277
1278 bool IsExact() const { return is_exact_; }
1279 bool IsTop() const { return is_top_; }
1280
1281 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
1282
Calin Juravleb1498f62015-02-16 13:13:29 +00001283 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Calin Juravleacf735c2015-02-12 15:25:22 +00001284 if (IsTop()) {
1285 // Top (equivalent for java.lang.Object) is supertype of anything.
1286 return true;
1287 }
1288 if (rti.IsTop()) {
1289 // If we get here `this` is not Top() so it can't be a supertype.
1290 return false;
1291 }
1292 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
1293 }
1294
1295 // Returns true if the type information provide the same amount of details.
1296 // Note that it does not mean that the instructions have the same actual type
1297 // (e.g. tops are equal but they can be the result of a merge).
1298 bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1299 if (IsExact() != rti.IsExact()) {
1300 return false;
1301 }
1302 if (IsTop() && rti.IsTop()) {
1303 // `Top` means java.lang.Object, so the types are equivalent.
1304 return true;
1305 }
1306 if (IsTop() || rti.IsTop()) {
1307 // If only one is top or object than they are not equivalent.
1308 // NB: We need this extra check because the type_handle of `Top` is invalid
1309 // and we cannot inspect its reference.
1310 return false;
1311 }
1312
1313 // Finally check the types.
1314 return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
1315 }
1316
1317 private:
Calin Juravleb1498f62015-02-16 13:13:29 +00001318 ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
1319 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
1320 : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
1321
Calin Juravleacf735c2015-02-12 15:25:22 +00001322 // The class of the object.
Calin Juravleb1498f62015-02-16 13:13:29 +00001323 TypeHandle type_handle_;
Calin Juravleacf735c2015-02-12 15:25:22 +00001324 // Whether or not the type is exact or a superclass of the actual type.
Calin Juravleb1498f62015-02-16 13:13:29 +00001325 // Whether or not we have any information about this type.
Calin Juravleacf735c2015-02-12 15:25:22 +00001326 bool is_exact_;
1327 // A true value here means that the object type should be java.lang.Object.
1328 // We don't have access to the corresponding mirror object every time so this
1329 // flag acts as a substitute. When true, the TypeHandle refers to a null
1330 // pointer and should not be used.
1331 bool is_top_;
1332};
1333
1334std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
1335
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001336class HInstruction : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001337 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001338 explicit HInstruction(SideEffects side_effects)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001339 : previous_(nullptr),
1340 next_(nullptr),
1341 block_(nullptr),
1342 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001343 ssa_index_(-1),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001344 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001345 locations_(nullptr),
1346 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001347 lifetime_position_(kNoLifetime),
Calin Juravleb1498f62015-02-16 13:13:29 +00001348 side_effects_(side_effects),
1349 reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001350
Dave Allison20dfc792014-06-16 20:44:29 -07001351 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001352
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001353#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001354 enum InstructionKind {
1355 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1356 };
1357#undef DECLARE_KIND
1358
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001359 HInstruction* GetNext() const { return next_; }
1360 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001361
Calin Juravle77520bc2015-01-12 18:45:46 +00001362 HInstruction* GetNextDisregardingMoves() const;
1363 HInstruction* GetPreviousDisregardingMoves() const;
1364
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001365 HBasicBlock* GetBlock() const { return block_; }
1366 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001367 bool IsInBlock() const { return block_ != nullptr; }
1368 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray3ac17fc2014-08-06 23:02:54 +01001369 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001370
Roland Levillain6b879dd2014-09-22 17:13:44 +01001371 virtual size_t InputCount() const = 0;
David Brazdil1abb4192015-02-17 18:33:36 +00001372 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001373
1374 virtual void Accept(HGraphVisitor* visitor) = 0;
1375 virtual const char* DebugName() const = 0;
1376
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001377 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
David Brazdil1abb4192015-02-17 18:33:36 +00001378 void SetRawInputAt(size_t index, HInstruction* input) {
1379 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1380 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001381
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001382 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001383 virtual uint32_t GetDexPc() const {
1384 LOG(FATAL) << "GetDexPc() cannot be called on an instruction that"
1385 " does not need an environment";
1386 UNREACHABLE();
1387 }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001388 virtual bool IsControlFlow() const { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01001389 virtual bool CanThrow() const { return false; }
Roland Levillain72bceff2014-09-15 18:29:00 +01001390 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001391
Calin Juravle10e244f2015-01-26 18:54:32 +00001392 // Does not apply for all instructions, but having this at top level greatly
1393 // simplifies the null check elimination.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001394 virtual bool CanBeNull() const {
1395 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1396 return true;
1397 }
Calin Juravle10e244f2015-01-26 18:54:32 +00001398
Calin Juravle641547a2015-04-21 22:08:51 +01001399 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj) const {
1400 UNUSED(obj);
1401 return false;
1402 }
Calin Juravle77520bc2015-01-12 18:45:46 +00001403
Calin Juravleacf735c2015-02-12 15:25:22 +00001404 void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
Calin Juravle61d544b2015-02-23 16:46:57 +00001405 DCHECK_EQ(GetType(), Primitive::kPrimNot);
Calin Juravleacf735c2015-02-12 15:25:22 +00001406 reference_type_info_ = reference_type_info;
1407 }
1408
Calin Juravle61d544b2015-02-23 16:46:57 +00001409 ReferenceTypeInfo GetReferenceTypeInfo() const {
1410 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1411 return reference_type_info_;
1412 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001413
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001414 void AddUseAt(HInstruction* user, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +00001415 DCHECK(user != nullptr);
1416 HUseListNode<HInstruction*>* use =
1417 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1418 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001419 }
1420
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001421 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +01001422 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +00001423 HUseListNode<HEnvironment*>* env_use =
1424 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1425 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001426 }
1427
David Brazdil1abb4192015-02-17 18:33:36 +00001428 void RemoveAsUserOfInput(size_t input) {
1429 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1430 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1431 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001432
David Brazdil1abb4192015-02-17 18:33:36 +00001433 const HUseList<HInstruction*>& GetUses() const { return uses_; }
1434 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001435
David Brazdiled596192015-01-23 10:39:45 +00001436 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
1437 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001438 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
Alexandre Rames188d4312015-04-09 18:30:21 +01001439 bool HasOnlyOneNonEnvironmentUse() const {
1440 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1441 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001442
Roland Levillain6c82d402014-10-13 16:10:27 +01001443 // Does this instruction strictly dominate `other_instruction`?
1444 // Returns false if this instruction and `other_instruction` are the same.
1445 // Aborts if this instruction and `other_instruction` are both phis.
1446 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +01001447
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001448 int GetId() const { return id_; }
1449 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001450
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001451 int GetSsaIndex() const { return ssa_index_; }
1452 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
1453 bool HasSsaIndex() const { return ssa_index_ != -1; }
1454
1455 bool HasEnvironment() const { return environment_ != nullptr; }
1456 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001457 // Set the `environment_` field. Raw because this method does not
1458 // update the uses lists.
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001459 void SetRawEnvironment(HEnvironment* environment) {
1460 DCHECK(environment_ == nullptr);
1461 DCHECK_EQ(environment->GetHolder(), this);
1462 environment_ = environment;
1463 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001464
1465 // Set the environment of this instruction, copying it from `environment`. While
1466 // copying, the uses lists are being updated.
1467 void CopyEnvironmentFrom(HEnvironment* environment) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001468 DCHECK(environment_ == nullptr);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001469 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001470 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001471 environment_->CopyFrom(environment);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001472 if (environment->GetParent() != nullptr) {
1473 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1474 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001475 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001476
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001477 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
1478 HBasicBlock* block) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001479 DCHECK(environment_ == nullptr);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001480 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001481 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001482 environment_->CopyFromWithLoopPhiAdjustment(environment, block);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001483 if (environment->GetParent() != nullptr) {
1484 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1485 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001486 }
1487
Nicolas Geoffray39468442014-09-02 15:17:15 +01001488 // Returns the number of entries in the environment. Typically, that is the
1489 // number of dex registers in a method. It could be more in case of inlining.
1490 size_t EnvironmentSize() const;
1491
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001492 LocationSummary* GetLocations() const { return locations_; }
1493 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001494
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001495 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001496 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001497
Alexandre Rames188d4312015-04-09 18:30:21 +01001498 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1499 // uses of this instruction by `other` are *not* updated.
1500 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
1501 ReplaceWith(other);
1502 other->ReplaceInput(this, use_index);
1503 }
1504
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001505 // Move `this` instruction before `cursor`.
1506 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001507
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001508#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +01001509 bool Is##type() const { return (As##type() != nullptr); } \
1510 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001511 virtual H##type* As##type() { return nullptr; }
1512
1513 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
1514#undef INSTRUCTION_TYPE_CHECK
1515
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001516 // Returns whether the instruction can be moved within the graph.
1517 virtual bool CanBeMoved() const { return false; }
1518
1519 // Returns whether the two instructions are of the same kind.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001520 virtual bool InstructionTypeEquals(HInstruction* other) const {
1521 UNUSED(other);
1522 return false;
1523 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001524
1525 // Returns whether any data encoded in the two instructions is equal.
1526 // This method does not look at the inputs. Both instructions must be
1527 // of the same type, otherwise the method has undefined behavior.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001528 virtual bool InstructionDataEquals(HInstruction* other) const {
1529 UNUSED(other);
1530 return false;
1531 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001532
1533 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00001534 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001535 // 2) Their inputs are identical.
1536 bool Equals(HInstruction* other) const;
1537
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001538 virtual InstructionKind GetKind() const = 0;
1539
1540 virtual size_t ComputeHashCode() const {
1541 size_t result = GetKind();
1542 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1543 result = (result * 31) + InputAt(i)->GetId();
1544 }
1545 return result;
1546 }
1547
1548 SideEffects GetSideEffects() const { return side_effects_; }
1549
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001550 size_t GetLifetimePosition() const { return lifetime_position_; }
1551 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
1552 LiveInterval* GetLiveInterval() const { return live_interval_; }
1553 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
1554 bool HasLiveInterval() const { return live_interval_ != nullptr; }
1555
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00001556 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1557
1558 // Returns whether the code generation of the instruction will require to have access
1559 // to the current method. Such instructions are:
1560 // (1): Instructions that require an environment, as calling the runtime requires
1561 // to walk the stack and have the current method stored at a specific stack address.
1562 // (2): Object literals like classes and strings, that are loaded from the dex cache
1563 // fields of the current method.
1564 bool NeedsCurrentMethod() const {
1565 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1566 }
1567
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001568 virtual bool NeedsDexCache() const { return false; }
1569
David Brazdil1abb4192015-02-17 18:33:36 +00001570 protected:
1571 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
1572 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
1573
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001574 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001575 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
1576
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001577 HInstruction* previous_;
1578 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001579 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001580
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001581 // An instruction gets an id when it is added to the graph.
1582 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01001583 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001584 int id_;
1585
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001586 // When doing liveness analysis, instructions that have uses get an SSA index.
1587 int ssa_index_;
1588
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001589 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00001590 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001591
1592 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00001593 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001594
Nicolas Geoffray39468442014-09-02 15:17:15 +01001595 // The environment associated with this instruction. Not null if the instruction
1596 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001597 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001598
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001599 // Set by the code generator.
1600 LocationSummary* locations_;
1601
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001602 // Set by the liveness analysis.
1603 LiveInterval* live_interval_;
1604
1605 // Set by the liveness analysis, this is the position in a linear
1606 // order of blocks where this instruction's live interval start.
1607 size_t lifetime_position_;
1608
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001609 const SideEffects side_effects_;
1610
Calin Juravleacf735c2015-02-12 15:25:22 +00001611 // TODO: for primitive types this should be marked as invalid.
1612 ReferenceTypeInfo reference_type_info_;
1613
David Brazdil1abb4192015-02-17 18:33:36 +00001614 friend class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001615 friend class HBasicBlock;
David Brazdil1abb4192015-02-17 18:33:36 +00001616 friend class HEnvironment;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001617 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001618 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001619
1620 DISALLOW_COPY_AND_ASSIGN(HInstruction);
1621};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001622std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001623
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001624class HInputIterator : public ValueObject {
1625 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001626 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001627
1628 bool Done() const { return index_ == instruction_->InputCount(); }
1629 HInstruction* Current() const { return instruction_->InputAt(index_); }
1630 void Advance() { index_++; }
1631
1632 private:
1633 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001634 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001635
1636 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1637};
1638
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001639class HInstructionIterator : public ValueObject {
1640 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001641 explicit HInstructionIterator(const HInstructionList& instructions)
1642 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001643 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001644 }
1645
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001646 bool Done() const { return instruction_ == nullptr; }
1647 HInstruction* Current() const { return instruction_; }
1648 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001649 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001650 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001651 }
1652
1653 private:
1654 HInstruction* instruction_;
1655 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001656
1657 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001658};
1659
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001660class HBackwardInstructionIterator : public ValueObject {
1661 public:
1662 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1663 : instruction_(instructions.last_instruction_) {
1664 next_ = Done() ? nullptr : instruction_->GetPrevious();
1665 }
1666
1667 bool Done() const { return instruction_ == nullptr; }
1668 HInstruction* Current() const { return instruction_; }
1669 void Advance() {
1670 instruction_ = next_;
1671 next_ = Done() ? nullptr : instruction_->GetPrevious();
1672 }
1673
1674 private:
1675 HInstruction* instruction_;
1676 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001677
1678 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001679};
1680
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001681// An embedded container with N elements of type T. Used (with partial
1682// specialization for N=0) because embedded arrays cannot have size 0.
1683template<typename T, intptr_t N>
1684class EmbeddedArray {
1685 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001686 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001687
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001688 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001689
1690 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001691 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001692 return elements_[i];
1693 }
1694
1695 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001696 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001697 return elements_[i];
1698 }
1699
1700 const T& At(intptr_t i) const {
1701 return (*this)[i];
1702 }
1703
1704 void SetAt(intptr_t i, const T& val) {
1705 (*this)[i] = val;
1706 }
1707
1708 private:
1709 T elements_[N];
1710};
1711
1712template<typename T>
1713class EmbeddedArray<T, 0> {
1714 public:
1715 intptr_t length() const { return 0; }
1716 const T& operator[](intptr_t i) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001717 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001718 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001719 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001720 }
1721 T& operator[](intptr_t i) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001722 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001723 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001724 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001725 }
1726};
1727
1728template<intptr_t N>
1729class HTemplateInstruction: public HInstruction {
1730 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001731 HTemplateInstruction<N>(SideEffects side_effects)
1732 : HInstruction(side_effects), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07001733 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001734
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001735 size_t InputCount() const OVERRIDE { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001736
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001737 protected:
David Brazdil1abb4192015-02-17 18:33:36 +00001738 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; }
1739
1740 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
1741 inputs_[i] = input;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001742 }
1743
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001744 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001745 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001746
1747 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001748};
1749
Dave Allison20dfc792014-06-16 20:44:29 -07001750template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001751class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07001752 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001753 HExpression<N>(Primitive::Type type, SideEffects side_effects)
1754 : HTemplateInstruction<N>(side_effects), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07001755 virtual ~HExpression() {}
1756
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001757 Primitive::Type GetType() const OVERRIDE { return type_; }
Dave Allison20dfc792014-06-16 20:44:29 -07001758
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001759 protected:
1760 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07001761};
1762
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001763// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1764// instruction that branches to the exit block.
1765class HReturnVoid : public HTemplateInstruction<0> {
1766 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001767 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001768
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001769 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001770
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001771 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001772
1773 private:
1774 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1775};
1776
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001777// Represents dex's RETURN opcodes. A HReturn is a control flow
1778// instruction that branches to the exit block.
1779class HReturn : public HTemplateInstruction<1> {
1780 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001781 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001782 SetRawInputAt(0, value);
1783 }
1784
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001785 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001786
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001787 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001788
1789 private:
1790 DISALLOW_COPY_AND_ASSIGN(HReturn);
1791};
1792
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001793// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001794// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001795// exit block.
1796class HExit : public HTemplateInstruction<0> {
1797 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001798 HExit() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001799
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001800 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001801
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001802 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001803
1804 private:
1805 DISALLOW_COPY_AND_ASSIGN(HExit);
1806};
1807
1808// Jumps from one block to another.
1809class HGoto : public HTemplateInstruction<0> {
1810 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001811 HGoto() : HTemplateInstruction(SideEffects::None()) {}
1812
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001813 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001814
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001815 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001816 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001817 }
1818
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001819 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001820
1821 private:
1822 DISALLOW_COPY_AND_ASSIGN(HGoto);
1823};
1824
Dave Allison20dfc792014-06-16 20:44:29 -07001825
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001826// Conditional branch. A block ending with an HIf instruction must have
1827// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001828class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001829 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001830 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001831 SetRawInputAt(0, input);
1832 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001833
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001834 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001835
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001836 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001837 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001838 }
1839
1840 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001841 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001842 }
1843
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001844 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001845
1846 private:
1847 DISALLOW_COPY_AND_ASSIGN(HIf);
1848};
1849
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001850// Deoptimize to interpreter, upon checking a condition.
1851class HDeoptimize : public HTemplateInstruction<1> {
1852 public:
1853 HDeoptimize(HInstruction* cond, uint32_t dex_pc)
1854 : HTemplateInstruction(SideEffects::None()),
1855 dex_pc_(dex_pc) {
1856 SetRawInputAt(0, cond);
1857 }
1858
1859 bool NeedsEnvironment() const OVERRIDE { return true; }
1860 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001861 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001862
1863 DECLARE_INSTRUCTION(Deoptimize);
1864
1865 private:
1866 uint32_t dex_pc_;
1867
1868 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
1869};
1870
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001871// Represents the ArtMethod that was passed as a first argument to
1872// the method. It is used by instructions that depend on it, like
1873// instructions that work with the dex cache.
1874class HCurrentMethod : public HExpression<0> {
1875 public:
1876 HCurrentMethod() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
1877
1878 DECLARE_INSTRUCTION(CurrentMethod);
1879
1880 private:
1881 DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
1882};
1883
Roland Levillain88cb1752014-10-20 16:36:47 +01001884class HUnaryOperation : public HExpression<1> {
1885 public:
1886 HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1887 : HExpression(result_type, SideEffects::None()) {
1888 SetRawInputAt(0, input);
1889 }
1890
1891 HInstruction* GetInput() const { return InputAt(0); }
1892 Primitive::Type GetResultType() const { return GetType(); }
1893
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001894 bool CanBeMoved() const OVERRIDE { return true; }
1895 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001896 UNUSED(other);
1897 return true;
1898 }
Roland Levillain88cb1752014-10-20 16:36:47 +01001899
Roland Levillain9240d6a2014-10-20 16:47:04 +01001900 // Try to statically evaluate `operation` and return a HConstant
1901 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001902 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001903 HConstant* TryStaticEvaluation() const;
1904
1905 // Apply this operation to `x`.
1906 virtual int32_t Evaluate(int32_t x) const = 0;
1907 virtual int64_t Evaluate(int64_t x) const = 0;
1908
Roland Levillain88cb1752014-10-20 16:36:47 +01001909 DECLARE_INSTRUCTION(UnaryOperation);
1910
1911 private:
1912 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1913};
1914
Dave Allison20dfc792014-06-16 20:44:29 -07001915class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001916 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001917 HBinaryOperation(Primitive::Type result_type,
1918 HInstruction* left,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001919 HInstruction* right) : HExpression(result_type, SideEffects::None()) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001920 SetRawInputAt(0, left);
1921 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001922 }
1923
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001924 HInstruction* GetLeft() const { return InputAt(0); }
1925 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07001926 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001927
Mingyao Yangdc5ac732015-02-25 11:28:05 -08001928 virtual bool IsCommutative() const { return false; }
1929
1930 // Put constant on the right.
1931 // Returns whether order is changed.
1932 bool OrderInputsWithConstantOnTheRight() {
1933 HInstruction* left = InputAt(0);
1934 HInstruction* right = InputAt(1);
1935 if (left->IsConstant() && !right->IsConstant()) {
1936 ReplaceInput(right, 0);
1937 ReplaceInput(left, 1);
1938 return true;
1939 }
1940 return false;
1941 }
1942
1943 // Order inputs by instruction id, but favor constant on the right side.
1944 // This helps GVN for commutative ops.
1945 void OrderInputs() {
1946 DCHECK(IsCommutative());
1947 HInstruction* left = InputAt(0);
1948 HInstruction* right = InputAt(1);
1949 if (left == right || (!left->IsConstant() && right->IsConstant())) {
1950 return;
1951 }
1952 if (OrderInputsWithConstantOnTheRight()) {
1953 return;
1954 }
1955 // Order according to instruction id.
1956 if (left->GetId() > right->GetId()) {
1957 ReplaceInput(right, 0);
1958 ReplaceInput(left, 1);
1959 }
1960 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001961
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001962 bool CanBeMoved() const OVERRIDE { return true; }
1963 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001964 UNUSED(other);
1965 return true;
1966 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001967
Roland Levillain9240d6a2014-10-20 16:47:04 +01001968 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01001969 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001970 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001971 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01001972
1973 // Apply this operation to `x` and `y`.
1974 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1975 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1976
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001977 // Returns an input that can legally be used as the right input and is
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001978 // constant, or null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001979 HConstant* GetConstantRight() const;
1980
1981 // If `GetConstantRight()` returns one of the input, this returns the other
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001982 // one. Otherwise it returns null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001983 HInstruction* GetLeastConstantLeft() const;
1984
Roland Levillainccc07a92014-09-16 14:48:16 +01001985 DECLARE_INSTRUCTION(BinaryOperation);
1986
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001987 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001988 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1989};
1990
Dave Allison20dfc792014-06-16 20:44:29 -07001991class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001992 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001993 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001994 : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1995 needs_materialization_(true) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001996
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001997 bool NeedsMaterialization() const { return needs_materialization_; }
1998 void ClearNeedsMaterialization() { needs_materialization_ = false; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001999
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002000 // For code generation purposes, returns whether this instruction is just before
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07002001 // `instruction`, and disregard moves in between.
2002 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002003
Dave Allison20dfc792014-06-16 20:44:29 -07002004 DECLARE_INSTRUCTION(Condition);
2005
2006 virtual IfCondition GetCondition() const = 0;
2007
2008 private:
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002009 // For register allocation purposes, returns whether this instruction needs to be
2010 // materialized (that is, not just be in the processor flags).
2011 bool needs_materialization_;
2012
Dave Allison20dfc792014-06-16 20:44:29 -07002013 DISALLOW_COPY_AND_ASSIGN(HCondition);
2014};
2015
2016// Instruction to check if two inputs are equal to each other.
2017class HEqual : public HCondition {
2018 public:
2019 HEqual(HInstruction* first, HInstruction* second)
2020 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002021
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002022 bool IsCommutative() const OVERRIDE { return true; }
2023
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002024 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002025 return x == y ? 1 : 0;
2026 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002027 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002028 return x == y ? 1 : 0;
2029 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002030
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002031 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002032
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002033 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002034 return kCondEQ;
2035 }
2036
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002037 private:
2038 DISALLOW_COPY_AND_ASSIGN(HEqual);
2039};
2040
Dave Allison20dfc792014-06-16 20:44:29 -07002041class HNotEqual : public HCondition {
2042 public:
2043 HNotEqual(HInstruction* first, HInstruction* second)
2044 : HCondition(first, second) {}
2045
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002046 bool IsCommutative() const OVERRIDE { return true; }
2047
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002048 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002049 return x != y ? 1 : 0;
2050 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002051 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002052 return x != y ? 1 : 0;
2053 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002054
Dave Allison20dfc792014-06-16 20:44:29 -07002055 DECLARE_INSTRUCTION(NotEqual);
2056
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002057 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002058 return kCondNE;
2059 }
2060
2061 private:
2062 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
2063};
2064
2065class HLessThan : public HCondition {
2066 public:
2067 HLessThan(HInstruction* first, HInstruction* second)
2068 : HCondition(first, second) {}
2069
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002070 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002071 return x < y ? 1 : 0;
2072 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002073 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002074 return x < y ? 1 : 0;
2075 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002076
Dave Allison20dfc792014-06-16 20:44:29 -07002077 DECLARE_INSTRUCTION(LessThan);
2078
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002079 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002080 return kCondLT;
2081 }
2082
2083 private:
2084 DISALLOW_COPY_AND_ASSIGN(HLessThan);
2085};
2086
2087class HLessThanOrEqual : public HCondition {
2088 public:
2089 HLessThanOrEqual(HInstruction* first, HInstruction* second)
2090 : HCondition(first, second) {}
2091
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002092 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002093 return x <= y ? 1 : 0;
2094 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002095 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002096 return x <= y ? 1 : 0;
2097 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002098
Dave Allison20dfc792014-06-16 20:44:29 -07002099 DECLARE_INSTRUCTION(LessThanOrEqual);
2100
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002101 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002102 return kCondLE;
2103 }
2104
2105 private:
2106 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
2107};
2108
2109class HGreaterThan : public HCondition {
2110 public:
2111 HGreaterThan(HInstruction* first, HInstruction* second)
2112 : HCondition(first, second) {}
2113
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002114 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002115 return x > y ? 1 : 0;
2116 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002117 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002118 return x > y ? 1 : 0;
2119 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002120
Dave Allison20dfc792014-06-16 20:44:29 -07002121 DECLARE_INSTRUCTION(GreaterThan);
2122
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002123 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002124 return kCondGT;
2125 }
2126
2127 private:
2128 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
2129};
2130
2131class HGreaterThanOrEqual : public HCondition {
2132 public:
2133 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
2134 : HCondition(first, second) {}
2135
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002136 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002137 return x >= y ? 1 : 0;
2138 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002139 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002140 return x >= y ? 1 : 0;
2141 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002142
Dave Allison20dfc792014-06-16 20:44:29 -07002143 DECLARE_INSTRUCTION(GreaterThanOrEqual);
2144
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002145 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002146 return kCondGE;
2147 }
2148
2149 private:
2150 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
2151};
2152
2153
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002154// Instruction to check how two inputs compare to each other.
2155// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
2156class HCompare : public HBinaryOperation {
2157 public:
Calin Juravleddb7df22014-11-25 20:56:51 +00002158 // The bias applies for floating point operations and indicates how NaN
2159 // comparisons are treated:
2160 enum Bias {
2161 kNoBias, // bias is not applicable (i.e. for long operation)
2162 kGtBias, // return 1 for NaN comparisons
2163 kLtBias, // return -1 for NaN comparisons
2164 };
2165
2166 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias)
2167 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002168 DCHECK_EQ(type, first->GetType());
2169 DCHECK_EQ(type, second->GetType());
2170 }
2171
Calin Juravleddb7df22014-11-25 20:56:51 +00002172 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002173 return
2174 x == y ? 0 :
2175 x > y ? 1 :
2176 -1;
2177 }
Calin Juravleddb7df22014-11-25 20:56:51 +00002178
2179 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002180 return
2181 x == y ? 0 :
2182 x > y ? 1 :
2183 -1;
2184 }
2185
Calin Juravleddb7df22014-11-25 20:56:51 +00002186 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2187 return bias_ == other->AsCompare()->bias_;
2188 }
2189
2190 bool IsGtBias() { return bias_ == kGtBias; }
2191
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002192 DECLARE_INSTRUCTION(Compare);
2193
2194 private:
Calin Juravleddb7df22014-11-25 20:56:51 +00002195 const Bias bias_;
2196
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002197 DISALLOW_COPY_AND_ASSIGN(HCompare);
2198};
2199
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002200// A local in the graph. Corresponds to a Dex register.
2201class HLocal : public HTemplateInstruction<0> {
2202 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002203 explicit HLocal(uint16_t reg_number)
2204 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002205
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002206 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002207
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002208 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002209
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002210 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002211 // The Dex register number.
2212 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002213
2214 DISALLOW_COPY_AND_ASSIGN(HLocal);
2215};
2216
2217// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07002218class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002219 public:
Roland Levillain5799fc02014-09-25 12:15:20 +01002220 HLoadLocal(HLocal* local, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002221 : HExpression(type, SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002222 SetRawInputAt(0, local);
2223 }
2224
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002225 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2226
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002227 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002228
2229 private:
2230 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
2231};
2232
2233// Store a value in a given local. This instruction has two inputs: the value
2234// and the local.
2235class HStoreLocal : public HTemplateInstruction<2> {
2236 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002237 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002238 SetRawInputAt(0, local);
2239 SetRawInputAt(1, value);
2240 }
2241
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002242 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2243
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002244 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002245
2246 private:
2247 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
2248};
2249
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002250class HConstant : public HExpression<0> {
2251 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002252 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
2253
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002254 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002255
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002256 virtual bool IsMinusOne() const { return false; }
2257 virtual bool IsZero() const { return false; }
2258 virtual bool IsOne() const { return false; }
2259
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002260 DECLARE_INSTRUCTION(Constant);
2261
2262 private:
2263 DISALLOW_COPY_AND_ASSIGN(HConstant);
2264};
2265
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002266class HFloatConstant : public HConstant {
2267 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002268 float GetValue() const { return value_; }
2269
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002270 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002271 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
2272 bit_cast<uint32_t, float>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002273 }
2274
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002275 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002276
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002277 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002278 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002279 }
2280 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002281 return value_ == 0.0f;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002282 }
2283 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002284 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
2285 }
2286 bool IsNaN() const {
2287 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002288 }
2289
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002290 DECLARE_INSTRUCTION(FloatConstant);
2291
2292 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002293 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002294 explicit HFloatConstant(int32_t value)
2295 : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002296
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002297 const float value_;
2298
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002299 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002300 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002301 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002302 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2303};
2304
2305class HDoubleConstant : public HConstant {
2306 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002307 double GetValue() const { return value_; }
2308
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002309 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002310 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
2311 bit_cast<uint64_t, double>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002312 }
2313
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002314 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002315
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002316 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002317 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002318 }
2319 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002320 return value_ == 0.0;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002321 }
2322 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002323 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
2324 }
2325 bool IsNaN() const {
2326 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002327 }
2328
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002329 DECLARE_INSTRUCTION(DoubleConstant);
2330
2331 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002332 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002333 explicit HDoubleConstant(int64_t value)
2334 : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002335
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002336 const double value_;
2337
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002338 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002339 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002340 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002341 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2342};
2343
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002344class HNullConstant : public HConstant {
2345 public:
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002346 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2347 return true;
2348 }
2349
2350 size_t ComputeHashCode() const OVERRIDE { return 0; }
2351
2352 DECLARE_INSTRUCTION(NullConstant);
2353
2354 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002355 HNullConstant() : HConstant(Primitive::kPrimNot) {}
2356
2357 friend class HGraph;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002358 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2359};
2360
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002361// Constants of the type int. Those can be from Dex instructions, or
2362// synthesized (for example with the if-eqz instruction).
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002363class HIntConstant : public HConstant {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002364 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002365 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002366
Calin Juravle61d544b2015-02-23 16:46:57 +00002367 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002368 return other->AsIntConstant()->value_ == value_;
2369 }
2370
Calin Juravle61d544b2015-02-23 16:46:57 +00002371 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2372
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002373 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2374 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2375 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2376
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002377 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002378
2379 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002380 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
2381
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002382 const int32_t value_;
2383
David Brazdil8d5b8b22015-03-24 10:51:52 +00002384 friend class HGraph;
2385 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
Zheng Xuad4450e2015-04-17 18:48:56 +08002386 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002387 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2388};
2389
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002390class HLongConstant : public HConstant {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002391 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002392 int64_t GetValue() const { return value_; }
2393
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002394 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002395 return other->AsLongConstant()->value_ == value_;
2396 }
2397
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002398 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002399
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002400 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2401 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2402 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2403
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002404 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002405
2406 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002407 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
2408
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002409 const int64_t value_;
2410
David Brazdil8d5b8b22015-03-24 10:51:52 +00002411 friend class HGraph;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002412 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2413};
2414
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002415enum class Intrinsics {
2416#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
2417#include "intrinsics_list.h"
2418 kNone,
2419 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
2420#undef INTRINSICS_LIST
2421#undef OPTIMIZING_INTRINSICS
2422};
2423std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
2424
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002425class HInvoke : public HInstruction {
2426 public:
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002427 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002428
2429 // Runtime needs to walk the stack, so Dex -> Dex calls need to
2430 // know their environment.
Calin Juravle77520bc2015-01-12 18:45:46 +00002431 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002432
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01002433 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002434 SetRawInputAt(index, argument);
2435 }
2436
Roland Levillain3e3d7332015-04-28 11:00:54 +01002437 // Return the number of arguments. This number can be lower than
2438 // the number of inputs returned by InputCount(), as some invoke
2439 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
2440 // inputs at the end of their list of inputs.
2441 uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
2442
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002443 Primitive::Type GetType() const OVERRIDE { return return_type_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002444
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002445 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002446
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002447 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002448 const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002449
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002450 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
2451
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01002452 Intrinsics GetIntrinsic() const {
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002453 return intrinsic_;
2454 }
2455
2456 void SetIntrinsic(Intrinsics intrinsic) {
2457 intrinsic_ = intrinsic;
2458 }
2459
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01002460 bool IsInlined() const {
2461 return GetEnvironment()->GetParent() != nullptr;
2462 }
2463
2464 bool CanThrow() const OVERRIDE { return true; }
2465
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002466 DECLARE_INSTRUCTION(Invoke);
2467
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002468 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002469 HInvoke(ArenaAllocator* arena,
2470 uint32_t number_of_arguments,
Roland Levillain3e3d7332015-04-28 11:00:54 +01002471 uint32_t number_of_other_inputs,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002472 Primitive::Type return_type,
2473 uint32_t dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002474 uint32_t dex_method_index,
2475 InvokeType original_invoke_type)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002476 : HInstruction(SideEffects::All()),
Roland Levillain3e3d7332015-04-28 11:00:54 +01002477 number_of_arguments_(number_of_arguments),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002478 inputs_(arena, number_of_arguments),
2479 return_type_(return_type),
2480 dex_pc_(dex_pc),
2481 dex_method_index_(dex_method_index),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002482 original_invoke_type_(original_invoke_type),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002483 intrinsic_(Intrinsics::kNone) {
Roland Levillain3e3d7332015-04-28 11:00:54 +01002484 uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
2485 inputs_.SetSize(number_of_inputs);
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002486 }
2487
David Brazdil1abb4192015-02-17 18:33:36 +00002488 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
2489 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2490 inputs_.Put(index, input);
2491 }
2492
Roland Levillain3e3d7332015-04-28 11:00:54 +01002493 uint32_t number_of_arguments_;
David Brazdil1abb4192015-02-17 18:33:36 +00002494 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002495 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002496 const uint32_t dex_pc_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002497 const uint32_t dex_method_index_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002498 const InvokeType original_invoke_type_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002499 Intrinsics intrinsic_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002500
2501 private:
2502 DISALLOW_COPY_AND_ASSIGN(HInvoke);
2503};
2504
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002505class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002506 public:
Roland Levillain4c0eb422015-04-24 16:43:49 +01002507 // Requirements of this method call regarding the class
2508 // initialization (clinit) check of its declaring class.
2509 enum class ClinitCheckRequirement {
2510 kNone, // Class already initialized.
2511 kExplicit, // Static call having explicit clinit check as last input.
2512 kImplicit, // Static call implicitly requiring a clinit check.
2513 };
2514
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002515 HInvokeStaticOrDirect(ArenaAllocator* arena,
2516 uint32_t number_of_arguments,
2517 Primitive::Type return_type,
2518 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002519 uint32_t dex_method_index,
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002520 bool is_recursive,
Jeff Hao848f70a2014-01-15 13:49:50 -08002521 int32_t string_init_offset,
Nicolas Geoffray79041292015-03-26 10:05:54 +00002522 InvokeType original_invoke_type,
Roland Levillain4c0eb422015-04-24 16:43:49 +01002523 InvokeType invoke_type,
2524 ClinitCheckRequirement clinit_check_requirement)
Roland Levillain3e3d7332015-04-28 11:00:54 +01002525 : HInvoke(arena,
2526 number_of_arguments,
2527 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
2528 return_type,
2529 dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002530 dex_method_index,
2531 original_invoke_type),
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002532 invoke_type_(invoke_type),
Roland Levillain4c0eb422015-04-24 16:43:49 +01002533 is_recursive_(is_recursive),
Jeff Hao848f70a2014-01-15 13:49:50 -08002534 clinit_check_requirement_(clinit_check_requirement),
2535 string_init_offset_(string_init_offset) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002536
Calin Juravle641547a2015-04-21 22:08:51 +01002537 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2538 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00002539 // We access the method via the dex cache so we can't do an implicit null check.
2540 // TODO: for intrinsics we can generate implicit null checks.
2541 return false;
2542 }
2543
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002544 InvokeType GetInvokeType() const { return invoke_type_; }
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002545 bool IsRecursive() const { return is_recursive_; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002546 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
Jeff Hao848f70a2014-01-15 13:49:50 -08002547 bool IsStringInit() const { return string_init_offset_ != 0; }
2548 int32_t GetStringInitOffset() const { return string_init_offset_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002549
Roland Levillain4c0eb422015-04-24 16:43:49 +01002550 // Is this instruction a call to a static method?
2551 bool IsStatic() const {
2552 return GetInvokeType() == kStatic;
2553 }
2554
Roland Levillain3e3d7332015-04-28 11:00:54 +01002555 // Remove the art::HLoadClass instruction set as last input by
2556 // art::PrepareForRegisterAllocation::VisitClinitCheck in lieu of
2557 // the initial art::HClinitCheck instruction (only relevant for
2558 // static calls with explicit clinit check).
2559 void RemoveLoadClassAsLastInput() {
Roland Levillain4c0eb422015-04-24 16:43:49 +01002560 DCHECK(IsStaticWithExplicitClinitCheck());
2561 size_t last_input_index = InputCount() - 1;
2562 HInstruction* last_input = InputAt(last_input_index);
2563 DCHECK(last_input != nullptr);
Roland Levillain3e3d7332015-04-28 11:00:54 +01002564 DCHECK(last_input->IsLoadClass()) << last_input->DebugName();
Roland Levillain4c0eb422015-04-24 16:43:49 +01002565 RemoveAsUserOfInput(last_input_index);
2566 inputs_.DeleteAt(last_input_index);
2567 clinit_check_requirement_ = ClinitCheckRequirement::kImplicit;
2568 DCHECK(IsStaticWithImplicitClinitCheck());
2569 }
2570
2571 // Is this a call to a static method whose declaring class has an
2572 // explicit intialization check in the graph?
2573 bool IsStaticWithExplicitClinitCheck() const {
2574 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit);
2575 }
2576
2577 // Is this a call to a static method whose declaring class has an
2578 // implicit intialization check requirement?
2579 bool IsStaticWithImplicitClinitCheck() const {
2580 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit);
2581 }
2582
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002583 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002584
Roland Levillain4c0eb422015-04-24 16:43:49 +01002585 protected:
2586 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
2587 const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i);
2588 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) {
2589 HInstruction* input = input_record.GetInstruction();
2590 // `input` is the last input of a static invoke marked as having
2591 // an explicit clinit check. It must either be:
2592 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
2593 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
2594 DCHECK(input != nullptr);
2595 DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName();
2596 }
2597 return input_record;
2598 }
2599
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002600 private:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002601 const InvokeType invoke_type_;
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002602 const bool is_recursive_;
Roland Levillain4c0eb422015-04-24 16:43:49 +01002603 ClinitCheckRequirement clinit_check_requirement_;
Jeff Hao848f70a2014-01-15 13:49:50 -08002604 // Thread entrypoint offset for string init method if this is a string init invoke.
2605 // Note that there are multiple string init methods, each having its own offset.
2606 int32_t string_init_offset_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002607
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002608 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002609};
2610
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002611class HInvokeVirtual : public HInvoke {
2612 public:
2613 HInvokeVirtual(ArenaAllocator* arena,
2614 uint32_t number_of_arguments,
2615 Primitive::Type return_type,
2616 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002617 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002618 uint32_t vtable_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002619 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kVirtual),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002620 vtable_index_(vtable_index) {}
2621
Calin Juravle641547a2015-04-21 22:08:51 +01002622 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002623 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002624 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002625 }
2626
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002627 uint32_t GetVTableIndex() const { return vtable_index_; }
2628
2629 DECLARE_INSTRUCTION(InvokeVirtual);
2630
2631 private:
2632 const uint32_t vtable_index_;
2633
2634 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
2635};
2636
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002637class HInvokeInterface : public HInvoke {
2638 public:
2639 HInvokeInterface(ArenaAllocator* arena,
2640 uint32_t number_of_arguments,
2641 Primitive::Type return_type,
2642 uint32_t dex_pc,
2643 uint32_t dex_method_index,
2644 uint32_t imt_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002645 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kInterface),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002646 imt_index_(imt_index) {}
2647
Calin Juravle641547a2015-04-21 22:08:51 +01002648 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002649 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002650 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002651 }
2652
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002653 uint32_t GetImtIndex() const { return imt_index_; }
2654 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2655
2656 DECLARE_INSTRUCTION(InvokeInterface);
2657
2658 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002659 const uint32_t imt_index_;
2660
2661 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
2662};
2663
Dave Allison20dfc792014-06-16 20:44:29 -07002664class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002665 public:
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002666 HNewInstance(uint32_t dex_pc,
2667 uint16_t type_index,
2668 const DexFile& dex_file,
2669 QuickEntrypointEnum entrypoint)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002670 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2671 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002672 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002673 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002674 entrypoint_(entrypoint) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002675
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002676 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002677 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002678 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002679
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002680 // Calls runtime so needs an environment.
Calin Juravle92a6ed22014-12-02 18:58:03 +00002681 bool NeedsEnvironment() const OVERRIDE { return true; }
2682 // It may throw when called on:
2683 // - interfaces
2684 // - abstract/innaccessible/unknown classes
2685 // TODO: optimize when possible.
2686 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002687
Calin Juravle10e244f2015-01-26 18:54:32 +00002688 bool CanBeNull() const OVERRIDE { return false; }
2689
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002690 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2691
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002692 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002693
2694 private:
2695 const uint32_t dex_pc_;
2696 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002697 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002698 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002699
2700 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
2701};
2702
Roland Levillain88cb1752014-10-20 16:36:47 +01002703class HNeg : public HUnaryOperation {
2704 public:
2705 explicit HNeg(Primitive::Type result_type, HInstruction* input)
2706 : HUnaryOperation(result_type, input) {}
2707
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002708 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
2709 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
Roland Levillain9240d6a2014-10-20 16:47:04 +01002710
Roland Levillain88cb1752014-10-20 16:36:47 +01002711 DECLARE_INSTRUCTION(Neg);
2712
2713 private:
2714 DISALLOW_COPY_AND_ASSIGN(HNeg);
2715};
2716
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002717class HNewArray : public HExpression<1> {
2718 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002719 HNewArray(HInstruction* length,
2720 uint32_t dex_pc,
2721 uint16_t type_index,
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002722 const DexFile& dex_file,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002723 QuickEntrypointEnum entrypoint)
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002724 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2725 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002726 type_index_(type_index),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002727 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002728 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002729 SetRawInputAt(0, length);
2730 }
2731
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002732 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002733 uint16_t GetTypeIndex() const { return type_index_; }
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002734 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002735
2736 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00002737 bool NeedsEnvironment() const OVERRIDE { return true; }
2738
Mingyao Yang0c365e62015-03-31 15:09:29 -07002739 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
2740 bool CanThrow() const OVERRIDE { return true; }
2741
Calin Juravle10e244f2015-01-26 18:54:32 +00002742 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002743
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002744 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2745
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002746 DECLARE_INSTRUCTION(NewArray);
2747
2748 private:
2749 const uint32_t dex_pc_;
2750 const uint16_t type_index_;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002751 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002752 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002753
2754 DISALLOW_COPY_AND_ASSIGN(HNewArray);
2755};
2756
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002757class HAdd : public HBinaryOperation {
2758 public:
2759 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2760 : HBinaryOperation(result_type, left, right) {}
2761
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002762 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002763
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002764 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002765 return x + y;
2766 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002767 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002768 return x + y;
2769 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002770
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002771 DECLARE_INSTRUCTION(Add);
2772
2773 private:
2774 DISALLOW_COPY_AND_ASSIGN(HAdd);
2775};
2776
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002777class HSub : public HBinaryOperation {
2778 public:
2779 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2780 : HBinaryOperation(result_type, left, right) {}
2781
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002782 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002783 return x - y;
2784 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002785 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002786 return x - y;
2787 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002788
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002789 DECLARE_INSTRUCTION(Sub);
2790
2791 private:
2792 DISALLOW_COPY_AND_ASSIGN(HSub);
2793};
2794
Calin Juravle34bacdf2014-10-07 20:23:36 +01002795class HMul : public HBinaryOperation {
2796 public:
2797 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2798 : HBinaryOperation(result_type, left, right) {}
2799
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002800 bool IsCommutative() const OVERRIDE { return true; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002801
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002802 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
2803 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002804
2805 DECLARE_INSTRUCTION(Mul);
2806
2807 private:
2808 DISALLOW_COPY_AND_ASSIGN(HMul);
2809};
2810
Calin Juravle7c4954d2014-10-28 16:57:40 +00002811class HDiv : public HBinaryOperation {
2812 public:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002813 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2814 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00002815
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002816 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002817 // Our graph structure ensures we never have 0 for `y` during constant folding.
2818 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00002819 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002820 return (y == -1) ? -x : x / y;
2821 }
Calin Juravlebacfec32014-11-14 15:54:36 +00002822
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002823 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002824 DCHECK_NE(y, 0);
2825 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2826 return (y == -1) ? -x : x / y;
2827 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00002828
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002829 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002830
Calin Juravle7c4954d2014-10-28 16:57:40 +00002831 DECLARE_INSTRUCTION(Div);
2832
2833 private:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002834 const uint32_t dex_pc_;
2835
Calin Juravle7c4954d2014-10-28 16:57:40 +00002836 DISALLOW_COPY_AND_ASSIGN(HDiv);
2837};
2838
Calin Juravlebacfec32014-11-14 15:54:36 +00002839class HRem : public HBinaryOperation {
2840 public:
2841 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2842 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2843
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002844 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002845 DCHECK_NE(y, 0);
2846 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2847 return (y == -1) ? 0 : x % y;
2848 }
2849
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002850 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002851 DCHECK_NE(y, 0);
2852 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2853 return (y == -1) ? 0 : x % y;
2854 }
2855
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002856 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravlebacfec32014-11-14 15:54:36 +00002857
2858 DECLARE_INSTRUCTION(Rem);
2859
2860 private:
2861 const uint32_t dex_pc_;
2862
2863 DISALLOW_COPY_AND_ASSIGN(HRem);
2864};
2865
Calin Juravled0d48522014-11-04 16:40:20 +00002866class HDivZeroCheck : public HExpression<1> {
2867 public:
2868 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
2869 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2870 SetRawInputAt(0, value);
2871 }
2872
2873 bool CanBeMoved() const OVERRIDE { return true; }
2874
2875 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2876 UNUSED(other);
2877 return true;
2878 }
2879
2880 bool NeedsEnvironment() const OVERRIDE { return true; }
2881 bool CanThrow() const OVERRIDE { return true; }
2882
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002883 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled0d48522014-11-04 16:40:20 +00002884
2885 DECLARE_INSTRUCTION(DivZeroCheck);
2886
2887 private:
2888 const uint32_t dex_pc_;
2889
2890 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
2891};
2892
Calin Juravle9aec02f2014-11-18 23:06:35 +00002893class HShl : public HBinaryOperation {
2894 public:
2895 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2896 : HBinaryOperation(result_type, left, right) {}
2897
2898 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
2899 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
2900
2901 DECLARE_INSTRUCTION(Shl);
2902
2903 private:
2904 DISALLOW_COPY_AND_ASSIGN(HShl);
2905};
2906
2907class HShr : public HBinaryOperation {
2908 public:
2909 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2910 : HBinaryOperation(result_type, left, right) {}
2911
2912 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
2913 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
2914
2915 DECLARE_INSTRUCTION(Shr);
2916
2917 private:
2918 DISALLOW_COPY_AND_ASSIGN(HShr);
2919};
2920
2921class HUShr : public HBinaryOperation {
2922 public:
2923 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2924 : HBinaryOperation(result_type, left, right) {}
2925
2926 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2927 uint32_t ux = static_cast<uint32_t>(x);
2928 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
2929 return static_cast<int32_t>(ux >> uy);
2930 }
2931
2932 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2933 uint64_t ux = static_cast<uint64_t>(x);
2934 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
2935 return static_cast<int64_t>(ux >> uy);
2936 }
2937
2938 DECLARE_INSTRUCTION(UShr);
2939
2940 private:
2941 DISALLOW_COPY_AND_ASSIGN(HUShr);
2942};
2943
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002944class HAnd : public HBinaryOperation {
2945 public:
2946 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2947 : HBinaryOperation(result_type, left, right) {}
2948
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002949 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002950
2951 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
2952 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
2953
2954 DECLARE_INSTRUCTION(And);
2955
2956 private:
2957 DISALLOW_COPY_AND_ASSIGN(HAnd);
2958};
2959
2960class HOr : public HBinaryOperation {
2961 public:
2962 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2963 : HBinaryOperation(result_type, left, right) {}
2964
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002965 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002966
2967 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
2968 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
2969
2970 DECLARE_INSTRUCTION(Or);
2971
2972 private:
2973 DISALLOW_COPY_AND_ASSIGN(HOr);
2974};
2975
2976class HXor : public HBinaryOperation {
2977 public:
2978 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2979 : HBinaryOperation(result_type, left, right) {}
2980
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002981 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002982
2983 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
2984 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
2985
2986 DECLARE_INSTRUCTION(Xor);
2987
2988 private:
2989 DISALLOW_COPY_AND_ASSIGN(HXor);
2990};
2991
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002992// The value of a parameter in this method. Its location depends on
2993// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07002994class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002995 public:
Calin Juravle10e244f2015-01-26 18:54:32 +00002996 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
2997 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002998
2999 uint8_t GetIndex() const { return index_; }
3000
Calin Juravle10e244f2015-01-26 18:54:32 +00003001 bool CanBeNull() const OVERRIDE { return !is_this_; }
3002
Calin Juravle3cd4fc82015-05-14 15:15:42 +01003003 bool IsThis() const { return is_this_; }
3004
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003005 DECLARE_INSTRUCTION(ParameterValue);
3006
3007 private:
3008 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00003009 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003010 const uint8_t index_;
3011
Calin Juravle10e244f2015-01-26 18:54:32 +00003012 // Whether or not the parameter value corresponds to 'this' argument.
3013 const bool is_this_;
3014
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003015 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
3016};
3017
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003018class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003019 public:
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003020 explicit HNot(Primitive::Type result_type, HInstruction* input)
3021 : HUnaryOperation(result_type, input) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003022
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003023 bool CanBeMoved() const OVERRIDE { return true; }
3024 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003025 UNUSED(other);
3026 return true;
3027 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003028
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003029 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
3030 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003031
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003032 DECLARE_INSTRUCTION(Not);
3033
3034 private:
3035 DISALLOW_COPY_AND_ASSIGN(HNot);
3036};
3037
David Brazdil66d126e2015-04-03 16:02:44 +01003038class HBooleanNot : public HUnaryOperation {
3039 public:
3040 explicit HBooleanNot(HInstruction* input)
3041 : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
3042
3043 bool CanBeMoved() const OVERRIDE { return true; }
3044 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3045 UNUSED(other);
3046 return true;
3047 }
3048
3049 int32_t Evaluate(int32_t x) const OVERRIDE {
3050 DCHECK(IsUint<1>(x));
3051 return !x;
3052 }
3053
3054 int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
3055 LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
3056 UNREACHABLE();
3057 }
3058
3059 DECLARE_INSTRUCTION(BooleanNot);
3060
3061 private:
3062 DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
3063};
3064
Roland Levillaindff1f282014-11-05 14:15:05 +00003065class HTypeConversion : public HExpression<1> {
3066 public:
3067 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00003068 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
3069 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00003070 SetRawInputAt(0, input);
3071 DCHECK_NE(input->GetType(), result_type);
3072 }
3073
3074 HInstruction* GetInput() const { return InputAt(0); }
3075 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
3076 Primitive::Type GetResultType() const { return GetType(); }
3077
Roland Levillain624279f2014-12-04 11:54:28 +00003078 // Required by the x86 and ARM code generators when producing calls
3079 // to the runtime.
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003080 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Roland Levillain624279f2014-12-04 11:54:28 +00003081
Roland Levillaindff1f282014-11-05 14:15:05 +00003082 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00003083 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00003084
Mark Mendelle82549b2015-05-06 10:55:34 -04003085 // Try to statically evaluate the conversion and return a HConstant
3086 // containing the result. If the input cannot be converted, return nullptr.
3087 HConstant* TryStaticEvaluation() const;
3088
Roland Levillaindff1f282014-11-05 14:15:05 +00003089 DECLARE_INSTRUCTION(TypeConversion);
3090
3091 private:
Roland Levillain624279f2014-12-04 11:54:28 +00003092 const uint32_t dex_pc_;
3093
Roland Levillaindff1f282014-11-05 14:15:05 +00003094 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
3095};
3096
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00003097static constexpr uint32_t kNoRegNumber = -1;
3098
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003099class HPhi : public HInstruction {
3100 public:
3101 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003102 : HInstruction(SideEffects::None()),
3103 inputs_(arena, number_of_inputs),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003104 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003105 type_(type),
Calin Juravle10e244f2015-01-26 18:54:32 +00003106 is_live_(false),
3107 can_be_null_(true) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003108 inputs_.SetSize(number_of_inputs);
3109 }
3110
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +00003111 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
3112 static Primitive::Type ToPhiType(Primitive::Type type) {
3113 switch (type) {
3114 case Primitive::kPrimBoolean:
3115 case Primitive::kPrimByte:
3116 case Primitive::kPrimShort:
3117 case Primitive::kPrimChar:
3118 return Primitive::kPrimInt;
3119 default:
3120 return type;
3121 }
3122 }
3123
Calin Juravle10e244f2015-01-26 18:54:32 +00003124 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003125
3126 void AddInput(HInstruction* input);
David Brazdil2d7352b2015-04-20 14:52:42 +01003127 void RemoveInputAt(size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003128
Calin Juravle10e244f2015-01-26 18:54:32 +00003129 Primitive::Type GetType() const OVERRIDE { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003130 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003131
Calin Juravle10e244f2015-01-26 18:54:32 +00003132 bool CanBeNull() const OVERRIDE { return can_be_null_; }
3133 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
3134
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003135 uint32_t GetRegNumber() const { return reg_number_; }
3136
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003137 void SetDead() { is_live_ = false; }
3138 void SetLive() { is_live_ = true; }
3139 bool IsDead() const { return !is_live_; }
3140 bool IsLive() const { return is_live_; }
3141
Calin Juravlea4f88312015-04-16 12:57:19 +01003142 // Returns the next equivalent phi (starting from the current one) or null if there is none.
3143 // An equivalent phi is a phi having the same dex register and type.
3144 // It assumes that phis with the same dex register are adjacent.
3145 HPhi* GetNextEquivalentPhiWithSameType() {
3146 HInstruction* next = GetNext();
3147 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
3148 if (next->GetType() == GetType()) {
3149 return next->AsPhi();
3150 }
3151 next = next->GetNext();
3152 }
3153 return nullptr;
3154 }
3155
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003156 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003157
David Brazdil1abb4192015-02-17 18:33:36 +00003158 protected:
3159 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
3160
3161 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
3162 inputs_.Put(index, input);
3163 }
3164
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01003165 private:
David Brazdil1abb4192015-02-17 18:33:36 +00003166 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003167 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003168 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003169 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00003170 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003171
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003172 DISALLOW_COPY_AND_ASSIGN(HPhi);
3173};
3174
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003175class HNullCheck : public HExpression<1> {
3176 public:
3177 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003178 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003179 SetRawInputAt(0, value);
3180 }
3181
Calin Juravle10e244f2015-01-26 18:54:32 +00003182 bool CanBeMoved() const OVERRIDE { return true; }
3183 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003184 UNUSED(other);
3185 return true;
3186 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003187
Calin Juravle10e244f2015-01-26 18:54:32 +00003188 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003189
Calin Juravle10e244f2015-01-26 18:54:32 +00003190 bool CanThrow() const OVERRIDE { return true; }
3191
3192 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003193
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003194 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003195
3196 DECLARE_INSTRUCTION(NullCheck);
3197
3198 private:
3199 const uint32_t dex_pc_;
3200
3201 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
3202};
3203
3204class FieldInfo : public ValueObject {
3205 public:
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003206 FieldInfo(MemberOffset field_offset,
3207 Primitive::Type field_type,
3208 bool is_volatile,
3209 uint32_t index,
3210 const DexFile& dex_file)
3211 : field_offset_(field_offset),
3212 field_type_(field_type),
3213 is_volatile_(is_volatile),
3214 index_(index),
3215 dex_file_(dex_file) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003216
3217 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003218 Primitive::Type GetFieldType() const { return field_type_; }
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003219 uint32_t GetFieldIndex() const { return index_; }
3220 const DexFile& GetDexFile() const { return dex_file_; }
Calin Juravle52c48962014-12-16 17:02:57 +00003221 bool IsVolatile() const { return is_volatile_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003222
3223 private:
3224 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01003225 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00003226 const bool is_volatile_;
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003227 uint32_t index_;
3228 const DexFile& dex_file_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003229};
3230
3231class HInstanceFieldGet : public HExpression<1> {
3232 public:
3233 HInstanceFieldGet(HInstruction* value,
3234 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003235 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003236 bool is_volatile,
3237 uint32_t field_idx,
3238 const DexFile& dex_file)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003239 : HExpression(field_type, SideEffects::DependsOnSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003240 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003241 SetRawInputAt(0, value);
3242 }
3243
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003244 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003245
3246 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3247 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
3248 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003249 }
3250
Calin Juravle641547a2015-04-21 22:08:51 +01003251 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3252 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003253 }
3254
3255 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01003256 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3257 }
3258
Calin Juravle52c48962014-12-16 17:02:57 +00003259 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003260 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003261 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003262 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003263
3264 DECLARE_INSTRUCTION(InstanceFieldGet);
3265
3266 private:
3267 const FieldInfo field_info_;
3268
3269 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
3270};
3271
3272class HInstanceFieldSet : public HTemplateInstruction<2> {
3273 public:
3274 HInstanceFieldSet(HInstruction* object,
3275 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01003276 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003277 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003278 bool is_volatile,
3279 uint32_t field_idx,
3280 const DexFile& dex_file)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003281 : HTemplateInstruction(SideEffects::ChangesSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003282 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003283 value_can_be_null_(true) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003284 SetRawInputAt(0, object);
3285 SetRawInputAt(1, value);
3286 }
3287
Calin Juravle641547a2015-04-21 22:08:51 +01003288 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3289 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003290 }
3291
Calin Juravle52c48962014-12-16 17:02:57 +00003292 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003293 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003294 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003295 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003296 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003297 bool GetValueCanBeNull() const { return value_can_be_null_; }
3298 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003299
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003300 DECLARE_INSTRUCTION(InstanceFieldSet);
3301
3302 private:
3303 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003304 bool value_can_be_null_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003305
3306 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
3307};
3308
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003309class HArrayGet : public HExpression<2> {
3310 public:
3311 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003312 : HExpression(type, SideEffects::DependsOnSomething()) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003313 SetRawInputAt(0, array);
3314 SetRawInputAt(1, index);
3315 }
3316
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003317 bool CanBeMoved() const OVERRIDE { return true; }
3318 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003319 UNUSED(other);
3320 return true;
3321 }
Calin Juravle641547a2015-04-21 22:08:51 +01003322 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3323 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003324 // TODO: We can be smarter here.
3325 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
3326 // which generates the implicit null check. There are cases when these can be removed
3327 // to produce better code. If we ever add optimizations to do so we should allow an
3328 // implicit check here (as long as the address falls in the first page).
3329 return false;
3330 }
3331
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003332 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003333
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003334 HInstruction* GetArray() const { return InputAt(0); }
3335 HInstruction* GetIndex() const { return InputAt(1); }
3336
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003337 DECLARE_INSTRUCTION(ArrayGet);
3338
3339 private:
3340 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
3341};
3342
3343class HArraySet : public HTemplateInstruction<3> {
3344 public:
3345 HArraySet(HInstruction* array,
3346 HInstruction* index,
3347 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003348 Primitive::Type expected_component_type,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003349 uint32_t dex_pc)
3350 : HTemplateInstruction(SideEffects::ChangesSomething()),
3351 dex_pc_(dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003352 expected_component_type_(expected_component_type),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003353 needs_type_check_(value->GetType() == Primitive::kPrimNot),
3354 value_can_be_null_(true) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003355 SetRawInputAt(0, array);
3356 SetRawInputAt(1, index);
3357 SetRawInputAt(2, value);
3358 }
3359
Calin Juravle77520bc2015-01-12 18:45:46 +00003360 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003361 // We currently always call a runtime method to catch array store
3362 // exceptions.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003363 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003364 }
3365
Calin Juravle641547a2015-04-21 22:08:51 +01003366 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3367 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003368 // TODO: Same as for ArrayGet.
3369 return false;
3370 }
3371
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003372 void ClearNeedsTypeCheck() {
3373 needs_type_check_ = false;
3374 }
3375
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003376 void ClearValueCanBeNull() {
3377 value_can_be_null_ = false;
3378 }
3379
3380 bool GetValueCanBeNull() const { return value_can_be_null_; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003381 bool NeedsTypeCheck() const { return needs_type_check_; }
3382
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003383 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003384
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003385 HInstruction* GetArray() const { return InputAt(0); }
3386 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003387 HInstruction* GetValue() const { return InputAt(2); }
3388
3389 Primitive::Type GetComponentType() const {
3390 // The Dex format does not type floating point index operations. Since the
3391 // `expected_component_type_` is set during building and can therefore not
3392 // be correct, we also check what is the value type. If it is a floating
3393 // point type, we must use that type.
3394 Primitive::Type value_type = GetValue()->GetType();
3395 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
3396 ? value_type
3397 : expected_component_type_;
3398 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003399
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003400 DECLARE_INSTRUCTION(ArraySet);
3401
3402 private:
3403 const uint32_t dex_pc_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003404 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003405 bool needs_type_check_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003406 bool value_can_be_null_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003407
3408 DISALLOW_COPY_AND_ASSIGN(HArraySet);
3409};
3410
3411class HArrayLength : public HExpression<1> {
3412 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003413 explicit HArrayLength(HInstruction* array)
3414 : HExpression(Primitive::kPrimInt, SideEffects::None()) {
3415 // Note that arrays do not change length, so the instruction does not
3416 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003417 SetRawInputAt(0, array);
3418 }
3419
Calin Juravle77520bc2015-01-12 18:45:46 +00003420 bool CanBeMoved() const OVERRIDE { return true; }
3421 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003422 UNUSED(other);
3423 return true;
3424 }
Calin Juravle641547a2015-04-21 22:08:51 +01003425 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3426 return obj == InputAt(0);
3427 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003428
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003429 DECLARE_INSTRUCTION(ArrayLength);
3430
3431 private:
3432 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
3433};
3434
3435class HBoundsCheck : public HExpression<2> {
3436 public:
3437 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003438 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003439 DCHECK(index->GetType() == Primitive::kPrimInt);
3440 SetRawInputAt(0, index);
3441 SetRawInputAt(1, length);
3442 }
3443
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003444 bool CanBeMoved() const OVERRIDE { return true; }
3445 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003446 UNUSED(other);
3447 return true;
3448 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003449
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003450 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003451
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003452 bool CanThrow() const OVERRIDE { return true; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003453
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003454 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003455
3456 DECLARE_INSTRUCTION(BoundsCheck);
3457
3458 private:
3459 const uint32_t dex_pc_;
3460
3461 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
3462};
3463
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003464/**
3465 * Some DEX instructions are folded into multiple HInstructions that need
3466 * to stay live until the last HInstruction. This class
3467 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00003468 * HInstruction stays live. `index` represents the stack location index of the
3469 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003470 */
3471class HTemporary : public HTemplateInstruction<0> {
3472 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003473 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003474
3475 size_t GetIndex() const { return index_; }
3476
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00003477 Primitive::Type GetType() const OVERRIDE {
3478 // The previous instruction is the one that will be stored in the temporary location.
3479 DCHECK(GetPrevious() != nullptr);
3480 return GetPrevious()->GetType();
3481 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00003482
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003483 DECLARE_INSTRUCTION(Temporary);
3484
3485 private:
3486 const size_t index_;
3487
3488 DISALLOW_COPY_AND_ASSIGN(HTemporary);
3489};
3490
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003491class HSuspendCheck : public HTemplateInstruction<0> {
3492 public:
3493 explicit HSuspendCheck(uint32_t dex_pc)
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003494 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003495
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003496 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003497 return true;
3498 }
3499
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003500 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003501 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
3502 SlowPathCode* GetSlowPath() const { return slow_path_; }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003503
3504 DECLARE_INSTRUCTION(SuspendCheck);
3505
3506 private:
3507 const uint32_t dex_pc_;
3508
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003509 // Only used for code generation, in order to share the same slow path between back edges
3510 // of a same loop.
3511 SlowPathCode* slow_path_;
3512
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003513 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
3514};
3515
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003516/**
3517 * Instruction to load a Class object.
3518 */
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003519class HLoadClass : public HExpression<1> {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003520 public:
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003521 HLoadClass(HCurrentMethod* current_method,
3522 uint16_t type_index,
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003523 const DexFile& dex_file,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003524 bool is_referrers_class,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003525 uint32_t dex_pc)
3526 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3527 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003528 dex_file_(dex_file),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003529 is_referrers_class_(is_referrers_class),
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003530 dex_pc_(dex_pc),
Calin Juravleb1498f62015-02-16 13:13:29 +00003531 generate_clinit_check_(false),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003532 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
3533 SetRawInputAt(0, current_method);
3534 }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003535
3536 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003537
3538 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3539 return other->AsLoadClass()->type_index_ == type_index_;
3540 }
3541
3542 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
3543
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003544 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003545 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003546 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003547
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003548 bool NeedsEnvironment() const OVERRIDE {
3549 // Will call runtime and load the class if the class is not loaded yet.
3550 // TODO: finer grain decision.
3551 return !is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003552 }
3553
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003554 bool MustGenerateClinitCheck() const {
3555 return generate_clinit_check_;
3556 }
3557
Calin Juravle0ba218d2015-05-19 18:46:01 +01003558 void SetMustGenerateClinitCheck(bool generate_clinit_check) {
3559 generate_clinit_check_ = generate_clinit_check;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003560 }
3561
3562 bool CanCallRuntime() const {
3563 return MustGenerateClinitCheck() || !is_referrers_class_;
3564 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003565
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003566 bool CanThrow() const OVERRIDE {
3567 // May call runtime and and therefore can throw.
3568 // TODO: finer grain decision.
3569 return !is_referrers_class_;
3570 }
3571
Calin Juravleacf735c2015-02-12 15:25:22 +00003572 ReferenceTypeInfo GetLoadedClassRTI() {
3573 return loaded_class_rti_;
3574 }
3575
3576 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
3577 // Make sure we only set exact types (the loaded class should never be merged).
3578 DCHECK(rti.IsExact());
3579 loaded_class_rti_ = rti;
3580 }
3581
3582 bool IsResolved() {
3583 return loaded_class_rti_.IsExact();
3584 }
3585
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003586 const DexFile& GetDexFile() { return dex_file_; }
3587
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003588 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
3589
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003590 DECLARE_INSTRUCTION(LoadClass);
3591
3592 private:
3593 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003594 const DexFile& dex_file_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003595 const bool is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003596 const uint32_t dex_pc_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003597 // Whether this instruction must generate the initialization check.
3598 // Used for code generation.
3599 bool generate_clinit_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003600
Calin Juravleacf735c2015-02-12 15:25:22 +00003601 ReferenceTypeInfo loaded_class_rti_;
3602
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003603 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
3604};
3605
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003606class HLoadString : public HExpression<1> {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003607 public:
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003608 HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003609 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3610 string_index_(string_index),
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003611 dex_pc_(dex_pc) {
3612 SetRawInputAt(0, current_method);
3613 }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003614
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003615 bool CanBeMoved() const OVERRIDE { return true; }
3616
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003617 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3618 return other->AsLoadString()->string_index_ == string_index_;
3619 }
3620
3621 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
3622
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003623 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003624 uint32_t GetStringIndex() const { return string_index_; }
3625
3626 // TODO: Can we deopt or debug when we resolve a string?
3627 bool NeedsEnvironment() const OVERRIDE { return false; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003628 bool NeedsDexCache() const OVERRIDE { return true; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003629
3630 DECLARE_INSTRUCTION(LoadString);
3631
3632 private:
3633 const uint32_t string_index_;
3634 const uint32_t dex_pc_;
3635
3636 DISALLOW_COPY_AND_ASSIGN(HLoadString);
3637};
3638
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003639/**
3640 * Performs an initialization check on its Class object input.
3641 */
3642class HClinitCheck : public HExpression<1> {
3643 public:
3644 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
Nicolas Geoffraya0466e12015-03-27 15:00:40 +00003645 : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003646 dex_pc_(dex_pc) {
3647 SetRawInputAt(0, constant);
3648 }
3649
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003650 bool CanBeMoved() const OVERRIDE { return true; }
3651 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3652 UNUSED(other);
3653 return true;
3654 }
3655
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003656 bool NeedsEnvironment() const OVERRIDE {
3657 // May call runtime to initialize the class.
3658 return true;
3659 }
3660
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003661 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003662
3663 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
3664
3665 DECLARE_INSTRUCTION(ClinitCheck);
3666
3667 private:
3668 const uint32_t dex_pc_;
3669
3670 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
3671};
3672
3673class HStaticFieldGet : public HExpression<1> {
3674 public:
3675 HStaticFieldGet(HInstruction* cls,
3676 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003677 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003678 bool is_volatile,
3679 uint32_t field_idx,
3680 const DexFile& dex_file)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003681 : HExpression(field_type, SideEffects::DependsOnSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003682 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003683 SetRawInputAt(0, cls);
3684 }
3685
Calin Juravle52c48962014-12-16 17:02:57 +00003686
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003687 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003688
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003689 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00003690 HStaticFieldGet* other_get = other->AsStaticFieldGet();
3691 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003692 }
3693
3694 size_t ComputeHashCode() const OVERRIDE {
3695 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3696 }
3697
Calin Juravle52c48962014-12-16 17:02:57 +00003698 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003699 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3700 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003701 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003702
3703 DECLARE_INSTRUCTION(StaticFieldGet);
3704
3705 private:
3706 const FieldInfo field_info_;
3707
3708 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
3709};
3710
3711class HStaticFieldSet : public HTemplateInstruction<2> {
3712 public:
3713 HStaticFieldSet(HInstruction* cls,
3714 HInstruction* value,
3715 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003716 MemberOffset field_offset,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003717 bool is_volatile,
3718 uint32_t field_idx,
3719 const DexFile& dex_file)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003720 : HTemplateInstruction(SideEffects::ChangesSomething()),
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +01003721 field_info_(field_offset, field_type, is_volatile, field_idx, dex_file),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003722 value_can_be_null_(true) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003723 SetRawInputAt(0, cls);
3724 SetRawInputAt(1, value);
3725 }
3726
Calin Juravle52c48962014-12-16 17:02:57 +00003727 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003728 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3729 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003730 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003731
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003732 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003733 bool GetValueCanBeNull() const { return value_can_be_null_; }
3734 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003735
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003736 DECLARE_INSTRUCTION(StaticFieldSet);
3737
3738 private:
3739 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003740 bool value_can_be_null_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003741
3742 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
3743};
3744
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003745// Implement the move-exception DEX instruction.
3746class HLoadException : public HExpression<0> {
3747 public:
3748 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
3749
3750 DECLARE_INSTRUCTION(LoadException);
3751
3752 private:
3753 DISALLOW_COPY_AND_ASSIGN(HLoadException);
3754};
3755
3756class HThrow : public HTemplateInstruction<1> {
3757 public:
3758 HThrow(HInstruction* exception, uint32_t dex_pc)
3759 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
3760 SetRawInputAt(0, exception);
3761 }
3762
3763 bool IsControlFlow() const OVERRIDE { return true; }
3764
3765 bool NeedsEnvironment() const OVERRIDE { return true; }
3766
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003767 bool CanThrow() const OVERRIDE { return true; }
3768
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003769 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003770
3771 DECLARE_INSTRUCTION(Throw);
3772
3773 private:
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003774 const uint32_t dex_pc_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003775
3776 DISALLOW_COPY_AND_ASSIGN(HThrow);
3777};
3778
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003779class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003780 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003781 HInstanceOf(HInstruction* object,
3782 HLoadClass* constant,
3783 bool class_is_final,
3784 uint32_t dex_pc)
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003785 : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
3786 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003787 must_do_null_check_(true),
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003788 dex_pc_(dex_pc) {
3789 SetRawInputAt(0, object);
3790 SetRawInputAt(1, constant);
3791 }
3792
3793 bool CanBeMoved() const OVERRIDE { return true; }
3794
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003795 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003796 return true;
3797 }
3798
3799 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003800 return false;
3801 }
3802
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003803 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003804
3805 bool IsClassFinal() const { return class_is_final_; }
3806
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003807 // Used only in code generation.
3808 bool MustDoNullCheck() const { return must_do_null_check_; }
3809 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3810
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003811 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003812
3813 private:
3814 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003815 bool must_do_null_check_;
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003816 const uint32_t dex_pc_;
3817
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003818 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
3819};
3820
Calin Juravleb1498f62015-02-16 13:13:29 +00003821class HBoundType : public HExpression<1> {
3822 public:
3823 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type)
3824 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3825 bound_type_(bound_type) {
Calin Juravle61d544b2015-02-23 16:46:57 +00003826 DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
Calin Juravleb1498f62015-02-16 13:13:29 +00003827 SetRawInputAt(0, input);
3828 }
3829
3830 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; }
3831
3832 bool CanBeNull() const OVERRIDE {
3833 // `null instanceof ClassX` always return false so we can't be null.
3834 return false;
3835 }
3836
3837 DECLARE_INSTRUCTION(BoundType);
3838
3839 private:
3840 // Encodes the most upper class that this instruction can have. In other words
3841 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()).
3842 // It is used to bound the type in cases like `if (x instanceof ClassX) {}`
3843 const ReferenceTypeInfo bound_type_;
3844
3845 DISALLOW_COPY_AND_ASSIGN(HBoundType);
3846};
3847
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003848class HCheckCast : public HTemplateInstruction<2> {
3849 public:
3850 HCheckCast(HInstruction* object,
3851 HLoadClass* constant,
3852 bool class_is_final,
3853 uint32_t dex_pc)
3854 : HTemplateInstruction(SideEffects::None()),
3855 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003856 must_do_null_check_(true),
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003857 dex_pc_(dex_pc) {
3858 SetRawInputAt(0, object);
3859 SetRawInputAt(1, constant);
3860 }
3861
3862 bool CanBeMoved() const OVERRIDE { return true; }
3863
3864 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3865 return true;
3866 }
3867
3868 bool NeedsEnvironment() const OVERRIDE {
3869 // Instruction may throw a CheckCastError.
3870 return true;
3871 }
3872
3873 bool CanThrow() const OVERRIDE { return true; }
3874
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003875 bool MustDoNullCheck() const { return must_do_null_check_; }
3876 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3877
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003878 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003879
3880 bool IsClassFinal() const { return class_is_final_; }
3881
3882 DECLARE_INSTRUCTION(CheckCast);
3883
3884 private:
3885 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003886 bool must_do_null_check_;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003887 const uint32_t dex_pc_;
3888
3889 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003890};
3891
Calin Juravle27df7582015-04-17 19:12:31 +01003892class HMemoryBarrier : public HTemplateInstruction<0> {
3893 public:
3894 explicit HMemoryBarrier(MemBarrierKind barrier_kind)
3895 : HTemplateInstruction(SideEffects::None()),
3896 barrier_kind_(barrier_kind) {}
3897
3898 MemBarrierKind GetBarrierKind() { return barrier_kind_; }
3899
3900 DECLARE_INSTRUCTION(MemoryBarrier);
3901
3902 private:
3903 const MemBarrierKind barrier_kind_;
3904
3905 DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier);
3906};
3907
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003908class HMonitorOperation : public HTemplateInstruction<1> {
3909 public:
3910 enum OperationKind {
3911 kEnter,
3912 kExit,
3913 };
3914
3915 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
3916 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
3917 SetRawInputAt(0, object);
3918 }
3919
3920 // Instruction may throw a Java exception, so we need an environment.
3921 bool NeedsEnvironment() const OVERRIDE { return true; }
3922 bool CanThrow() const OVERRIDE { return true; }
3923
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003924 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003925
3926 bool IsEnter() const { return kind_ == kEnter; }
3927
3928 DECLARE_INSTRUCTION(MonitorOperation);
3929
Calin Juravle52c48962014-12-16 17:02:57 +00003930 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003931 const OperationKind kind_;
3932 const uint32_t dex_pc_;
3933
3934 private:
3935 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
3936};
3937
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003938class MoveOperands : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003939 public:
Nicolas Geoffray90218252015-04-15 11:56:51 +01003940 MoveOperands(Location source,
3941 Location destination,
3942 Primitive::Type type,
3943 HInstruction* instruction)
3944 : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003945
3946 Location GetSource() const { return source_; }
3947 Location GetDestination() const { return destination_; }
3948
3949 void SetSource(Location value) { source_ = value; }
3950 void SetDestination(Location value) { destination_ = value; }
3951
3952 // The parallel move resolver marks moves as "in-progress" by clearing the
3953 // destination (but not the source).
3954 Location MarkPending() {
3955 DCHECK(!IsPending());
3956 Location dest = destination_;
3957 destination_ = Location::NoLocation();
3958 return dest;
3959 }
3960
3961 void ClearPending(Location dest) {
3962 DCHECK(IsPending());
3963 destination_ = dest;
3964 }
3965
3966 bool IsPending() const {
3967 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3968 return destination_.IsInvalid() && !source_.IsInvalid();
3969 }
3970
3971 // True if this blocks a move from the given location.
3972 bool Blocks(Location loc) const {
Zheng Xuad4450e2015-04-17 18:48:56 +08003973 return !IsEliminated() && source_.OverlapsWith(loc);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003974 }
3975
3976 // A move is redundant if it's been eliminated, if its source and
3977 // destination are the same, or if its destination is unneeded.
3978 bool IsRedundant() const {
3979 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
3980 }
3981
3982 // We clear both operands to indicate move that's been eliminated.
3983 void Eliminate() {
3984 source_ = destination_ = Location::NoLocation();
3985 }
3986
3987 bool IsEliminated() const {
3988 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3989 return source_.IsInvalid();
3990 }
3991
Nicolas Geoffray90218252015-04-15 11:56:51 +01003992 bool Is64BitMove() const {
3993 return Primitive::Is64BitType(type_);
3994 }
3995
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003996 HInstruction* GetInstruction() const { return instruction_; }
3997
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003998 private:
3999 Location source_;
4000 Location destination_;
Nicolas Geoffray90218252015-04-15 11:56:51 +01004001 // The type this move is for.
4002 Primitive::Type type_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004003 // The instruction this move is assocatied with. Null when this move is
4004 // for moving an input in the expected locations of user (including a phi user).
4005 // This is only used in debug mode, to ensure we do not connect interval siblings
4006 // in the same parallel move.
4007 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004008};
4009
4010static constexpr size_t kDefaultNumberOfMoves = 4;
4011
4012class HParallelMove : public HTemplateInstruction<0> {
4013 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01004014 explicit HParallelMove(ArenaAllocator* arena)
4015 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004016
Nicolas Geoffray90218252015-04-15 11:56:51 +01004017 void AddMove(Location source,
4018 Location destination,
4019 Primitive::Type type,
4020 HInstruction* instruction) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004021 DCHECK(source.IsValid());
4022 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004023 if (kIsDebugBuild) {
4024 if (instruction != nullptr) {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004025 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00004026 if (moves_.Get(i).GetInstruction() == instruction) {
4027 // Special case the situation where the move is for the spill slot
4028 // of the instruction.
4029 if ((GetPrevious() == instruction)
4030 || ((GetPrevious() == nullptr)
4031 && instruction->IsPhi()
4032 && instruction->GetBlock() == GetBlock())) {
4033 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind())
4034 << "Doing parallel moves for the same instruction.";
4035 } else {
4036 DCHECK(false) << "Doing parallel moves for the same instruction.";
4037 }
4038 }
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004039 }
4040 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004041 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Zheng Xuad4450e2015-04-17 18:48:56 +08004042 DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination()))
Guillaume "Vermeille" Sanchez8909baf2015-04-23 21:35:11 +01004043 << "Overlapped destination for two moves in a parallel move: "
4044 << moves_.Get(i).GetSource() << " ==> " << moves_.Get(i).GetDestination() << " and "
4045 << source << " ==> " << destination;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004046 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004047 }
Nicolas Geoffray90218252015-04-15 11:56:51 +01004048 moves_.Add(MoveOperands(source, destination, type, instruction));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004049 }
4050
4051 MoveOperands* MoveOperandsAt(size_t index) const {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004052 return moves_.GetRawStorage() + index;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004053 }
4054
4055 size_t NumMoves() const { return moves_.Size(); }
4056
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01004057 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004058
4059 private:
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004060 GrowableArray<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004061
4062 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
4063};
4064
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004065class HGraphVisitor : public ValueObject {
4066 public:
Dave Allison20dfc792014-06-16 20:44:29 -07004067 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
4068 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004069
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004070 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004071 virtual void VisitBasicBlock(HBasicBlock* block);
4072
Roland Levillain633021e2014-10-01 14:12:25 +01004073 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004074 void VisitInsertionOrder();
4075
Roland Levillain633021e2014-10-01 14:12:25 +01004076 // Visit the graph following dominator tree reverse post-order.
4077 void VisitReversePostOrder();
4078
Nicolas Geoffray787c3072014-03-17 10:20:19 +00004079 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00004080
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004081 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004082#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004083 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
4084
4085 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4086
4087#undef DECLARE_VISIT_INSTRUCTION
4088
4089 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07004090 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004091
4092 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
4093};
4094
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004095class HGraphDelegateVisitor : public HGraphVisitor {
4096 public:
4097 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
4098 virtual ~HGraphDelegateVisitor() {}
4099
4100 // Visit functions that delegate to to super class.
4101#define DECLARE_VISIT_INSTRUCTION(name, super) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004102 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004103
4104 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4105
4106#undef DECLARE_VISIT_INSTRUCTION
4107
4108 private:
4109 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
4110};
4111
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004112class HInsertionOrderIterator : public ValueObject {
4113 public:
4114 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
4115
4116 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
4117 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
4118 void Advance() { ++index_; }
4119
4120 private:
4121 const HGraph& graph_;
4122 size_t index_;
4123
4124 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
4125};
4126
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004127class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004128 public:
David Brazdil10f56cb2015-03-24 18:49:14 +00004129 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
4130 // Check that reverse post order of the graph has been built.
4131 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4132 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004133
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004134 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
4135 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004136 void Advance() { ++index_; }
4137
4138 private:
4139 const HGraph& graph_;
4140 size_t index_;
4141
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004142 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004143};
4144
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004145class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004146 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004147 explicit HPostOrderIterator(const HGraph& graph)
David Brazdil10f56cb2015-03-24 18:49:14 +00004148 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {
4149 // Check that reverse post order of the graph has been built.
4150 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4151 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004152
4153 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004154 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004155 void Advance() { --index_; }
4156
4157 private:
4158 const HGraph& graph_;
4159 size_t index_;
4160
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004161 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004162};
4163
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01004164class HLinearPostOrderIterator : public ValueObject {
4165 public:
4166 explicit HLinearPostOrderIterator(const HGraph& graph)
4167 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {}
4168
4169 bool Done() const { return index_ == 0; }
4170
4171 HBasicBlock* Current() const { return order_.Get(index_ -1); }
4172
4173 void Advance() {
4174 --index_;
4175 DCHECK_GE(index_, 0U);
4176 }
4177
4178 private:
4179 const GrowableArray<HBasicBlock*>& order_;
4180 size_t index_;
4181
4182 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
4183};
4184
4185class HLinearOrderIterator : public ValueObject {
4186 public:
4187 explicit HLinearOrderIterator(const HGraph& graph)
4188 : order_(graph.GetLinearOrder()), index_(0) {}
4189
4190 bool Done() const { return index_ == order_.Size(); }
4191 HBasicBlock* Current() const { return order_.Get(index_); }
4192 void Advance() { ++index_; }
4193
4194 private:
4195 const GrowableArray<HBasicBlock*>& order_;
4196 size_t index_;
4197
4198 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
4199};
4200
Nicolas Geoffray82091da2015-01-26 10:02:45 +00004201// Iterator over the blocks that art part of the loop. Includes blocks part
4202// of an inner loop. The order in which the blocks are iterated is on their
4203// block id.
4204class HBlocksInLoopIterator : public ValueObject {
4205 public:
4206 explicit HBlocksInLoopIterator(const HLoopInformation& info)
4207 : blocks_in_loop_(info.GetBlocks()),
4208 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
4209 index_(0) {
4210 if (!blocks_in_loop_.IsBitSet(index_)) {
4211 Advance();
4212 }
4213 }
4214
4215 bool Done() const { return index_ == blocks_.Size(); }
4216 HBasicBlock* Current() const { return blocks_.Get(index_); }
4217 void Advance() {
4218 ++index_;
4219 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4220 if (blocks_in_loop_.IsBitSet(index_)) {
4221 break;
4222 }
4223 }
4224 }
4225
4226 private:
4227 const BitVector& blocks_in_loop_;
4228 const GrowableArray<HBasicBlock*>& blocks_;
4229 size_t index_;
4230
4231 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
4232};
4233
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00004234inline int64_t Int64FromConstant(HConstant* constant) {
4235 DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
4236 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
4237 : constant->AsLongConstant()->GetValue();
4238}
4239
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004240} // namespace art
4241
4242#endif // ART_COMPILER_OPTIMIZING_NODES_H_