blob: 005d50eea0244d094d85d8ab5660c017a641bd78 [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
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +010064static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
65
Dave Allison20dfc792014-06-16 20:44:29 -070066enum IfCondition {
67 kCondEQ,
68 kCondNE,
69 kCondLT,
70 kCondLE,
71 kCondGT,
72 kCondGE,
73};
74
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010075class HInstructionList {
76 public:
77 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
78
79 void AddInstruction(HInstruction* instruction);
80 void RemoveInstruction(HInstruction* instruction);
81
David Brazdilc3d743f2015-04-22 13:40:50 +010082 // Insert `instruction` before/after an existing instruction `cursor`.
83 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
84 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
85
Roland Levillain6b469232014-09-25 10:10:38 +010086 // Return true if this list contains `instruction`.
87 bool Contains(HInstruction* instruction) const;
88
Roland Levillainccc07a92014-09-16 14:48:16 +010089 // Return true if `instruction1` is found before `instruction2` in
90 // this instruction list and false otherwise. Abort if none
91 // of these instructions is found.
92 bool FoundBefore(const HInstruction* instruction1,
93 const HInstruction* instruction2) const;
94
Nicolas Geoffray276d9da2015-02-02 18:24:11 +000095 bool IsEmpty() const { return first_instruction_ == nullptr; }
96 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
97
98 // Update the block of all instructions to be `block`.
99 void SetBlockOfInstructions(HBasicBlock* block) const;
100
101 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
102 void Add(const HInstructionList& instruction_list);
103
David Brazdil2d7352b2015-04-20 14:52:42 +0100104 // Return the number of instructions in the list. This is an expensive operation.
105 size_t CountSize() const;
106
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100107 private:
108 HInstruction* first_instruction_;
109 HInstruction* last_instruction_;
110
111 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000112 friend class HGraph;
113 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100114 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100115 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100116
117 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
118};
119
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000120// Control-flow graph of a method. Contains a list of basic blocks.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700121class HGraph : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000122 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100123 HGraph(ArenaAllocator* arena,
124 const DexFile& dex_file,
125 uint32_t method_idx,
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100126 bool should_generate_constructor_barrier,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100127 InvokeType invoke_type = kInvalidInvokeType,
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100128 bool debuggable = false,
129 int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000130 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000131 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100132 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100133 linear_order_(arena, kDefaultNumberOfBlocks),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700134 entry_block_(nullptr),
135 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100136 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100137 number_of_vregs_(0),
138 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000139 temporaries_vreg_slots_(0),
Mark Mendell1152c922015-04-24 17:06:35 -0400140 has_bounds_checks_(false),
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000141 debuggable_(debuggable),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000142 current_instruction_id_(start_instruction_id),
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100143 dex_file_(dex_file),
144 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100145 invoke_type_(invoke_type),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100146 in_ssa_form_(false),
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100147 should_generate_constructor_barrier_(should_generate_constructor_barrier),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000148 cached_null_constant_(nullptr),
149 cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000150 cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
151 cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100152 cached_double_constants_(std::less<int64_t>(), arena->Adapter()),
153 cached_current_method_(nullptr) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000154
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000155 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100156 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Roland Levillain93445682014-10-06 19:24:02 +0100157 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000158
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000159 HBasicBlock* GetEntryBlock() const { return entry_block_; }
160 HBasicBlock* GetExitBlock() const { return exit_block_; }
David Brazdilc7af85d2015-05-26 12:05:55 +0100161 bool HasExitBlock() const { return exit_block_ != nullptr; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000162
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000163 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
164 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000165
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000166 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100167
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000168 // Try building the SSA form of this graph, with dominance computation and loop
169 // recognition. Returns whether it was successful in doing all these steps.
170 bool TryBuildingSsa() {
171 BuildDominatorTree();
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000172 // The SSA builder requires loops to all be natural. Specifically, the dead phi
173 // elimination phase checks the consistency of the graph when doing a post-order
174 // visit for eliminating dead phis: a dead phi can only have loop header phi
175 // users remaining when being visited.
176 if (!AnalyzeNaturalLoops()) return false;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000177 TransformToSsa();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100178 in_ssa_form_ = true;
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000179 return true;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000180 }
181
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000182 void BuildDominatorTree();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000183 void TransformToSsa();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100184 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000185
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000186 // Analyze all natural loops in this graph. Returns false if one
187 // loop is not natural, that is the header does not dominate the
188 // back edge.
189 bool AnalyzeNaturalLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100190
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000191 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
192 void InlineInto(HGraph* outer_graph, HInvoke* invoke);
193
David Brazdil2d7352b2015-04-20 14:52:42 +0100194 // Removes `block` from the graph.
195 void DeleteDeadBlock(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000196
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100197 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
198 void SimplifyLoop(HBasicBlock* header);
199
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000200 int32_t GetNextInstructionId() {
201 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000202 return current_instruction_id_++;
203 }
204
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000205 int32_t GetCurrentInstructionId() const {
206 return current_instruction_id_;
207 }
208
209 void SetCurrentInstructionId(int32_t id) {
210 current_instruction_id_ = id;
211 }
212
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100213 uint16_t GetMaximumNumberOfOutVRegs() const {
214 return maximum_number_of_out_vregs_;
215 }
216
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000217 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
218 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100219 }
220
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100221 void UpdateMaximumNumberOfOutVRegs(uint16_t other_value) {
222 maximum_number_of_out_vregs_ = std::max(maximum_number_of_out_vregs_, other_value);
223 }
224
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000225 void UpdateTemporariesVRegSlots(size_t slots) {
226 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100227 }
228
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000229 size_t GetTemporariesVRegSlots() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100230 DCHECK(!in_ssa_form_);
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000231 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100232 }
233
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100234 void SetNumberOfVRegs(uint16_t number_of_vregs) {
235 number_of_vregs_ = number_of_vregs;
236 }
237
238 uint16_t GetNumberOfVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100239 DCHECK(!in_ssa_form_);
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100240 return number_of_vregs_;
241 }
242
243 void SetNumberOfInVRegs(uint16_t value) {
244 number_of_in_vregs_ = value;
245 }
246
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100247 uint16_t GetNumberOfLocalVRegs() const {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100248 DCHECK(!in_ssa_form_);
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100249 return number_of_vregs_ - number_of_in_vregs_;
250 }
251
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100252 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
253 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100254 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100255
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100256 const GrowableArray<HBasicBlock*>& GetLinearOrder() const {
257 return linear_order_;
258 }
259
Mark Mendell1152c922015-04-24 17:06:35 -0400260 bool HasBoundsChecks() const {
261 return has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800262 }
263
Mark Mendell1152c922015-04-24 17:06:35 -0400264 void SetHasBoundsChecks(bool value) {
265 has_bounds_checks_ = value;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800266 }
267
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100268 bool ShouldGenerateConstructorBarrier() const {
269 return should_generate_constructor_barrier_;
270 }
271
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000272 bool IsDebuggable() const { return debuggable_; }
273
David Brazdil8d5b8b22015-03-24 10:51:52 +0000274 // Returns a constant of the given type and value. If it does not exist
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000275 // already, it is created and inserted into the graph. This method is only for
276 // integral types.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000277 HConstant* GetConstant(Primitive::Type type, int64_t value);
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000278 HNullConstant* GetNullConstant();
David Brazdil8d5b8b22015-03-24 10:51:52 +0000279 HIntConstant* GetIntConstant(int32_t value) {
280 return CreateConstant(value, &cached_int_constants_);
281 }
282 HLongConstant* GetLongConstant(int64_t value) {
283 return CreateConstant(value, &cached_long_constants_);
284 }
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000285 HFloatConstant* GetFloatConstant(float value) {
286 return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_);
287 }
288 HDoubleConstant* GetDoubleConstant(double value) {
289 return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
290 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000291
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100292 HCurrentMethod* GetCurrentMethod();
293
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000294 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
David Brazdil2d7352b2015-04-20 14:52:42 +0100295
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100296 const DexFile& GetDexFile() const {
297 return dex_file_;
298 }
299
300 uint32_t GetMethodIdx() const {
301 return method_idx_;
302 }
303
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100304 InvokeType GetInvokeType() const {
305 return invoke_type_;
306 }
307
David Brazdil2d7352b2015-04-20 14:52:42 +0100308 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000309 void VisitBlockForDominatorTree(HBasicBlock* block,
310 HBasicBlock* predecessor,
311 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100312 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000313 void VisitBlockForBackEdges(HBasicBlock* block,
314 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100315 ArenaBitVector* visiting);
Roland Levillainfc600dc2014-12-02 17:16:31 +0000316 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffrayf776b922015-04-15 18:22:45 +0100317 void RemoveDeadBlocks(const ArenaBitVector& visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000318
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000319 template <class InstructionType, typename ValueType>
320 InstructionType* CreateConstant(ValueType value,
321 ArenaSafeMap<ValueType, InstructionType*>* cache) {
322 // Try to find an existing constant of the given value.
323 InstructionType* constant = nullptr;
324 auto cached_constant = cache->find(value);
325 if (cached_constant != cache->end()) {
326 constant = cached_constant->second;
327 }
328
329 // If not found or previously deleted, create and cache a new instruction.
330 if (constant == nullptr || constant->GetBlock() == nullptr) {
331 constant = new (arena_) InstructionType(value);
332 cache->Overwrite(value, constant);
333 InsertConstant(constant);
334 }
335 return constant;
336 }
337
David Brazdil8d5b8b22015-03-24 10:51:52 +0000338 void InsertConstant(HConstant* instruction);
339
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000340 // Cache a float constant into the graph. This method should only be
341 // called by the SsaBuilder when creating "equivalent" instructions.
342 void CacheFloatConstant(HFloatConstant* constant);
343
344 // See CacheFloatConstant comment.
345 void CacheDoubleConstant(HDoubleConstant* constant);
346
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000347 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000348
349 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000350 GrowableArray<HBasicBlock*> blocks_;
351
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100352 // List of blocks to perform a reverse post order tree traversal.
353 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000354
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100355 // List of blocks to perform a linear order tree traversal.
356 GrowableArray<HBasicBlock*> linear_order_;
357
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000358 HBasicBlock* entry_block_;
359 HBasicBlock* exit_block_;
360
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100361 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100362 uint16_t maximum_number_of_out_vregs_;
363
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100364 // The number of virtual registers in this method. Contains the parameters.
365 uint16_t number_of_vregs_;
366
367 // The number of virtual registers used by parameters of this method.
368 uint16_t number_of_in_vregs_;
369
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000370 // Number of vreg size slots that the temporaries use (used in baseline compiler).
371 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100372
Mark Mendell1152c922015-04-24 17:06:35 -0400373 // Has bounds checks. We can totally skip BCE if it's false.
374 bool has_bounds_checks_;
Mingyao Yange4335eb2015-03-02 15:14:13 -0800375
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000376 // Indicates whether the graph should be compiled in a way that
377 // ensures full debuggability. If false, we can apply more
378 // aggressive optimizations that may limit the level of debugging.
379 const bool debuggable_;
380
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000381 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000382 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000383
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100384 // The dex file from which the method is from.
385 const DexFile& dex_file_;
386
387 // The method index in the dex file.
388 const uint32_t method_idx_;
389
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +0100390 // If inlined, this encodes how the callee is being invoked.
391 const InvokeType invoke_type_;
392
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +0100393 // Whether the graph has been transformed to SSA form. Only used
394 // in debug mode to ensure we are not using properties only valid
395 // for non-SSA form (like the number of temporaries).
396 bool in_ssa_form_;
397
Calin Juravle3cd4fc82015-05-14 15:15:42 +0100398 const bool should_generate_constructor_barrier_;
399
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000400 // Cached constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000401 HNullConstant* cached_null_constant_;
402 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000403 ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
David Brazdil8d5b8b22015-03-24 10:51:52 +0000404 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000405 ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
David Brazdil46e2a392015-03-16 17:31:52 +0000406
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100407 HCurrentMethod* cached_current_method_;
408
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000409 friend class SsaBuilder; // For caching constants.
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100410 friend class SsaLivenessAnalysis; // For the linear order.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000411 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000412 DISALLOW_COPY_AND_ASSIGN(HGraph);
413};
414
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700415class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000416 public:
417 HLoopInformation(HBasicBlock* header, HGraph* graph)
418 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100419 suspend_check_(nullptr),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100420 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100421 // Make bit vector growable, as the number of blocks may change.
422 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100423
424 HBasicBlock* GetHeader() const {
425 return header_;
426 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000427
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000428 void SetHeader(HBasicBlock* block) {
429 header_ = block;
430 }
431
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100432 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
433 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
434 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
435
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000436 void AddBackEdge(HBasicBlock* back_edge) {
437 back_edges_.Add(back_edge);
438 }
439
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100440 void RemoveBackEdge(HBasicBlock* back_edge) {
441 back_edges_.Delete(back_edge);
442 }
443
David Brazdil46e2a392015-03-16 17:31:52 +0000444 bool IsBackEdge(const HBasicBlock& block) const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100445 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
David Brazdil46e2a392015-03-16 17:31:52 +0000446 if (back_edges_.Get(i) == &block) return true;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100447 }
448 return false;
449 }
450
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000451 size_t NumberOfBackEdges() const {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000452 return back_edges_.Size();
453 }
454
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100455 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100456
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100457 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
458 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100459 }
460
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100461 // Returns the lifetime position of the back edge that has the
462 // greatest lifetime position.
463 size_t GetLifetimeEnd() const;
464
465 void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
466 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
467 if (back_edges_.Get(i) == existing) {
468 back_edges_.Put(i, new_back_edge);
469 return;
470 }
471 }
472 UNREACHABLE();
Nicolas Geoffray57902602015-04-21 14:28:41 +0100473 }
474
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100475 // Finds blocks that are part of this loop. Returns whether the loop is a natural loop,
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100476 // that is the header dominates the back edge.
477 bool Populate();
478
David Brazdila4b8c212015-05-07 09:59:30 +0100479 // Reanalyzes the loop by removing loop info from its blocks and re-running
480 // Populate(). If there are no back edges left, the loop info is completely
481 // removed as well as its SuspendCheck instruction. It must be run on nested
482 // inner loops first.
483 void Update();
484
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100485 // Returns whether this loop information contains `block`.
486 // Note that this loop information *must* be populated before entering this function.
487 bool Contains(const HBasicBlock& block) const;
488
489 // Returns whether this loop information is an inner loop of `other`.
490 // Note that `other` *must* be populated before entering this function.
491 bool IsIn(const HLoopInformation& other) const;
492
493 const ArenaBitVector& GetBlocks() const { return blocks_; }
494
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000495 void Add(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000496 void Remove(HBasicBlock* block);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000497
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000498 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100499 // Internal recursive implementation of `Populate`.
500 void PopulateRecursive(HBasicBlock* block);
501
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000502 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100503 HSuspendCheck* suspend_check_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000504 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100505 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000506
507 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
508};
509
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100510static constexpr size_t kNoLifetime = -1;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100511static constexpr uint32_t kNoDexPc = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100512
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000513// A block in a method. Contains the list of instructions represented
514// as a double linked list. Each block knows its predecessors and
515// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100516
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700517class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000518 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100519 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000520 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000521 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
522 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000523 loop_information_(nullptr),
524 dominator_(nullptr),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100525 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100526 block_id_(-1),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100527 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100528 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000529 lifetime_end_(kNoLifetime),
530 is_catch_block_(false) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000531
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100532 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
533 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000534 }
535
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100536 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
537 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000538 }
539
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100540 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
541 return dominated_blocks_;
542 }
543
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100544 bool IsEntryBlock() const {
545 return graph_->GetEntryBlock() == this;
546 }
547
548 bool IsExitBlock() const {
549 return graph_->GetExitBlock() == this;
550 }
551
David Brazdil46e2a392015-03-16 17:31:52 +0000552 bool IsSingleGoto() const;
553
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000554 void AddBackEdge(HBasicBlock* back_edge) {
555 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000556 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000557 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100558 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000559 loop_information_->AddBackEdge(back_edge);
560 }
561
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000562 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000563 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000564
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000565 int GetBlockId() const { return block_id_; }
566 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000567
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000568 HBasicBlock* GetDominator() const { return dominator_; }
569 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100570 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
David Brazdil2d7352b2015-04-20 14:52:42 +0100571 void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000572 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
573 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
574 if (dominated_blocks_.Get(i) == existing) {
575 dominated_blocks_.Put(i, new_block);
576 return;
577 }
578 }
579 LOG(FATAL) << "Unreachable";
580 UNREACHABLE();
581 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000582
583 int NumberOfBackEdges() const {
584 return loop_information_ == nullptr
585 ? 0
586 : loop_information_->NumberOfBackEdges();
587 }
588
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100589 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
590 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100591 const HInstructionList& GetInstructions() const { return instructions_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100592 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
David Brazdilc3d743f2015-04-22 13:40:50 +0100593 HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
594 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000595
596 void AddSuccessor(HBasicBlock* block) {
597 successors_.Add(block);
598 block->predecessors_.Add(this);
599 }
600
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100601 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
602 size_t successor_index = GetSuccessorIndexOf(existing);
603 DCHECK_NE(successor_index, static_cast<size_t>(-1));
604 existing->RemovePredecessor(this);
605 new_block->predecessors_.Add(this);
606 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000607 }
608
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000609 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
610 size_t predecessor_index = GetPredecessorIndexOf(existing);
611 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
612 existing->RemoveSuccessor(this);
613 new_block->successors_.Add(this);
614 predecessors_.Put(predecessor_index, new_block);
615 }
616
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100617 void RemovePredecessor(HBasicBlock* block) {
618 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100619 }
620
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000621 void RemoveSuccessor(HBasicBlock* block) {
622 successors_.Delete(block);
623 }
624
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100625 void ClearAllPredecessors() {
626 predecessors_.Reset();
627 }
628
629 void AddPredecessor(HBasicBlock* block) {
630 predecessors_.Add(block);
631 block->successors_.Add(this);
632 }
633
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100634 void SwapPredecessors() {
Nicolas Geoffrayc83d4412014-09-18 16:46:20 +0100635 DCHECK_EQ(predecessors_.Size(), 2u);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100636 HBasicBlock* temp = predecessors_.Get(0);
637 predecessors_.Put(0, predecessors_.Get(1));
638 predecessors_.Put(1, temp);
639 }
640
David Brazdil769c9e52015-04-27 13:54:09 +0100641 void SwapSuccessors() {
642 DCHECK_EQ(successors_.Size(), 2u);
643 HBasicBlock* temp = successors_.Get(0);
644 successors_.Put(0, successors_.Get(1));
645 successors_.Put(1, temp);
646 }
647
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100648 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
649 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
650 if (predecessors_.Get(i) == predecessor) {
651 return i;
652 }
653 }
654 return -1;
655 }
656
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100657 size_t GetSuccessorIndexOf(HBasicBlock* successor) {
658 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
659 if (successors_.Get(i) == successor) {
660 return i;
661 }
662 }
663 return -1;
664 }
665
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000666 // Split the block into two blocks just after `cursor`. Returns the newly
667 // created block. Note that this method just updates raw block information,
668 // like predecessors, successors, dominators, and instruction list. It does not
669 // update the graph, reverse post order, loop information, nor make sure the
670 // blocks are consistent (for example ending with a control flow instruction).
671 HBasicBlock* SplitAfter(HInstruction* cursor);
672
673 // Merge `other` at the end of `this`. Successors and dominated blocks of
674 // `other` are changed to be successors and dominated blocks of `this`. Note
675 // that this method does not update the graph, reverse post order, loop
676 // information, nor make sure the blocks are consistent (for example ending
677 // with a control flow instruction).
David Brazdil2d7352b2015-04-20 14:52:42 +0100678 void MergeWithInlined(HBasicBlock* other);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000679
680 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
681 // of `this` are moved to `other`.
682 // Note that this method does not update the graph, reverse post order, loop
683 // information, nor make sure the blocks are consistent (for example ending
David Brazdil46e2a392015-03-16 17:31:52 +0000684 // with a control flow instruction).
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000685 void ReplaceWith(HBasicBlock* other);
686
David Brazdil2d7352b2015-04-20 14:52:42 +0100687 // Merge `other` at the end of `this`. This method updates loops, reverse post
688 // order, links to predecessors, successors, dominators and deletes the block
689 // from the graph. The two blocks must be successive, i.e. `this` the only
690 // predecessor of `other` and vice versa.
691 void MergeWith(HBasicBlock* other);
692
693 // Disconnects `this` from all its predecessors, successors and dominator,
694 // removes it from all loops it is included in and eventually from the graph.
695 // The block must not dominate any other block. Predecessors and successors
696 // are safely updated.
697 void DisconnectAndDelete();
David Brazdil46e2a392015-03-16 17:31:52 +0000698
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000699 void AddInstruction(HInstruction* instruction);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100700 // Insert `instruction` before/after an existing instruction `cursor`.
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100701 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Guillaume "Vermeille" Sanchez2967ec62015-04-24 16:36:52 +0100702 void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +0100703 // Replace instruction `initial` with `replacement` within this block.
704 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
705 HInstruction* replacement);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100706 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100707 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
David Brazdil1abb4192015-02-17 18:33:36 +0000708 // RemoveInstruction and RemovePhi delete a given instruction from the respective
709 // instruction list. With 'ensure_safety' set to true, it verifies that the
710 // instruction is not in use and removes it from the use lists of its inputs.
711 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
712 void RemovePhi(HPhi* phi, bool ensure_safety = true);
David Brazdilc7508e92015-04-27 13:28:57 +0100713 void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100714
715 bool IsLoopHeader() const {
David Brazdil69a28042015-04-29 17:16:07 +0100716 return IsInLoop() && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100717 }
718
Roland Levillain6b879dd2014-09-22 17:13:44 +0100719 bool IsLoopPreHeaderFirstPredecessor() const {
720 DCHECK(IsLoopHeader());
721 DCHECK(!GetPredecessors().IsEmpty());
722 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
723 }
724
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100725 HLoopInformation* GetLoopInformation() const {
726 return loop_information_;
727 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000728
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000729 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100730 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000731 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100732 void SetInLoop(HLoopInformation* info) {
733 if (IsLoopHeader()) {
734 // Nothing to do. This just means `info` is an outer loop.
David Brazdil69a28042015-04-29 17:16:07 +0100735 } else if (!IsInLoop()) {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100736 loop_information_ = info;
737 } else if (loop_information_->Contains(*info->GetHeader())) {
738 // Block is currently part of an outer loop. Make it part of this inner loop.
739 // Note that a non loop header having a loop information means this loop information
740 // has already been populated
741 loop_information_ = info;
742 } else {
743 // Block is part of an inner loop. Do not update the loop information.
744 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
745 // at this point, because this method is being called while populating `info`.
746 }
747 }
748
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000749 // Raw update of the loop information.
750 void SetLoopInformation(HLoopInformation* info) {
751 loop_information_ = info;
752 }
753
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100754 bool IsInLoop() const { return loop_information_ != nullptr; }
755
David Brazdila4b8c212015-05-07 09:59:30 +0100756 // Returns whether this block dominates the blocked passed as parameter.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100757 bool Dominates(HBasicBlock* block) const;
758
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100759 size_t GetLifetimeStart() const { return lifetime_start_; }
760 size_t GetLifetimeEnd() const { return lifetime_end_; }
761
762 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
763 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
764
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100765 uint32_t GetDexPc() const { return dex_pc_; }
766
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000767 bool IsCatchBlock() const { return is_catch_block_; }
768 void SetIsCatchBlock() { is_catch_block_ = true; }
769
David Brazdil8d5b8b22015-03-24 10:51:52 +0000770 bool EndsWithControlFlowInstruction() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +0000771 bool EndsWithIf() const;
772 bool HasSinglePhi() const;
773
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000774 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000775 HGraph* graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000776 GrowableArray<HBasicBlock*> predecessors_;
777 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100778 HInstructionList instructions_;
779 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000780 HLoopInformation* loop_information_;
781 HBasicBlock* dominator_;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100782 GrowableArray<HBasicBlock*> dominated_blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000783 int block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100784 // The dex program counter of the first instruction of this block.
785 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100786 size_t lifetime_start_;
787 size_t lifetime_end_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000788 bool is_catch_block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000789
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000790 friend class HGraph;
791 friend class HInstruction;
792
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000793 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
794};
795
David Brazdilb2bd1c52015-03-25 11:17:37 +0000796// Iterates over the LoopInformation of all loops which contain 'block'
797// from the innermost to the outermost.
798class HLoopInformationOutwardIterator : public ValueObject {
799 public:
800 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
801 : current_(block.GetLoopInformation()) {}
802
803 bool Done() const { return current_ == nullptr; }
804
805 void Advance() {
806 DCHECK(!Done());
David Brazdil69a28042015-04-29 17:16:07 +0100807 current_ = current_->GetPreHeader()->GetLoopInformation();
David Brazdilb2bd1c52015-03-25 11:17:37 +0000808 }
809
810 HLoopInformation* Current() const {
811 DCHECK(!Done());
812 return current_;
813 }
814
815 private:
816 HLoopInformation* current_;
817
818 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
819};
820
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100821#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
822 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000823 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000824 M(ArrayGet, Instruction) \
825 M(ArrayLength, Instruction) \
826 M(ArraySet, Instruction) \
David Brazdil66d126e2015-04-03 16:02:44 +0100827 M(BooleanNot, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000828 M(BoundsCheck, Instruction) \
Calin Juravleb1498f62015-02-16 13:13:29 +0000829 M(BoundType, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000830 M(CheckCast, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100831 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000832 M(Compare, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100833 M(Condition, BinaryOperation) \
Nicolas Geoffray76b1e172015-05-27 17:18:33 +0100834 M(CurrentMethod, Instruction) \
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700835 M(Deoptimize, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000836 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +0000837 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000838 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100839 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000840 M(Exit, Instruction) \
841 M(FloatConstant, Constant) \
842 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100843 M(GreaterThan, Condition) \
844 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100845 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000846 M(InstanceFieldGet, Instruction) \
847 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000848 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100849 M(IntConstant, Constant) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000850 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000851 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100852 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000853 M(LessThan, Condition) \
854 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000855 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000856 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100857 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000858 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100859 M(Local, Instruction) \
860 M(LongConstant, Constant) \
Calin Juravle27df7582015-04-17 19:12:31 +0100861 M(MemoryBarrier, Instruction) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +0000862 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000863 M(Mul, BinaryOperation) \
864 M(Neg, UnaryOperation) \
865 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100866 M(NewInstance, Instruction) \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100867 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000868 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000869 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000870 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000871 M(Or, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100872 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000873 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100874 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000875 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100876 M(Return, Instruction) \
877 M(ReturnVoid, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000878 M(Shl, BinaryOperation) \
879 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100880 M(StaticFieldGet, Instruction) \
881 M(StaticFieldSet, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100882 M(StoreLocal, Instruction) \
883 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100884 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000885 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000886 M(Throw, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +0000887 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000888 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000889 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000890
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100891#define FOR_EACH_INSTRUCTION(M) \
892 FOR_EACH_CONCRETE_INSTRUCTION(M) \
893 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +0100894 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +0100895 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100896 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -0700897
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100898#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000899FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
900#undef FORWARD_DECLARATION
901
Roland Levillainccc07a92014-09-16 14:48:16 +0100902#define DECLARE_INSTRUCTION(type) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000903 InstructionKind GetKind() const OVERRIDE { return k##type; } \
904 const char* DebugName() const OVERRIDE { return #type; } \
905 const H##type* As##type() const OVERRIDE { return this; } \
906 H##type* As##type() OVERRIDE { return this; } \
907 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \
Roland Levillainccc07a92014-09-16 14:48:16 +0100908 return other->Is##type(); \
909 } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000910 void Accept(HGraphVisitor* visitor) OVERRIDE
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000911
David Brazdiled596192015-01-23 10:39:45 +0000912template <typename T> class HUseList;
913
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100914template <typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700915class HUseListNode : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000916 public:
David Brazdiled596192015-01-23 10:39:45 +0000917 HUseListNode* GetPrevious() const { return prev_; }
918 HUseListNode* GetNext() const { return next_; }
919 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100920 size_t GetIndex() const { return index_; }
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100921 void SetIndex(size_t index) { index_ = index; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100922
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000923 private:
David Brazdiled596192015-01-23 10:39:45 +0000924 HUseListNode(T user, size_t index)
925 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
926
927 T const user_;
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +0100928 size_t index_;
David Brazdiled596192015-01-23 10:39:45 +0000929 HUseListNode<T>* prev_;
930 HUseListNode<T>* next_;
931
932 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000933
934 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
935};
936
David Brazdiled596192015-01-23 10:39:45 +0000937template <typename T>
938class HUseList : public ValueObject {
939 public:
940 HUseList() : first_(nullptr) {}
941
942 void Clear() {
943 first_ = nullptr;
944 }
945
946 // Adds a new entry at the beginning of the use list and returns
947 // the newly created node.
948 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +0000949 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +0000950 if (IsEmpty()) {
951 first_ = new_node;
952 } else {
953 first_->prev_ = new_node;
954 new_node->next_ = first_;
955 first_ = new_node;
956 }
957 return new_node;
958 }
959
960 HUseListNode<T>* GetFirst() const {
961 return first_;
962 }
963
964 void Remove(HUseListNode<T>* node) {
David Brazdil1abb4192015-02-17 18:33:36 +0000965 DCHECK(node != nullptr);
966 DCHECK(Contains(node));
967
David Brazdiled596192015-01-23 10:39:45 +0000968 if (node->prev_ != nullptr) {
969 node->prev_->next_ = node->next_;
970 }
971 if (node->next_ != nullptr) {
972 node->next_->prev_ = node->prev_;
973 }
974 if (node == first_) {
975 first_ = node->next_;
976 }
977 }
978
David Brazdil1abb4192015-02-17 18:33:36 +0000979 bool Contains(const HUseListNode<T>* node) const {
980 if (node == nullptr) {
981 return false;
982 }
983 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
984 if (current == node) {
985 return true;
986 }
987 }
988 return false;
989 }
990
David Brazdiled596192015-01-23 10:39:45 +0000991 bool IsEmpty() const {
992 return first_ == nullptr;
993 }
994
995 bool HasOnlyOneUse() const {
996 return first_ != nullptr && first_->next_ == nullptr;
997 }
998
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100999 size_t SizeSlow() const {
1000 size_t count = 0;
1001 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
1002 ++count;
1003 }
1004 return count;
1005 }
1006
David Brazdiled596192015-01-23 10:39:45 +00001007 private:
1008 HUseListNode<T>* first_;
1009};
1010
1011template<typename T>
1012class HUseIterator : public ValueObject {
1013 public:
1014 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
1015
1016 bool Done() const { return current_ == nullptr; }
1017
1018 void Advance() {
1019 DCHECK(!Done());
1020 current_ = current_->GetNext();
1021 }
1022
1023 HUseListNode<T>* Current() const {
1024 DCHECK(!Done());
1025 return current_;
1026 }
1027
1028 private:
1029 HUseListNode<T>* current_;
1030
1031 friend class HValue;
1032};
1033
David Brazdil1abb4192015-02-17 18:33:36 +00001034// This class is used by HEnvironment and HInstruction classes to record the
1035// instructions they use and pointers to the corresponding HUseListNodes kept
1036// by the used instructions.
1037template <typename T>
1038class HUserRecord : public ValueObject {
1039 public:
1040 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
1041 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
1042
1043 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
1044 : instruction_(old_record.instruction_), use_node_(use_node) {
1045 DCHECK(instruction_ != nullptr);
1046 DCHECK(use_node_ != nullptr);
1047 DCHECK(old_record.use_node_ == nullptr);
1048 }
1049
1050 HInstruction* GetInstruction() const { return instruction_; }
1051 HUseListNode<T>* GetUseNode() const { return use_node_; }
1052
1053 private:
1054 // Instruction used by the user.
1055 HInstruction* instruction_;
1056
1057 // Corresponding entry in the use list kept by 'instruction_'.
1058 HUseListNode<T>* use_node_;
1059};
1060
Calin Juravle27df7582015-04-17 19:12:31 +01001061// TODO: Add better documentation to this class and maybe refactor with more suggestive names.
1062// - Has(All)SideEffects suggests that all the side effects are present but only ChangesSomething
1063// flag is consider.
1064// - DependsOn suggests that there is a real dependency between side effects but it only
1065// checks DependendsOnSomething flag.
1066//
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001067// Represents the side effects an instruction may have.
1068class SideEffects : public ValueObject {
1069 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001070 SideEffects() : flags_(0) {}
1071
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001072 static SideEffects None() {
1073 return SideEffects(0);
1074 }
1075
1076 static SideEffects All() {
1077 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
1078 }
1079
1080 static SideEffects ChangesSomething() {
1081 return SideEffects((1 << kFlagChangesCount) - 1);
1082 }
1083
1084 static SideEffects DependsOnSomething() {
1085 int count = kFlagDependsOnCount - kFlagChangesCount;
1086 return SideEffects(((1 << count) - 1) << kFlagChangesCount);
1087 }
1088
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001089 SideEffects Union(SideEffects other) const {
1090 return SideEffects(flags_ | other.flags_);
1091 }
1092
Roland Levillain72bceff2014-09-15 18:29:00 +01001093 bool HasSideEffects() const {
1094 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1095 return (flags_ & all_bits_set) != 0;
1096 }
1097
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001098 bool HasAllSideEffects() const {
1099 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1100 return all_bits_set == (flags_ & all_bits_set);
1101 }
1102
1103 bool DependsOn(SideEffects other) const {
1104 size_t depends_flags = other.ComputeDependsFlags();
1105 return (flags_ & depends_flags) != 0;
1106 }
1107
1108 bool HasDependencies() const {
1109 int count = kFlagDependsOnCount - kFlagChangesCount;
1110 size_t all_bits_set = (1 << count) - 1;
1111 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
1112 }
1113
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001114 private:
1115 static constexpr int kFlagChangesSomething = 0;
1116 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
1117
1118 static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
1119 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
1120
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001121 explicit SideEffects(size_t flags) : flags_(flags) {}
1122
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001123 size_t ComputeDependsFlags() const {
1124 return flags_ << kFlagChangesCount;
1125 }
1126
1127 size_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001128};
1129
David Brazdiled596192015-01-23 10:39:45 +00001130// A HEnvironment object contains the values of virtual registers at a given location.
1131class HEnvironment : public ArenaObject<kArenaAllocMisc> {
1132 public:
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001133 HEnvironment(ArenaAllocator* arena,
1134 size_t number_of_vregs,
1135 const DexFile& dex_file,
1136 uint32_t method_idx,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001137 uint32_t dex_pc,
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001138 InvokeType invoke_type,
1139 HInstruction* holder)
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001140 : vregs_(arena, number_of_vregs),
1141 locations_(arena, number_of_vregs),
1142 parent_(nullptr),
1143 dex_file_(dex_file),
1144 method_idx_(method_idx),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001145 dex_pc_(dex_pc),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001146 invoke_type_(invoke_type),
1147 holder_(holder) {
David Brazdiled596192015-01-23 10:39:45 +00001148 vregs_.SetSize(number_of_vregs);
1149 for (size_t i = 0; i < number_of_vregs; i++) {
David Brazdil1abb4192015-02-17 18:33:36 +00001150 vregs_.Put(i, HUserRecord<HEnvironment*>());
David Brazdiled596192015-01-23 10:39:45 +00001151 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001152
1153 locations_.SetSize(number_of_vregs);
1154 for (size_t i = 0; i < number_of_vregs; ++i) {
1155 locations_.Put(i, Location());
1156 }
1157 }
1158
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001159 HEnvironment(ArenaAllocator* arena, const HEnvironment& to_copy, HInstruction* holder)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001160 : HEnvironment(arena,
1161 to_copy.Size(),
1162 to_copy.GetDexFile(),
1163 to_copy.GetMethodIdx(),
1164 to_copy.GetDexPc(),
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001165 to_copy.GetInvokeType(),
1166 holder) {}
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001167
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001168 void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001169 if (parent_ != nullptr) {
1170 parent_->SetAndCopyParentChain(allocator, parent);
1171 } else {
1172 parent_ = new (allocator) HEnvironment(allocator, *parent, holder_);
1173 parent_->CopyFrom(parent);
1174 if (parent->GetParent() != nullptr) {
1175 parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1176 }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001177 }
David Brazdiled596192015-01-23 10:39:45 +00001178 }
1179
Nicolas Geoffray8c0c91a2015-05-07 11:46:05 +01001180 void CopyFrom(const GrowableArray<HInstruction*>& locals);
1181 void CopyFrom(HEnvironment* environment);
1182
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001183 // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1184 // input to the loop phi instead. This is for inserting instructions that
1185 // require an environment (like HDeoptimization) in the loop pre-header.
1186 void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
David Brazdiled596192015-01-23 10:39:45 +00001187
1188 void SetRawEnvAt(size_t index, HInstruction* instruction) {
David Brazdil1abb4192015-02-17 18:33:36 +00001189 vregs_.Put(index, HUserRecord<HEnvironment*>(instruction));
David Brazdiled596192015-01-23 10:39:45 +00001190 }
1191
1192 HInstruction* GetInstructionAt(size_t index) const {
David Brazdil1abb4192015-02-17 18:33:36 +00001193 return vregs_.Get(index).GetInstruction();
David Brazdiled596192015-01-23 10:39:45 +00001194 }
1195
David Brazdil1abb4192015-02-17 18:33:36 +00001196 void RemoveAsUserOfInput(size_t index) const;
David Brazdiled596192015-01-23 10:39:45 +00001197
1198 size_t Size() const { return vregs_.Size(); }
1199
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001200 HEnvironment* GetParent() const { return parent_; }
1201
1202 void SetLocationAt(size_t index, Location location) {
1203 locations_.Put(index, location);
1204 }
1205
1206 Location GetLocationAt(size_t index) const {
1207 return locations_.Get(index);
1208 }
1209
1210 uint32_t GetDexPc() const {
1211 return dex_pc_;
1212 }
1213
1214 uint32_t GetMethodIdx() const {
1215 return method_idx_;
1216 }
1217
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001218 InvokeType GetInvokeType() const {
1219 return invoke_type_;
1220 }
1221
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001222 const DexFile& GetDexFile() const {
1223 return dex_file_;
1224 }
1225
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001226 HInstruction* GetHolder() const {
1227 return holder_;
1228 }
1229
David Brazdiled596192015-01-23 10:39:45 +00001230 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001231 // Record instructions' use entries of this environment for constant-time removal.
1232 // It should only be called by HInstruction when a new environment use is added.
1233 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1234 DCHECK(env_use->GetUser() == this);
1235 size_t index = env_use->GetIndex();
1236 vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use));
1237 }
David Brazdiled596192015-01-23 10:39:45 +00001238
David Brazdil1abb4192015-02-17 18:33:36 +00001239 GrowableArray<HUserRecord<HEnvironment*> > vregs_;
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001240 GrowableArray<Location> locations_;
1241 HEnvironment* parent_;
1242 const DexFile& dex_file_;
1243 const uint32_t method_idx_;
1244 const uint32_t dex_pc_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001245 const InvokeType invoke_type_;
David Brazdiled596192015-01-23 10:39:45 +00001246
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001247 // The instruction that holds this environment. Only used in debug mode
1248 // to ensure the graph is consistent.
1249 HInstruction* const holder_;
1250
Nicolas Geoffray5d7b7f82015-04-28 00:52:43 +01001251 friend class HInstruction;
David Brazdiled596192015-01-23 10:39:45 +00001252
1253 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1254};
1255
Calin Juravleacf735c2015-02-12 15:25:22 +00001256class ReferenceTypeInfo : ValueObject {
1257 public:
Calin Juravleb1498f62015-02-16 13:13:29 +00001258 typedef Handle<mirror::Class> TypeHandle;
1259
1260 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
1261 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1262 if (type_handle->IsObjectClass()) {
1263 // Override the type handle to be consistent with the case when we get to
1264 // Top but don't have the Object class available. It avoids having to guess
1265 // what value the type_handle has when it's Top.
1266 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1267 } else {
1268 return ReferenceTypeInfo(type_handle, is_exact, false);
1269 }
1270 }
1271
1272 static ReferenceTypeInfo CreateTop(bool is_exact) {
1273 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
Calin Juravleacf735c2015-02-12 15:25:22 +00001274 }
1275
1276 bool IsExact() const { return is_exact_; }
1277 bool IsTop() const { return is_top_; }
1278
1279 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
1280
Calin Juravleb1498f62015-02-16 13:13:29 +00001281 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Calin Juravleacf735c2015-02-12 15:25:22 +00001282 if (IsTop()) {
1283 // Top (equivalent for java.lang.Object) is supertype of anything.
1284 return true;
1285 }
1286 if (rti.IsTop()) {
1287 // If we get here `this` is not Top() so it can't be a supertype.
1288 return false;
1289 }
1290 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
1291 }
1292
1293 // Returns true if the type information provide the same amount of details.
1294 // Note that it does not mean that the instructions have the same actual type
1295 // (e.g. tops are equal but they can be the result of a merge).
1296 bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1297 if (IsExact() != rti.IsExact()) {
1298 return false;
1299 }
1300 if (IsTop() && rti.IsTop()) {
1301 // `Top` means java.lang.Object, so the types are equivalent.
1302 return true;
1303 }
1304 if (IsTop() || rti.IsTop()) {
1305 // If only one is top or object than they are not equivalent.
1306 // NB: We need this extra check because the type_handle of `Top` is invalid
1307 // and we cannot inspect its reference.
1308 return false;
1309 }
1310
1311 // Finally check the types.
1312 return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
1313 }
1314
1315 private:
Calin Juravleb1498f62015-02-16 13:13:29 +00001316 ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
1317 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
1318 : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
1319
Calin Juravleacf735c2015-02-12 15:25:22 +00001320 // The class of the object.
Calin Juravleb1498f62015-02-16 13:13:29 +00001321 TypeHandle type_handle_;
Calin Juravleacf735c2015-02-12 15:25:22 +00001322 // Whether or not the type is exact or a superclass of the actual type.
Calin Juravleb1498f62015-02-16 13:13:29 +00001323 // Whether or not we have any information about this type.
Calin Juravleacf735c2015-02-12 15:25:22 +00001324 bool is_exact_;
1325 // A true value here means that the object type should be java.lang.Object.
1326 // We don't have access to the corresponding mirror object every time so this
1327 // flag acts as a substitute. When true, the TypeHandle refers to a null
1328 // pointer and should not be used.
1329 bool is_top_;
1330};
1331
1332std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
1333
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001334class HInstruction : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001335 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001336 explicit HInstruction(SideEffects side_effects)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001337 : previous_(nullptr),
1338 next_(nullptr),
1339 block_(nullptr),
1340 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001341 ssa_index_(-1),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001342 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001343 locations_(nullptr),
1344 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001345 lifetime_position_(kNoLifetime),
Calin Juravleb1498f62015-02-16 13:13:29 +00001346 side_effects_(side_effects),
1347 reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001348
Dave Allison20dfc792014-06-16 20:44:29 -07001349 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001350
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001351#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001352 enum InstructionKind {
1353 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1354 };
1355#undef DECLARE_KIND
1356
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001357 HInstruction* GetNext() const { return next_; }
1358 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001359
Calin Juravle77520bc2015-01-12 18:45:46 +00001360 HInstruction* GetNextDisregardingMoves() const;
1361 HInstruction* GetPreviousDisregardingMoves() const;
1362
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001363 HBasicBlock* GetBlock() const { return block_; }
1364 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001365 bool IsInBlock() const { return block_ != nullptr; }
1366 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray3ac17fc2014-08-06 23:02:54 +01001367 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001368
Roland Levillain6b879dd2014-09-22 17:13:44 +01001369 virtual size_t InputCount() const = 0;
David Brazdil1abb4192015-02-17 18:33:36 +00001370 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001371
1372 virtual void Accept(HGraphVisitor* visitor) = 0;
1373 virtual const char* DebugName() const = 0;
1374
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001375 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
David Brazdil1abb4192015-02-17 18:33:36 +00001376 void SetRawInputAt(size_t index, HInstruction* input) {
1377 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1378 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001379
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001380 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001381 virtual uint32_t GetDexPc() const {
1382 LOG(FATAL) << "GetDexPc() cannot be called on an instruction that"
1383 " does not need an environment";
1384 UNREACHABLE();
1385 }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001386 virtual bool IsControlFlow() const { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01001387 virtual bool CanThrow() const { return false; }
Roland Levillain72bceff2014-09-15 18:29:00 +01001388 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001389
Calin Juravle10e244f2015-01-26 18:54:32 +00001390 // Does not apply for all instructions, but having this at top level greatly
1391 // simplifies the null check elimination.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001392 virtual bool CanBeNull() const {
1393 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1394 return true;
1395 }
Calin Juravle10e244f2015-01-26 18:54:32 +00001396
Calin Juravle641547a2015-04-21 22:08:51 +01001397 virtual bool CanDoImplicitNullCheckOn(HInstruction* obj) const {
1398 UNUSED(obj);
1399 return false;
1400 }
Calin Juravle77520bc2015-01-12 18:45:46 +00001401
Calin Juravleacf735c2015-02-12 15:25:22 +00001402 void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
Calin Juravle61d544b2015-02-23 16:46:57 +00001403 DCHECK_EQ(GetType(), Primitive::kPrimNot);
Calin Juravleacf735c2015-02-12 15:25:22 +00001404 reference_type_info_ = reference_type_info;
1405 }
1406
Calin Juravle61d544b2015-02-23 16:46:57 +00001407 ReferenceTypeInfo GetReferenceTypeInfo() const {
1408 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1409 return reference_type_info_;
1410 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001411
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001412 void AddUseAt(HInstruction* user, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +00001413 DCHECK(user != nullptr);
1414 HUseListNode<HInstruction*>* use =
1415 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1416 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001417 }
1418
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001419 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +01001420 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +00001421 HUseListNode<HEnvironment*>* env_use =
1422 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1423 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001424 }
1425
David Brazdil1abb4192015-02-17 18:33:36 +00001426 void RemoveAsUserOfInput(size_t input) {
1427 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1428 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1429 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001430
David Brazdil1abb4192015-02-17 18:33:36 +00001431 const HUseList<HInstruction*>& GetUses() const { return uses_; }
1432 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001433
David Brazdiled596192015-01-23 10:39:45 +00001434 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
1435 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001436 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
Alexandre Rames188d4312015-04-09 18:30:21 +01001437 bool HasOnlyOneNonEnvironmentUse() const {
1438 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1439 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001440
Roland Levillain6c82d402014-10-13 16:10:27 +01001441 // Does this instruction strictly dominate `other_instruction`?
1442 // Returns false if this instruction and `other_instruction` are the same.
1443 // Aborts if this instruction and `other_instruction` are both phis.
1444 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +01001445
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001446 int GetId() const { return id_; }
1447 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001448
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001449 int GetSsaIndex() const { return ssa_index_; }
1450 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
1451 bool HasSsaIndex() const { return ssa_index_ != -1; }
1452
1453 bool HasEnvironment() const { return environment_ != nullptr; }
1454 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001455 // Set the `environment_` field. Raw because this method does not
1456 // update the uses lists.
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001457 void SetRawEnvironment(HEnvironment* environment) {
1458 DCHECK(environment_ == nullptr);
1459 DCHECK_EQ(environment->GetHolder(), this);
1460 environment_ = environment;
1461 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001462
1463 // Set the environment of this instruction, copying it from `environment`. While
1464 // copying, the uses lists are being updated.
1465 void CopyEnvironmentFrom(HEnvironment* environment) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001466 DCHECK(environment_ == nullptr);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001467 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001468 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001469 environment_->CopyFrom(environment);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001470 if (environment->GetParent() != nullptr) {
1471 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1472 }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001473 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001474
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001475 void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
1476 HBasicBlock* block) {
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001477 DCHECK(environment_ == nullptr);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001478 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01001479 environment_ = new (allocator) HEnvironment(allocator, *environment, this);
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01001480 environment_->CopyFromWithLoopPhiAdjustment(environment, block);
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001481 if (environment->GetParent() != nullptr) {
1482 environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1483 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001484 }
1485
Nicolas Geoffray39468442014-09-02 15:17:15 +01001486 // Returns the number of entries in the environment. Typically, that is the
1487 // number of dex registers in a method. It could be more in case of inlining.
1488 size_t EnvironmentSize() const;
1489
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001490 LocationSummary* GetLocations() const { return locations_; }
1491 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001492
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001493 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001494 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001495
Alexandre Rames188d4312015-04-09 18:30:21 +01001496 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1497 // uses of this instruction by `other` are *not* updated.
1498 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
1499 ReplaceWith(other);
1500 other->ReplaceInput(this, use_index);
1501 }
1502
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001503 // Move `this` instruction before `cursor`.
1504 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001505
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001506#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +01001507 bool Is##type() const { return (As##type() != nullptr); } \
1508 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001509 virtual H##type* As##type() { return nullptr; }
1510
1511 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
1512#undef INSTRUCTION_TYPE_CHECK
1513
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001514 // Returns whether the instruction can be moved within the graph.
1515 virtual bool CanBeMoved() const { return false; }
1516
1517 // Returns whether the two instructions are of the same kind.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001518 virtual bool InstructionTypeEquals(HInstruction* other) const {
1519 UNUSED(other);
1520 return false;
1521 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001522
1523 // Returns whether any data encoded in the two instructions is equal.
1524 // This method does not look at the inputs. Both instructions must be
1525 // of the same type, otherwise the method has undefined behavior.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001526 virtual bool InstructionDataEquals(HInstruction* other) const {
1527 UNUSED(other);
1528 return false;
1529 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001530
1531 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00001532 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001533 // 2) Their inputs are identical.
1534 bool Equals(HInstruction* other) const;
1535
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001536 virtual InstructionKind GetKind() const = 0;
1537
1538 virtual size_t ComputeHashCode() const {
1539 size_t result = GetKind();
1540 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1541 result = (result * 31) + InputAt(i)->GetId();
1542 }
1543 return result;
1544 }
1545
1546 SideEffects GetSideEffects() const { return side_effects_; }
1547
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001548 size_t GetLifetimePosition() const { return lifetime_position_; }
1549 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
1550 LiveInterval* GetLiveInterval() const { return live_interval_; }
1551 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
1552 bool HasLiveInterval() const { return live_interval_ != nullptr; }
1553
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00001554 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1555
1556 // Returns whether the code generation of the instruction will require to have access
1557 // to the current method. Such instructions are:
1558 // (1): Instructions that require an environment, as calling the runtime requires
1559 // to walk the stack and have the current method stored at a specific stack address.
1560 // (2): Object literals like classes and strings, that are loaded from the dex cache
1561 // fields of the current method.
1562 bool NeedsCurrentMethod() const {
1563 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1564 }
1565
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001566 virtual bool NeedsDexCache() const { return false; }
1567
David Brazdil1abb4192015-02-17 18:33:36 +00001568 protected:
1569 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
1570 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
1571
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001572 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001573 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
1574
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001575 HInstruction* previous_;
1576 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001577 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001578
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001579 // An instruction gets an id when it is added to the graph.
1580 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01001581 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001582 int id_;
1583
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001584 // When doing liveness analysis, instructions that have uses get an SSA index.
1585 int ssa_index_;
1586
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001587 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00001588 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001589
1590 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00001591 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001592
Nicolas Geoffray39468442014-09-02 15:17:15 +01001593 // The environment associated with this instruction. Not null if the instruction
1594 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001595 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001596
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001597 // Set by the code generator.
1598 LocationSummary* locations_;
1599
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001600 // Set by the liveness analysis.
1601 LiveInterval* live_interval_;
1602
1603 // Set by the liveness analysis, this is the position in a linear
1604 // order of blocks where this instruction's live interval start.
1605 size_t lifetime_position_;
1606
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001607 const SideEffects side_effects_;
1608
Calin Juravleacf735c2015-02-12 15:25:22 +00001609 // TODO: for primitive types this should be marked as invalid.
1610 ReferenceTypeInfo reference_type_info_;
1611
David Brazdil1abb4192015-02-17 18:33:36 +00001612 friend class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001613 friend class HBasicBlock;
David Brazdil1abb4192015-02-17 18:33:36 +00001614 friend class HEnvironment;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001615 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001616 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001617
1618 DISALLOW_COPY_AND_ASSIGN(HInstruction);
1619};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001620std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001621
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001622class HInputIterator : public ValueObject {
1623 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001624 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001625
1626 bool Done() const { return index_ == instruction_->InputCount(); }
1627 HInstruction* Current() const { return instruction_->InputAt(index_); }
1628 void Advance() { index_++; }
1629
1630 private:
1631 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001632 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001633
1634 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1635};
1636
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001637class HInstructionIterator : public ValueObject {
1638 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001639 explicit HInstructionIterator(const HInstructionList& instructions)
1640 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001641 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001642 }
1643
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001644 bool Done() const { return instruction_ == nullptr; }
1645 HInstruction* Current() const { return instruction_; }
1646 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001647 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001648 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001649 }
1650
1651 private:
1652 HInstruction* instruction_;
1653 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001654
1655 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001656};
1657
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001658class HBackwardInstructionIterator : public ValueObject {
1659 public:
1660 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1661 : instruction_(instructions.last_instruction_) {
1662 next_ = Done() ? nullptr : instruction_->GetPrevious();
1663 }
1664
1665 bool Done() const { return instruction_ == nullptr; }
1666 HInstruction* Current() const { return instruction_; }
1667 void Advance() {
1668 instruction_ = next_;
1669 next_ = Done() ? nullptr : instruction_->GetPrevious();
1670 }
1671
1672 private:
1673 HInstruction* instruction_;
1674 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001675
1676 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001677};
1678
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001679// An embedded container with N elements of type T. Used (with partial
1680// specialization for N=0) because embedded arrays cannot have size 0.
1681template<typename T, intptr_t N>
1682class EmbeddedArray {
1683 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001684 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001685
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001686 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001687
1688 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001689 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001690 return elements_[i];
1691 }
1692
1693 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001694 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001695 return elements_[i];
1696 }
1697
1698 const T& At(intptr_t i) const {
1699 return (*this)[i];
1700 }
1701
1702 void SetAt(intptr_t i, const T& val) {
1703 (*this)[i] = val;
1704 }
1705
1706 private:
1707 T elements_[N];
1708};
1709
1710template<typename T>
1711class EmbeddedArray<T, 0> {
1712 public:
1713 intptr_t length() const { return 0; }
1714 const T& operator[](intptr_t i) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001715 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001716 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001717 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001718 }
1719 T& operator[](intptr_t i) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001720 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001721 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001722 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001723 }
1724};
1725
1726template<intptr_t N>
1727class HTemplateInstruction: public HInstruction {
1728 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001729 HTemplateInstruction<N>(SideEffects side_effects)
1730 : HInstruction(side_effects), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07001731 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001732
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001733 size_t InputCount() const OVERRIDE { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001734
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001735 protected:
David Brazdil1abb4192015-02-17 18:33:36 +00001736 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; }
1737
1738 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
1739 inputs_[i] = input;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001740 }
1741
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001742 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001743 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001744
1745 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001746};
1747
Dave Allison20dfc792014-06-16 20:44:29 -07001748template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001749class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07001750 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001751 HExpression<N>(Primitive::Type type, SideEffects side_effects)
1752 : HTemplateInstruction<N>(side_effects), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07001753 virtual ~HExpression() {}
1754
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001755 Primitive::Type GetType() const OVERRIDE { return type_; }
Dave Allison20dfc792014-06-16 20:44:29 -07001756
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001757 protected:
1758 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07001759};
1760
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001761// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1762// instruction that branches to the exit block.
1763class HReturnVoid : public HTemplateInstruction<0> {
1764 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001765 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001766
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001767 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001768
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001769 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001770
1771 private:
1772 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1773};
1774
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001775// Represents dex's RETURN opcodes. A HReturn is a control flow
1776// instruction that branches to the exit block.
1777class HReturn : public HTemplateInstruction<1> {
1778 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001779 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001780 SetRawInputAt(0, value);
1781 }
1782
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001783 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001784
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001785 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001786
1787 private:
1788 DISALLOW_COPY_AND_ASSIGN(HReturn);
1789};
1790
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001791// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001792// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001793// exit block.
1794class HExit : public HTemplateInstruction<0> {
1795 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001796 HExit() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001797
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001798 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001799
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001800 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001801
1802 private:
1803 DISALLOW_COPY_AND_ASSIGN(HExit);
1804};
1805
1806// Jumps from one block to another.
1807class HGoto : public HTemplateInstruction<0> {
1808 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001809 HGoto() : HTemplateInstruction(SideEffects::None()) {}
1810
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001811 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001812
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001813 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001814 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001815 }
1816
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001817 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001818
1819 private:
1820 DISALLOW_COPY_AND_ASSIGN(HGoto);
1821};
1822
Dave Allison20dfc792014-06-16 20:44:29 -07001823
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001824// Conditional branch. A block ending with an HIf instruction must have
1825// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001826class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001827 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001828 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001829 SetRawInputAt(0, input);
1830 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001831
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001832 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001833
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001834 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001835 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001836 }
1837
1838 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001839 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001840 }
1841
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001842 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001843
1844 private:
1845 DISALLOW_COPY_AND_ASSIGN(HIf);
1846};
1847
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001848// Deoptimize to interpreter, upon checking a condition.
1849class HDeoptimize : public HTemplateInstruction<1> {
1850 public:
1851 HDeoptimize(HInstruction* cond, uint32_t dex_pc)
1852 : HTemplateInstruction(SideEffects::None()),
1853 dex_pc_(dex_pc) {
1854 SetRawInputAt(0, cond);
1855 }
1856
1857 bool NeedsEnvironment() const OVERRIDE { return true; }
1858 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01001859 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001860
1861 DECLARE_INSTRUCTION(Deoptimize);
1862
1863 private:
1864 uint32_t dex_pc_;
1865
1866 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
1867};
1868
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01001869// Represents the ArtMethod that was passed as a first argument to
1870// the method. It is used by instructions that depend on it, like
1871// instructions that work with the dex cache.
1872class HCurrentMethod : public HExpression<0> {
1873 public:
1874 HCurrentMethod() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
1875
1876 DECLARE_INSTRUCTION(CurrentMethod);
1877
1878 private:
1879 DISALLOW_COPY_AND_ASSIGN(HCurrentMethod);
1880};
1881
Roland Levillain88cb1752014-10-20 16:36:47 +01001882class HUnaryOperation : public HExpression<1> {
1883 public:
1884 HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1885 : HExpression(result_type, SideEffects::None()) {
1886 SetRawInputAt(0, input);
1887 }
1888
1889 HInstruction* GetInput() const { return InputAt(0); }
1890 Primitive::Type GetResultType() const { return GetType(); }
1891
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001892 bool CanBeMoved() const OVERRIDE { return true; }
1893 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001894 UNUSED(other);
1895 return true;
1896 }
Roland Levillain88cb1752014-10-20 16:36:47 +01001897
Roland Levillain9240d6a2014-10-20 16:47:04 +01001898 // Try to statically evaluate `operation` and return a HConstant
1899 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001900 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001901 HConstant* TryStaticEvaluation() const;
1902
1903 // Apply this operation to `x`.
1904 virtual int32_t Evaluate(int32_t x) const = 0;
1905 virtual int64_t Evaluate(int64_t x) const = 0;
1906
Roland Levillain88cb1752014-10-20 16:36:47 +01001907 DECLARE_INSTRUCTION(UnaryOperation);
1908
1909 private:
1910 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1911};
1912
Dave Allison20dfc792014-06-16 20:44:29 -07001913class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001914 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001915 HBinaryOperation(Primitive::Type result_type,
1916 HInstruction* left,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001917 HInstruction* right) : HExpression(result_type, SideEffects::None()) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001918 SetRawInputAt(0, left);
1919 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001920 }
1921
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001922 HInstruction* GetLeft() const { return InputAt(0); }
1923 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07001924 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001925
Mingyao Yangdc5ac732015-02-25 11:28:05 -08001926 virtual bool IsCommutative() const { return false; }
1927
1928 // Put constant on the right.
1929 // Returns whether order is changed.
1930 bool OrderInputsWithConstantOnTheRight() {
1931 HInstruction* left = InputAt(0);
1932 HInstruction* right = InputAt(1);
1933 if (left->IsConstant() && !right->IsConstant()) {
1934 ReplaceInput(right, 0);
1935 ReplaceInput(left, 1);
1936 return true;
1937 }
1938 return false;
1939 }
1940
1941 // Order inputs by instruction id, but favor constant on the right side.
1942 // This helps GVN for commutative ops.
1943 void OrderInputs() {
1944 DCHECK(IsCommutative());
1945 HInstruction* left = InputAt(0);
1946 HInstruction* right = InputAt(1);
1947 if (left == right || (!left->IsConstant() && right->IsConstant())) {
1948 return;
1949 }
1950 if (OrderInputsWithConstantOnTheRight()) {
1951 return;
1952 }
1953 // Order according to instruction id.
1954 if (left->GetId() > right->GetId()) {
1955 ReplaceInput(right, 0);
1956 ReplaceInput(left, 1);
1957 }
1958 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001959
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001960 bool CanBeMoved() const OVERRIDE { return true; }
1961 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001962 UNUSED(other);
1963 return true;
1964 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001965
Roland Levillain9240d6a2014-10-20 16:47:04 +01001966 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01001967 // containing the result of this evaluation. If `operation` cannot
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001968 // be evaluated as a constant, return null.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001969 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01001970
1971 // Apply this operation to `x` and `y`.
1972 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1973 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1974
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001975 // Returns an input that can legally be used as the right input and is
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001976 // constant, or null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001977 HConstant* GetConstantRight() const;
1978
1979 // If `GetConstantRight()` returns one of the input, this returns the other
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001980 // one. Otherwise it returns null.
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001981 HInstruction* GetLeastConstantLeft() const;
1982
Roland Levillainccc07a92014-09-16 14:48:16 +01001983 DECLARE_INSTRUCTION(BinaryOperation);
1984
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001985 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001986 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1987};
1988
Dave Allison20dfc792014-06-16 20:44:29 -07001989class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001990 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001991 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001992 : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1993 needs_materialization_(true) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001994
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001995 bool NeedsMaterialization() const { return needs_materialization_; }
1996 void ClearNeedsMaterialization() { needs_materialization_ = false; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001997
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001998 // For code generation purposes, returns whether this instruction is just before
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001999 // `instruction`, and disregard moves in between.
2000 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
Nicolas Geoffray18efde52014-09-22 15:51:11 +01002001
Dave Allison20dfc792014-06-16 20:44:29 -07002002 DECLARE_INSTRUCTION(Condition);
2003
2004 virtual IfCondition GetCondition() const = 0;
2005
2006 private:
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002007 // For register allocation purposes, returns whether this instruction needs to be
2008 // materialized (that is, not just be in the processor flags).
2009 bool needs_materialization_;
2010
Dave Allison20dfc792014-06-16 20:44:29 -07002011 DISALLOW_COPY_AND_ASSIGN(HCondition);
2012};
2013
2014// Instruction to check if two inputs are equal to each other.
2015class HEqual : public HCondition {
2016 public:
2017 HEqual(HInstruction* first, HInstruction* second)
2018 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002019
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002020 bool IsCommutative() const OVERRIDE { return true; }
2021
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002022 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002023 return x == y ? 1 : 0;
2024 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002025 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002026 return x == y ? 1 : 0;
2027 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002028
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002029 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002030
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002031 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002032 return kCondEQ;
2033 }
2034
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002035 private:
2036 DISALLOW_COPY_AND_ASSIGN(HEqual);
2037};
2038
Dave Allison20dfc792014-06-16 20:44:29 -07002039class HNotEqual : public HCondition {
2040 public:
2041 HNotEqual(HInstruction* first, HInstruction* second)
2042 : HCondition(first, second) {}
2043
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002044 bool IsCommutative() const OVERRIDE { return true; }
2045
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002046 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002047 return x != y ? 1 : 0;
2048 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002049 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002050 return x != y ? 1 : 0;
2051 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002052
Dave Allison20dfc792014-06-16 20:44:29 -07002053 DECLARE_INSTRUCTION(NotEqual);
2054
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002055 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002056 return kCondNE;
2057 }
2058
2059 private:
2060 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
2061};
2062
2063class HLessThan : public HCondition {
2064 public:
2065 HLessThan(HInstruction* first, HInstruction* second)
2066 : HCondition(first, second) {}
2067
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002068 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002069 return x < y ? 1 : 0;
2070 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002071 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002072 return x < y ? 1 : 0;
2073 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002074
Dave Allison20dfc792014-06-16 20:44:29 -07002075 DECLARE_INSTRUCTION(LessThan);
2076
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002077 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002078 return kCondLT;
2079 }
2080
2081 private:
2082 DISALLOW_COPY_AND_ASSIGN(HLessThan);
2083};
2084
2085class HLessThanOrEqual : public HCondition {
2086 public:
2087 HLessThanOrEqual(HInstruction* first, HInstruction* second)
2088 : HCondition(first, second) {}
2089
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002090 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002091 return x <= y ? 1 : 0;
2092 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002093 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002094 return x <= y ? 1 : 0;
2095 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002096
Dave Allison20dfc792014-06-16 20:44:29 -07002097 DECLARE_INSTRUCTION(LessThanOrEqual);
2098
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002099 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002100 return kCondLE;
2101 }
2102
2103 private:
2104 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
2105};
2106
2107class HGreaterThan : public HCondition {
2108 public:
2109 HGreaterThan(HInstruction* first, HInstruction* second)
2110 : HCondition(first, second) {}
2111
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002112 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002113 return x > y ? 1 : 0;
2114 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002115 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002116 return x > y ? 1 : 0;
2117 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002118
Dave Allison20dfc792014-06-16 20:44:29 -07002119 DECLARE_INSTRUCTION(GreaterThan);
2120
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002121 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002122 return kCondGT;
2123 }
2124
2125 private:
2126 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
2127};
2128
2129class HGreaterThanOrEqual : public HCondition {
2130 public:
2131 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
2132 : HCondition(first, second) {}
2133
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002134 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002135 return x >= y ? 1 : 0;
2136 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002137 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002138 return x >= y ? 1 : 0;
2139 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002140
Dave Allison20dfc792014-06-16 20:44:29 -07002141 DECLARE_INSTRUCTION(GreaterThanOrEqual);
2142
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002143 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07002144 return kCondGE;
2145 }
2146
2147 private:
2148 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
2149};
2150
2151
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002152// Instruction to check how two inputs compare to each other.
2153// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
2154class HCompare : public HBinaryOperation {
2155 public:
Calin Juravleddb7df22014-11-25 20:56:51 +00002156 // The bias applies for floating point operations and indicates how NaN
2157 // comparisons are treated:
2158 enum Bias {
2159 kNoBias, // bias is not applicable (i.e. for long operation)
2160 kGtBias, // return 1 for NaN comparisons
2161 kLtBias, // return -1 for NaN comparisons
2162 };
2163
2164 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias)
2165 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002166 DCHECK_EQ(type, first->GetType());
2167 DCHECK_EQ(type, second->GetType());
2168 }
2169
Calin Juravleddb7df22014-11-25 20:56:51 +00002170 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002171 return
2172 x == y ? 0 :
2173 x > y ? 1 :
2174 -1;
2175 }
Calin Juravleddb7df22014-11-25 20:56:51 +00002176
2177 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01002178 return
2179 x == y ? 0 :
2180 x > y ? 1 :
2181 -1;
2182 }
2183
Calin Juravleddb7df22014-11-25 20:56:51 +00002184 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2185 return bias_ == other->AsCompare()->bias_;
2186 }
2187
2188 bool IsGtBias() { return bias_ == kGtBias; }
2189
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002190 DECLARE_INSTRUCTION(Compare);
2191
2192 private:
Calin Juravleddb7df22014-11-25 20:56:51 +00002193 const Bias bias_;
2194
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01002195 DISALLOW_COPY_AND_ASSIGN(HCompare);
2196};
2197
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002198// A local in the graph. Corresponds to a Dex register.
2199class HLocal : public HTemplateInstruction<0> {
2200 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002201 explicit HLocal(uint16_t reg_number)
2202 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002203
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002204 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002205
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002206 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002207
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002208 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002209 // The Dex register number.
2210 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002211
2212 DISALLOW_COPY_AND_ASSIGN(HLocal);
2213};
2214
2215// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07002216class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002217 public:
Roland Levillain5799fc02014-09-25 12:15:20 +01002218 HLoadLocal(HLocal* local, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002219 : HExpression(type, SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002220 SetRawInputAt(0, local);
2221 }
2222
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002223 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2224
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002225 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002226
2227 private:
2228 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
2229};
2230
2231// Store a value in a given local. This instruction has two inputs: the value
2232// and the local.
2233class HStoreLocal : public HTemplateInstruction<2> {
2234 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002235 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002236 SetRawInputAt(0, local);
2237 SetRawInputAt(1, value);
2238 }
2239
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002240 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2241
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002242 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002243
2244 private:
2245 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
2246};
2247
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002248class HConstant : public HExpression<0> {
2249 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002250 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
2251
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002252 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002253
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002254 virtual bool IsMinusOne() const { return false; }
2255 virtual bool IsZero() const { return false; }
2256 virtual bool IsOne() const { return false; }
2257
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002258 DECLARE_INSTRUCTION(Constant);
2259
2260 private:
2261 DISALLOW_COPY_AND_ASSIGN(HConstant);
2262};
2263
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002264class HFloatConstant : public HConstant {
2265 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002266 float GetValue() const { return value_; }
2267
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002268 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002269 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
2270 bit_cast<uint32_t, float>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002271 }
2272
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002273 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002274
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002275 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002276 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>((-1.0f));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002277 }
2278 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002279 return value_ == 0.0f;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002280 }
2281 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002282 return bit_cast<uint32_t, float>(value_) == bit_cast<uint32_t, float>(1.0f);
2283 }
2284 bool IsNaN() const {
2285 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002286 }
2287
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002288 DECLARE_INSTRUCTION(FloatConstant);
2289
2290 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002291 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002292 explicit HFloatConstant(int32_t value)
2293 : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002294
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002295 const float value_;
2296
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002297 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002298 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002299 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002300 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2301};
2302
2303class HDoubleConstant : public HConstant {
2304 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002305 double GetValue() const { return value_; }
2306
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002307 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002308 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
2309 bit_cast<uint64_t, double>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002310 }
2311
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002312 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002313
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002314 bool IsMinusOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002315 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>((-1.0));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002316 }
2317 bool IsZero() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002318 return value_ == 0.0;
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002319 }
2320 bool IsOne() const OVERRIDE {
Roland Levillain3b55ebb2015-05-08 13:13:19 +01002321 return bit_cast<uint64_t, double>(value_) == bit_cast<uint64_t, double>(1.0);
2322 }
2323 bool IsNaN() const {
2324 return std::isnan(value_);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002325 }
2326
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002327 DECLARE_INSTRUCTION(DoubleConstant);
2328
2329 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002330 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002331 explicit HDoubleConstant(int64_t value)
2332 : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {}
David Brazdil8d5b8b22015-03-24 10:51:52 +00002333
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002334 const double value_;
2335
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002336 // Only the SsaBuilder and HGraph can create floating-point constants.
David Brazdil8d5b8b22015-03-24 10:51:52 +00002337 friend class SsaBuilder;
Nicolas Geoffrayf213e052015-04-27 08:53:46 +00002338 friend class HGraph;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002339 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2340};
2341
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002342class HNullConstant : public HConstant {
2343 public:
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002344 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2345 return true;
2346 }
2347
2348 size_t ComputeHashCode() const OVERRIDE { return 0; }
2349
2350 DECLARE_INSTRUCTION(NullConstant);
2351
2352 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002353 HNullConstant() : HConstant(Primitive::kPrimNot) {}
2354
2355 friend class HGraph;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002356 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2357};
2358
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002359// Constants of the type int. Those can be from Dex instructions, or
2360// synthesized (for example with the if-eqz instruction).
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002361class HIntConstant : public HConstant {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002362 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002363 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002364
Calin Juravle61d544b2015-02-23 16:46:57 +00002365 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002366 return other->AsIntConstant()->value_ == value_;
2367 }
2368
Calin Juravle61d544b2015-02-23 16:46:57 +00002369 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2370
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002371 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2372 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2373 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2374
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002375 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002376
2377 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002378 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
2379
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002380 const int32_t value_;
2381
David Brazdil8d5b8b22015-03-24 10:51:52 +00002382 friend class HGraph;
2383 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
Zheng Xuad4450e2015-04-17 18:48:56 +08002384 ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002385 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2386};
2387
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002388class HLongConstant : public HConstant {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002389 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002390 int64_t GetValue() const { return value_; }
2391
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002392 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002393 return other->AsLongConstant()->value_ == value_;
2394 }
2395
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002396 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002397
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002398 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2399 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2400 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2401
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002402 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002403
2404 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002405 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
2406
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002407 const int64_t value_;
2408
David Brazdil8d5b8b22015-03-24 10:51:52 +00002409 friend class HGraph;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002410 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2411};
2412
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002413enum class Intrinsics {
2414#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
2415#include "intrinsics_list.h"
2416 kNone,
2417 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
2418#undef INTRINSICS_LIST
2419#undef OPTIMIZING_INTRINSICS
2420};
2421std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
2422
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002423class HInvoke : public HInstruction {
2424 public:
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002425 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002426
2427 // Runtime needs to walk the stack, so Dex -> Dex calls need to
2428 // know their environment.
Calin Juravle77520bc2015-01-12 18:45:46 +00002429 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002430
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01002431 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002432 SetRawInputAt(index, argument);
2433 }
2434
Roland Levillain3e3d7332015-04-28 11:00:54 +01002435 // Return the number of arguments. This number can be lower than
2436 // the number of inputs returned by InputCount(), as some invoke
2437 // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
2438 // inputs at the end of their list of inputs.
2439 uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
2440
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002441 Primitive::Type GetType() const OVERRIDE { return return_type_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002442
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002443 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002444
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002445 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002446 const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002447
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002448 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
2449
Nicolas Geoffray1ba19812015-04-21 09:12:40 +01002450 Intrinsics GetIntrinsic() const {
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002451 return intrinsic_;
2452 }
2453
2454 void SetIntrinsic(Intrinsics intrinsic) {
2455 intrinsic_ = intrinsic;
2456 }
2457
Nicolas Geoffrayd23eeef2015-05-18 22:31:29 +01002458 bool IsInlined() const {
2459 return GetEnvironment()->GetParent() != nullptr;
2460 }
2461
2462 bool CanThrow() const OVERRIDE { return true; }
2463
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002464 DECLARE_INSTRUCTION(Invoke);
2465
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002466 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002467 HInvoke(ArenaAllocator* arena,
2468 uint32_t number_of_arguments,
Roland Levillain3e3d7332015-04-28 11:00:54 +01002469 uint32_t number_of_other_inputs,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002470 Primitive::Type return_type,
2471 uint32_t dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002472 uint32_t dex_method_index,
2473 InvokeType original_invoke_type)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002474 : HInstruction(SideEffects::All()),
Roland Levillain3e3d7332015-04-28 11:00:54 +01002475 number_of_arguments_(number_of_arguments),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002476 inputs_(arena, number_of_arguments),
2477 return_type_(return_type),
2478 dex_pc_(dex_pc),
2479 dex_method_index_(dex_method_index),
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002480 original_invoke_type_(original_invoke_type),
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002481 intrinsic_(Intrinsics::kNone) {
Roland Levillain3e3d7332015-04-28 11:00:54 +01002482 uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
2483 inputs_.SetSize(number_of_inputs);
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002484 }
2485
David Brazdil1abb4192015-02-17 18:33:36 +00002486 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
2487 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2488 inputs_.Put(index, input);
2489 }
2490
Roland Levillain3e3d7332015-04-28 11:00:54 +01002491 uint32_t number_of_arguments_;
David Brazdil1abb4192015-02-17 18:33:36 +00002492 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002493 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002494 const uint32_t dex_pc_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002495 const uint32_t dex_method_index_;
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002496 const InvokeType original_invoke_type_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002497 Intrinsics intrinsic_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002498
2499 private:
2500 DISALLOW_COPY_AND_ASSIGN(HInvoke);
2501};
2502
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002503class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002504 public:
Roland Levillain4c0eb422015-04-24 16:43:49 +01002505 // Requirements of this method call regarding the class
2506 // initialization (clinit) check of its declaring class.
2507 enum class ClinitCheckRequirement {
2508 kNone, // Class already initialized.
2509 kExplicit, // Static call having explicit clinit check as last input.
2510 kImplicit, // Static call implicitly requiring a clinit check.
2511 };
2512
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002513 HInvokeStaticOrDirect(ArenaAllocator* arena,
2514 uint32_t number_of_arguments,
2515 Primitive::Type return_type,
2516 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002517 uint32_t dex_method_index,
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002518 bool is_recursive,
Jeff Hao848f70a2014-01-15 13:49:50 -08002519 int32_t string_init_offset,
Nicolas Geoffray79041292015-03-26 10:05:54 +00002520 InvokeType original_invoke_type,
Roland Levillain4c0eb422015-04-24 16:43:49 +01002521 InvokeType invoke_type,
2522 ClinitCheckRequirement clinit_check_requirement)
Roland Levillain3e3d7332015-04-28 11:00:54 +01002523 : HInvoke(arena,
2524 number_of_arguments,
2525 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
2526 return_type,
2527 dex_pc,
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002528 dex_method_index,
2529 original_invoke_type),
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002530 invoke_type_(invoke_type),
Roland Levillain4c0eb422015-04-24 16:43:49 +01002531 is_recursive_(is_recursive),
Jeff Hao848f70a2014-01-15 13:49:50 -08002532 clinit_check_requirement_(clinit_check_requirement),
2533 string_init_offset_(string_init_offset) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002534
Calin Juravle641547a2015-04-21 22:08:51 +01002535 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2536 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00002537 // We access the method via the dex cache so we can't do an implicit null check.
2538 // TODO: for intrinsics we can generate implicit null checks.
2539 return false;
2540 }
2541
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002542 InvokeType GetInvokeType() const { return invoke_type_; }
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002543 bool IsRecursive() const { return is_recursive_; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002544 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
Jeff Hao848f70a2014-01-15 13:49:50 -08002545 bool IsStringInit() const { return string_init_offset_ != 0; }
2546 int32_t GetStringInitOffset() const { return string_init_offset_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002547
Roland Levillain4c0eb422015-04-24 16:43:49 +01002548 // Is this instruction a call to a static method?
2549 bool IsStatic() const {
2550 return GetInvokeType() == kStatic;
2551 }
2552
Roland Levillain3e3d7332015-04-28 11:00:54 +01002553 // Remove the art::HLoadClass instruction set as last input by
2554 // art::PrepareForRegisterAllocation::VisitClinitCheck in lieu of
2555 // the initial art::HClinitCheck instruction (only relevant for
2556 // static calls with explicit clinit check).
2557 void RemoveLoadClassAsLastInput() {
Roland Levillain4c0eb422015-04-24 16:43:49 +01002558 DCHECK(IsStaticWithExplicitClinitCheck());
2559 size_t last_input_index = InputCount() - 1;
2560 HInstruction* last_input = InputAt(last_input_index);
2561 DCHECK(last_input != nullptr);
Roland Levillain3e3d7332015-04-28 11:00:54 +01002562 DCHECK(last_input->IsLoadClass()) << last_input->DebugName();
Roland Levillain4c0eb422015-04-24 16:43:49 +01002563 RemoveAsUserOfInput(last_input_index);
2564 inputs_.DeleteAt(last_input_index);
2565 clinit_check_requirement_ = ClinitCheckRequirement::kImplicit;
2566 DCHECK(IsStaticWithImplicitClinitCheck());
2567 }
2568
2569 // Is this a call to a static method whose declaring class has an
2570 // explicit intialization check in the graph?
2571 bool IsStaticWithExplicitClinitCheck() const {
2572 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit);
2573 }
2574
2575 // Is this a call to a static method whose declaring class has an
2576 // implicit intialization check requirement?
2577 bool IsStaticWithImplicitClinitCheck() const {
2578 return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit);
2579 }
2580
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002581 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002582
Roland Levillain4c0eb422015-04-24 16:43:49 +01002583 protected:
2584 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
2585 const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i);
2586 if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) {
2587 HInstruction* input = input_record.GetInstruction();
2588 // `input` is the last input of a static invoke marked as having
2589 // an explicit clinit check. It must either be:
2590 // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
2591 // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
2592 DCHECK(input != nullptr);
2593 DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName();
2594 }
2595 return input_record;
2596 }
2597
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002598 private:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002599 const InvokeType invoke_type_;
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002600 const bool is_recursive_;
Roland Levillain4c0eb422015-04-24 16:43:49 +01002601 ClinitCheckRequirement clinit_check_requirement_;
Jeff Hao848f70a2014-01-15 13:49:50 -08002602 // Thread entrypoint offset for string init method if this is a string init invoke.
2603 // Note that there are multiple string init methods, each having its own offset.
2604 int32_t string_init_offset_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002605
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002606 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002607};
2608
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002609class HInvokeVirtual : public HInvoke {
2610 public:
2611 HInvokeVirtual(ArenaAllocator* arena,
2612 uint32_t number_of_arguments,
2613 Primitive::Type return_type,
2614 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002615 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002616 uint32_t vtable_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002617 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kVirtual),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002618 vtable_index_(vtable_index) {}
2619
Calin Juravle641547a2015-04-21 22:08:51 +01002620 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002621 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002622 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002623 }
2624
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002625 uint32_t GetVTableIndex() const { return vtable_index_; }
2626
2627 DECLARE_INSTRUCTION(InvokeVirtual);
2628
2629 private:
2630 const uint32_t vtable_index_;
2631
2632 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
2633};
2634
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002635class HInvokeInterface : public HInvoke {
2636 public:
2637 HInvokeInterface(ArenaAllocator* arena,
2638 uint32_t number_of_arguments,
2639 Primitive::Type return_type,
2640 uint32_t dex_pc,
2641 uint32_t dex_method_index,
2642 uint32_t imt_index)
Nicolas Geoffrayb176d7c2015-05-20 18:48:31 +01002643 : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index, kInterface),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002644 imt_index_(imt_index) {}
2645
Calin Juravle641547a2015-04-21 22:08:51 +01002646 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
Calin Juravle77520bc2015-01-12 18:45:46 +00002647 // TODO: Add implicit null checks in intrinsics.
Calin Juravle641547a2015-04-21 22:08:51 +01002648 return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
Calin Juravle77520bc2015-01-12 18:45:46 +00002649 }
2650
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002651 uint32_t GetImtIndex() const { return imt_index_; }
2652 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2653
2654 DECLARE_INSTRUCTION(InvokeInterface);
2655
2656 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002657 const uint32_t imt_index_;
2658
2659 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
2660};
2661
Dave Allison20dfc792014-06-16 20:44:29 -07002662class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002663 public:
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002664 HNewInstance(uint32_t dex_pc,
2665 uint16_t type_index,
2666 const DexFile& dex_file,
2667 QuickEntrypointEnum entrypoint)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002668 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2669 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002670 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002671 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002672 entrypoint_(entrypoint) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002673
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002674 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002675 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002676 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002677
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002678 // Calls runtime so needs an environment.
Calin Juravle92a6ed22014-12-02 18:58:03 +00002679 bool NeedsEnvironment() const OVERRIDE { return true; }
2680 // It may throw when called on:
2681 // - interfaces
2682 // - abstract/innaccessible/unknown classes
2683 // TODO: optimize when possible.
2684 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002685
Calin Juravle10e244f2015-01-26 18:54:32 +00002686 bool CanBeNull() const OVERRIDE { return false; }
2687
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002688 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2689
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002690 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002691
2692 private:
2693 const uint32_t dex_pc_;
2694 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01002695 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002696 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002697
2698 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
2699};
2700
Roland Levillain88cb1752014-10-20 16:36:47 +01002701class HNeg : public HUnaryOperation {
2702 public:
2703 explicit HNeg(Primitive::Type result_type, HInstruction* input)
2704 : HUnaryOperation(result_type, input) {}
2705
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002706 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
2707 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
Roland Levillain9240d6a2014-10-20 16:47:04 +01002708
Roland Levillain88cb1752014-10-20 16:36:47 +01002709 DECLARE_INSTRUCTION(Neg);
2710
2711 private:
2712 DISALLOW_COPY_AND_ASSIGN(HNeg);
2713};
2714
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002715class HNewArray : public HExpression<1> {
2716 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002717 HNewArray(HInstruction* length,
2718 uint32_t dex_pc,
2719 uint16_t type_index,
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002720 const DexFile& dex_file,
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002721 QuickEntrypointEnum entrypoint)
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002722 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2723 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002724 type_index_(type_index),
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002725 dex_file_(dex_file),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002726 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002727 SetRawInputAt(0, length);
2728 }
2729
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002730 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002731 uint16_t GetTypeIndex() const { return type_index_; }
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002732 const DexFile& GetDexFile() const { return dex_file_; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002733
2734 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00002735 bool NeedsEnvironment() const OVERRIDE { return true; }
2736
Mingyao Yang0c365e62015-03-31 15:09:29 -07002737 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
2738 bool CanThrow() const OVERRIDE { return true; }
2739
Calin Juravle10e244f2015-01-26 18:54:32 +00002740 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002741
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002742 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2743
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002744 DECLARE_INSTRUCTION(NewArray);
2745
2746 private:
2747 const uint32_t dex_pc_;
2748 const uint16_t type_index_;
Guillaume "Vermeille" Sanchez81d804a2015-05-20 12:42:25 +01002749 const DexFile& dex_file_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002750 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002751
2752 DISALLOW_COPY_AND_ASSIGN(HNewArray);
2753};
2754
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002755class HAdd : public HBinaryOperation {
2756 public:
2757 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2758 : HBinaryOperation(result_type, left, right) {}
2759
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002760 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002761
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002762 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002763 return x + y;
2764 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002765 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002766 return x + y;
2767 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002768
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002769 DECLARE_INSTRUCTION(Add);
2770
2771 private:
2772 DISALLOW_COPY_AND_ASSIGN(HAdd);
2773};
2774
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002775class HSub : public HBinaryOperation {
2776 public:
2777 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2778 : HBinaryOperation(result_type, left, right) {}
2779
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002780 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002781 return x - y;
2782 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002783 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002784 return x - y;
2785 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002786
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002787 DECLARE_INSTRUCTION(Sub);
2788
2789 private:
2790 DISALLOW_COPY_AND_ASSIGN(HSub);
2791};
2792
Calin Juravle34bacdf2014-10-07 20:23:36 +01002793class HMul : public HBinaryOperation {
2794 public:
2795 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2796 : HBinaryOperation(result_type, left, right) {}
2797
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002798 bool IsCommutative() const OVERRIDE { return true; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002799
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002800 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
2801 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002802
2803 DECLARE_INSTRUCTION(Mul);
2804
2805 private:
2806 DISALLOW_COPY_AND_ASSIGN(HMul);
2807};
2808
Calin Juravle7c4954d2014-10-28 16:57:40 +00002809class HDiv : public HBinaryOperation {
2810 public:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002811 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2812 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00002813
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002814 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002815 // Our graph structure ensures we never have 0 for `y` during constant folding.
2816 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00002817 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002818 return (y == -1) ? -x : x / y;
2819 }
Calin Juravlebacfec32014-11-14 15:54:36 +00002820
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002821 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002822 DCHECK_NE(y, 0);
2823 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2824 return (y == -1) ? -x : x / y;
2825 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00002826
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002827 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002828
Calin Juravle7c4954d2014-10-28 16:57:40 +00002829 DECLARE_INSTRUCTION(Div);
2830
2831 private:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002832 const uint32_t dex_pc_;
2833
Calin Juravle7c4954d2014-10-28 16:57:40 +00002834 DISALLOW_COPY_AND_ASSIGN(HDiv);
2835};
2836
Calin Juravlebacfec32014-11-14 15:54:36 +00002837class HRem : public HBinaryOperation {
2838 public:
2839 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2840 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2841
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002842 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002843 DCHECK_NE(y, 0);
2844 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2845 return (y == -1) ? 0 : x % y;
2846 }
2847
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002848 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002849 DCHECK_NE(y, 0);
2850 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2851 return (y == -1) ? 0 : x % y;
2852 }
2853
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002854 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravlebacfec32014-11-14 15:54:36 +00002855
2856 DECLARE_INSTRUCTION(Rem);
2857
2858 private:
2859 const uint32_t dex_pc_;
2860
2861 DISALLOW_COPY_AND_ASSIGN(HRem);
2862};
2863
Calin Juravled0d48522014-11-04 16:40:20 +00002864class HDivZeroCheck : public HExpression<1> {
2865 public:
2866 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
2867 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2868 SetRawInputAt(0, value);
2869 }
2870
2871 bool CanBeMoved() const OVERRIDE { return true; }
2872
2873 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2874 UNUSED(other);
2875 return true;
2876 }
2877
2878 bool NeedsEnvironment() const OVERRIDE { return true; }
2879 bool CanThrow() const OVERRIDE { return true; }
2880
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01002881 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Calin Juravled0d48522014-11-04 16:40:20 +00002882
2883 DECLARE_INSTRUCTION(DivZeroCheck);
2884
2885 private:
2886 const uint32_t dex_pc_;
2887
2888 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
2889};
2890
Calin Juravle9aec02f2014-11-18 23:06:35 +00002891class HShl : public HBinaryOperation {
2892 public:
2893 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2894 : HBinaryOperation(result_type, left, right) {}
2895
2896 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
2897 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
2898
2899 DECLARE_INSTRUCTION(Shl);
2900
2901 private:
2902 DISALLOW_COPY_AND_ASSIGN(HShl);
2903};
2904
2905class HShr : public HBinaryOperation {
2906 public:
2907 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2908 : HBinaryOperation(result_type, left, right) {}
2909
2910 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
2911 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
2912
2913 DECLARE_INSTRUCTION(Shr);
2914
2915 private:
2916 DISALLOW_COPY_AND_ASSIGN(HShr);
2917};
2918
2919class HUShr : public HBinaryOperation {
2920 public:
2921 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2922 : HBinaryOperation(result_type, left, right) {}
2923
2924 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2925 uint32_t ux = static_cast<uint32_t>(x);
2926 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
2927 return static_cast<int32_t>(ux >> uy);
2928 }
2929
2930 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2931 uint64_t ux = static_cast<uint64_t>(x);
2932 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
2933 return static_cast<int64_t>(ux >> uy);
2934 }
2935
2936 DECLARE_INSTRUCTION(UShr);
2937
2938 private:
2939 DISALLOW_COPY_AND_ASSIGN(HUShr);
2940};
2941
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002942class HAnd : public HBinaryOperation {
2943 public:
2944 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2945 : HBinaryOperation(result_type, left, right) {}
2946
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002947 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002948
2949 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
2950 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
2951
2952 DECLARE_INSTRUCTION(And);
2953
2954 private:
2955 DISALLOW_COPY_AND_ASSIGN(HAnd);
2956};
2957
2958class HOr : public HBinaryOperation {
2959 public:
2960 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2961 : HBinaryOperation(result_type, left, right) {}
2962
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002963 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002964
2965 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
2966 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
2967
2968 DECLARE_INSTRUCTION(Or);
2969
2970 private:
2971 DISALLOW_COPY_AND_ASSIGN(HOr);
2972};
2973
2974class HXor : public HBinaryOperation {
2975 public:
2976 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2977 : HBinaryOperation(result_type, left, right) {}
2978
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002979 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002980
2981 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
2982 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
2983
2984 DECLARE_INSTRUCTION(Xor);
2985
2986 private:
2987 DISALLOW_COPY_AND_ASSIGN(HXor);
2988};
2989
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002990// The value of a parameter in this method. Its location depends on
2991// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07002992class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002993 public:
Calin Juravle10e244f2015-01-26 18:54:32 +00002994 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
2995 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002996
2997 uint8_t GetIndex() const { return index_; }
2998
Calin Juravle10e244f2015-01-26 18:54:32 +00002999 bool CanBeNull() const OVERRIDE { return !is_this_; }
3000
Calin Juravle3cd4fc82015-05-14 15:15:42 +01003001 bool IsThis() const { return is_this_; }
3002
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003003 DECLARE_INSTRUCTION(ParameterValue);
3004
3005 private:
3006 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00003007 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003008 const uint8_t index_;
3009
Calin Juravle10e244f2015-01-26 18:54:32 +00003010 // Whether or not the parameter value corresponds to 'this' argument.
3011 const bool is_this_;
3012
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01003013 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
3014};
3015
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003016class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003017 public:
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003018 explicit HNot(Primitive::Type result_type, HInstruction* input)
3019 : HUnaryOperation(result_type, input) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003020
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003021 bool CanBeMoved() const OVERRIDE { return true; }
3022 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003023 UNUSED(other);
3024 return true;
3025 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003026
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003027 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
3028 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
Roland Levillain1cc5f2512014-10-22 18:06:21 +01003029
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01003030 DECLARE_INSTRUCTION(Not);
3031
3032 private:
3033 DISALLOW_COPY_AND_ASSIGN(HNot);
3034};
3035
David Brazdil66d126e2015-04-03 16:02:44 +01003036class HBooleanNot : public HUnaryOperation {
3037 public:
3038 explicit HBooleanNot(HInstruction* input)
3039 : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
3040
3041 bool CanBeMoved() const OVERRIDE { return true; }
3042 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3043 UNUSED(other);
3044 return true;
3045 }
3046
3047 int32_t Evaluate(int32_t x) const OVERRIDE {
3048 DCHECK(IsUint<1>(x));
3049 return !x;
3050 }
3051
3052 int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
3053 LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
3054 UNREACHABLE();
3055 }
3056
3057 DECLARE_INSTRUCTION(BooleanNot);
3058
3059 private:
3060 DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
3061};
3062
Roland Levillaindff1f282014-11-05 14:15:05 +00003063class HTypeConversion : public HExpression<1> {
3064 public:
3065 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00003066 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
3067 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00003068 SetRawInputAt(0, input);
3069 DCHECK_NE(input->GetType(), result_type);
3070 }
3071
3072 HInstruction* GetInput() const { return InputAt(0); }
3073 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
3074 Primitive::Type GetResultType() const { return GetType(); }
3075
Roland Levillain624279f2014-12-04 11:54:28 +00003076 // Required by the x86 and ARM code generators when producing calls
3077 // to the runtime.
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003078 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Roland Levillain624279f2014-12-04 11:54:28 +00003079
Roland Levillaindff1f282014-11-05 14:15:05 +00003080 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00003081 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00003082
Mark Mendelle82549b2015-05-06 10:55:34 -04003083 // Try to statically evaluate the conversion and return a HConstant
3084 // containing the result. If the input cannot be converted, return nullptr.
3085 HConstant* TryStaticEvaluation() const;
3086
Roland Levillaindff1f282014-11-05 14:15:05 +00003087 DECLARE_INSTRUCTION(TypeConversion);
3088
3089 private:
Roland Levillain624279f2014-12-04 11:54:28 +00003090 const uint32_t dex_pc_;
3091
Roland Levillaindff1f282014-11-05 14:15:05 +00003092 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
3093};
3094
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00003095static constexpr uint32_t kNoRegNumber = -1;
3096
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003097class HPhi : public HInstruction {
3098 public:
3099 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003100 : HInstruction(SideEffects::None()),
3101 inputs_(arena, number_of_inputs),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003102 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003103 type_(type),
Calin Juravle10e244f2015-01-26 18:54:32 +00003104 is_live_(false),
3105 can_be_null_(true) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003106 inputs_.SetSize(number_of_inputs);
3107 }
3108
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +00003109 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
3110 static Primitive::Type ToPhiType(Primitive::Type type) {
3111 switch (type) {
3112 case Primitive::kPrimBoolean:
3113 case Primitive::kPrimByte:
3114 case Primitive::kPrimShort:
3115 case Primitive::kPrimChar:
3116 return Primitive::kPrimInt;
3117 default:
3118 return type;
3119 }
3120 }
3121
Calin Juravle10e244f2015-01-26 18:54:32 +00003122 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003123
3124 void AddInput(HInstruction* input);
David Brazdil2d7352b2015-04-20 14:52:42 +01003125 void RemoveInputAt(size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003126
Calin Juravle10e244f2015-01-26 18:54:32 +00003127 Primitive::Type GetType() const OVERRIDE { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003128 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003129
Calin Juravle10e244f2015-01-26 18:54:32 +00003130 bool CanBeNull() const OVERRIDE { return can_be_null_; }
3131 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
3132
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003133 uint32_t GetRegNumber() const { return reg_number_; }
3134
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003135 void SetDead() { is_live_ = false; }
3136 void SetLive() { is_live_ = true; }
3137 bool IsDead() const { return !is_live_; }
3138 bool IsLive() const { return is_live_; }
3139
Calin Juravlea4f88312015-04-16 12:57:19 +01003140 // Returns the next equivalent phi (starting from the current one) or null if there is none.
3141 // An equivalent phi is a phi having the same dex register and type.
3142 // It assumes that phis with the same dex register are adjacent.
3143 HPhi* GetNextEquivalentPhiWithSameType() {
3144 HInstruction* next = GetNext();
3145 while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
3146 if (next->GetType() == GetType()) {
3147 return next->AsPhi();
3148 }
3149 next = next->GetNext();
3150 }
3151 return nullptr;
3152 }
3153
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003154 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003155
David Brazdil1abb4192015-02-17 18:33:36 +00003156 protected:
3157 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
3158
3159 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
3160 inputs_.Put(index, input);
3161 }
3162
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01003163 private:
David Brazdil1abb4192015-02-17 18:33:36 +00003164 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003165 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003166 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01003167 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00003168 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003169
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01003170 DISALLOW_COPY_AND_ASSIGN(HPhi);
3171};
3172
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003173class HNullCheck : public HExpression<1> {
3174 public:
3175 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003176 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003177 SetRawInputAt(0, value);
3178 }
3179
Calin Juravle10e244f2015-01-26 18:54:32 +00003180 bool CanBeMoved() const OVERRIDE { return true; }
3181 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003182 UNUSED(other);
3183 return true;
3184 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003185
Calin Juravle10e244f2015-01-26 18:54:32 +00003186 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003187
Calin Juravle10e244f2015-01-26 18:54:32 +00003188 bool CanThrow() const OVERRIDE { return true; }
3189
3190 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003191
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003192 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003193
3194 DECLARE_INSTRUCTION(NullCheck);
3195
3196 private:
3197 const uint32_t dex_pc_;
3198
3199 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
3200};
3201
3202class FieldInfo : public ValueObject {
3203 public:
Calin Juravle52c48962014-12-16 17:02:57 +00003204 FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
3205 : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003206
3207 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003208 Primitive::Type GetFieldType() const { return field_type_; }
Calin Juravle52c48962014-12-16 17:02:57 +00003209 bool IsVolatile() const { return is_volatile_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003210
3211 private:
3212 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01003213 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00003214 const bool is_volatile_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003215};
3216
3217class HInstanceFieldGet : public HExpression<1> {
3218 public:
3219 HInstanceFieldGet(HInstruction* value,
3220 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003221 MemberOffset field_offset,
3222 bool is_volatile)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003223 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00003224 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003225 SetRawInputAt(0, value);
3226 }
3227
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003228 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003229
3230 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3231 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
3232 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003233 }
3234
Calin Juravle641547a2015-04-21 22:08:51 +01003235 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3236 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003237 }
3238
3239 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01003240 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3241 }
3242
Calin Juravle52c48962014-12-16 17:02:57 +00003243 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003244 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003245 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003246 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003247
3248 DECLARE_INSTRUCTION(InstanceFieldGet);
3249
3250 private:
3251 const FieldInfo field_info_;
3252
3253 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
3254};
3255
3256class HInstanceFieldSet : public HTemplateInstruction<2> {
3257 public:
3258 HInstanceFieldSet(HInstruction* object,
3259 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01003260 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003261 MemberOffset field_offset,
3262 bool is_volatile)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003263 : HTemplateInstruction(SideEffects::ChangesSomething()),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003264 field_info_(field_offset, field_type, is_volatile),
3265 value_can_be_null_(true) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003266 SetRawInputAt(0, object);
3267 SetRawInputAt(1, value);
3268 }
3269
Calin Juravle641547a2015-04-21 22:08:51 +01003270 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3271 return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
Calin Juravle77520bc2015-01-12 18:45:46 +00003272 }
3273
Calin Juravle52c48962014-12-16 17:02:57 +00003274 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003275 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003276 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003277 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003278 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003279 bool GetValueCanBeNull() const { return value_can_be_null_; }
3280 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003281
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003282 DECLARE_INSTRUCTION(InstanceFieldSet);
3283
3284 private:
3285 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003286 bool value_can_be_null_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003287
3288 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
3289};
3290
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003291class HArrayGet : public HExpression<2> {
3292 public:
3293 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003294 : HExpression(type, SideEffects::DependsOnSomething()) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003295 SetRawInputAt(0, array);
3296 SetRawInputAt(1, index);
3297 }
3298
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003299 bool CanBeMoved() const OVERRIDE { return true; }
3300 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003301 UNUSED(other);
3302 return true;
3303 }
Calin Juravle641547a2015-04-21 22:08:51 +01003304 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3305 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003306 // TODO: We can be smarter here.
3307 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
3308 // which generates the implicit null check. There are cases when these can be removed
3309 // to produce better code. If we ever add optimizations to do so we should allow an
3310 // implicit check here (as long as the address falls in the first page).
3311 return false;
3312 }
3313
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003314 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003315
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003316 HInstruction* GetArray() const { return InputAt(0); }
3317 HInstruction* GetIndex() const { return InputAt(1); }
3318
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003319 DECLARE_INSTRUCTION(ArrayGet);
3320
3321 private:
3322 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
3323};
3324
3325class HArraySet : public HTemplateInstruction<3> {
3326 public:
3327 HArraySet(HInstruction* array,
3328 HInstruction* index,
3329 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003330 Primitive::Type expected_component_type,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003331 uint32_t dex_pc)
3332 : HTemplateInstruction(SideEffects::ChangesSomething()),
3333 dex_pc_(dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003334 expected_component_type_(expected_component_type),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003335 needs_type_check_(value->GetType() == Primitive::kPrimNot),
3336 value_can_be_null_(true) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003337 SetRawInputAt(0, array);
3338 SetRawInputAt(1, index);
3339 SetRawInputAt(2, value);
3340 }
3341
Calin Juravle77520bc2015-01-12 18:45:46 +00003342 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003343 // We currently always call a runtime method to catch array store
3344 // exceptions.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003345 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003346 }
3347
Calin Juravle641547a2015-04-21 22:08:51 +01003348 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3349 UNUSED(obj);
Calin Juravle77520bc2015-01-12 18:45:46 +00003350 // TODO: Same as for ArrayGet.
3351 return false;
3352 }
3353
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003354 void ClearNeedsTypeCheck() {
3355 needs_type_check_ = false;
3356 }
3357
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003358 void ClearValueCanBeNull() {
3359 value_can_be_null_ = false;
3360 }
3361
3362 bool GetValueCanBeNull() const { return value_can_be_null_; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003363 bool NeedsTypeCheck() const { return needs_type_check_; }
3364
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003365 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003366
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003367 HInstruction* GetArray() const { return InputAt(0); }
3368 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003369 HInstruction* GetValue() const { return InputAt(2); }
3370
3371 Primitive::Type GetComponentType() const {
3372 // The Dex format does not type floating point index operations. Since the
3373 // `expected_component_type_` is set during building and can therefore not
3374 // be correct, we also check what is the value type. If it is a floating
3375 // point type, we must use that type.
3376 Primitive::Type value_type = GetValue()->GetType();
3377 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
3378 ? value_type
3379 : expected_component_type_;
3380 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01003381
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003382 DECLARE_INSTRUCTION(ArraySet);
3383
3384 private:
3385 const uint32_t dex_pc_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01003386 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003387 bool needs_type_check_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003388 bool value_can_be_null_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003389
3390 DISALLOW_COPY_AND_ASSIGN(HArraySet);
3391};
3392
3393class HArrayLength : public HExpression<1> {
3394 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003395 explicit HArrayLength(HInstruction* array)
3396 : HExpression(Primitive::kPrimInt, SideEffects::None()) {
3397 // Note that arrays do not change length, so the instruction does not
3398 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003399 SetRawInputAt(0, array);
3400 }
3401
Calin Juravle77520bc2015-01-12 18:45:46 +00003402 bool CanBeMoved() const OVERRIDE { return true; }
3403 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003404 UNUSED(other);
3405 return true;
3406 }
Calin Juravle641547a2015-04-21 22:08:51 +01003407 bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3408 return obj == InputAt(0);
3409 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003410
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003411 DECLARE_INSTRUCTION(ArrayLength);
3412
3413 private:
3414 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
3415};
3416
3417class HBoundsCheck : public HExpression<2> {
3418 public:
3419 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003420 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003421 DCHECK(index->GetType() == Primitive::kPrimInt);
3422 SetRawInputAt(0, index);
3423 SetRawInputAt(1, length);
3424 }
3425
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003426 bool CanBeMoved() const OVERRIDE { return true; }
3427 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003428 UNUSED(other);
3429 return true;
3430 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003431
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003432 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003433
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003434 bool CanThrow() const OVERRIDE { return true; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01003435
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003436 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01003437
3438 DECLARE_INSTRUCTION(BoundsCheck);
3439
3440 private:
3441 const uint32_t dex_pc_;
3442
3443 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
3444};
3445
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003446/**
3447 * Some DEX instructions are folded into multiple HInstructions that need
3448 * to stay live until the last HInstruction. This class
3449 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00003450 * HInstruction stays live. `index` represents the stack location index of the
3451 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003452 */
3453class HTemporary : public HTemplateInstruction<0> {
3454 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003455 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003456
3457 size_t GetIndex() const { return index_; }
3458
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00003459 Primitive::Type GetType() const OVERRIDE {
3460 // The previous instruction is the one that will be stored in the temporary location.
3461 DCHECK(GetPrevious() != nullptr);
3462 return GetPrevious()->GetType();
3463 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00003464
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003465 DECLARE_INSTRUCTION(Temporary);
3466
3467 private:
3468 const size_t index_;
3469
3470 DISALLOW_COPY_AND_ASSIGN(HTemporary);
3471};
3472
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003473class HSuspendCheck : public HTemplateInstruction<0> {
3474 public:
3475 explicit HSuspendCheck(uint32_t dex_pc)
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003476 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003477
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003478 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003479 return true;
3480 }
3481
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003482 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003483 void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
3484 SlowPathCode* GetSlowPath() const { return slow_path_; }
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003485
3486 DECLARE_INSTRUCTION(SuspendCheck);
3487
3488 private:
3489 const uint32_t dex_pc_;
3490
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01003491 // Only used for code generation, in order to share the same slow path between back edges
3492 // of a same loop.
3493 SlowPathCode* slow_path_;
3494
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003495 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
3496};
3497
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003498/**
3499 * Instruction to load a Class object.
3500 */
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003501class HLoadClass : public HExpression<1> {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003502 public:
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003503 HLoadClass(HCurrentMethod* current_method,
3504 uint16_t type_index,
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003505 const DexFile& dex_file,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003506 bool is_referrers_class,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003507 uint32_t dex_pc)
3508 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3509 type_index_(type_index),
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003510 dex_file_(dex_file),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003511 is_referrers_class_(is_referrers_class),
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003512 dex_pc_(dex_pc),
Calin Juravleb1498f62015-02-16 13:13:29 +00003513 generate_clinit_check_(false),
Nicolas Geoffray76b1e172015-05-27 17:18:33 +01003514 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
3515 SetRawInputAt(0, current_method);
3516 }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003517
3518 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003519
3520 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3521 return other->AsLoadClass()->type_index_ == type_index_;
3522 }
3523
3524 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
3525
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003526 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003527 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003528 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003529
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003530 bool NeedsEnvironment() const OVERRIDE {
3531 // Will call runtime and load the class if the class is not loaded yet.
3532 // TODO: finer grain decision.
3533 return !is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003534 }
3535
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003536 bool MustGenerateClinitCheck() const {
3537 return generate_clinit_check_;
3538 }
3539
Calin Juravle0ba218d2015-05-19 18:46:01 +01003540 void SetMustGenerateClinitCheck(bool generate_clinit_check) {
3541 generate_clinit_check_ = generate_clinit_check;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003542 }
3543
3544 bool CanCallRuntime() const {
3545 return MustGenerateClinitCheck() || !is_referrers_class_;
3546 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003547
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003548 bool CanThrow() const OVERRIDE {
3549 // May call runtime and and therefore can throw.
3550 // TODO: finer grain decision.
3551 return !is_referrers_class_;
3552 }
3553
Calin Juravleacf735c2015-02-12 15:25:22 +00003554 ReferenceTypeInfo GetLoadedClassRTI() {
3555 return loaded_class_rti_;
3556 }
3557
3558 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
3559 // Make sure we only set exact types (the loaded class should never be merged).
3560 DCHECK(rti.IsExact());
3561 loaded_class_rti_ = rti;
3562 }
3563
3564 bool IsResolved() {
3565 return loaded_class_rti_.IsExact();
3566 }
3567
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003568 const DexFile& GetDexFile() { return dex_file_; }
3569
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003570 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
3571
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003572 DECLARE_INSTRUCTION(LoadClass);
3573
3574 private:
3575 const uint16_t type_index_;
Nicolas Geoffrayd5111bf2015-05-22 15:37:09 +01003576 const DexFile& dex_file_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003577 const bool is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003578 const uint32_t dex_pc_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003579 // Whether this instruction must generate the initialization check.
3580 // Used for code generation.
3581 bool generate_clinit_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003582
Calin Juravleacf735c2015-02-12 15:25:22 +00003583 ReferenceTypeInfo loaded_class_rti_;
3584
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003585 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
3586};
3587
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003588class HLoadString : public HExpression<1> {
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003589 public:
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003590 HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003591 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3592 string_index_(string_index),
Nicolas Geoffrayfbdaa302015-05-29 12:06:56 +01003593 dex_pc_(dex_pc) {
3594 SetRawInputAt(0, current_method);
3595 }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003596
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003597 bool CanBeMoved() const OVERRIDE { return true; }
3598
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003599 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3600 return other->AsLoadString()->string_index_ == string_index_;
3601 }
3602
3603 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
3604
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003605 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003606 uint32_t GetStringIndex() const { return string_index_; }
3607
3608 // TODO: Can we deopt or debug when we resolve a string?
3609 bool NeedsEnvironment() const OVERRIDE { return false; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003610 bool NeedsDexCache() const OVERRIDE { return true; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003611
3612 DECLARE_INSTRUCTION(LoadString);
3613
3614 private:
3615 const uint32_t string_index_;
3616 const uint32_t dex_pc_;
3617
3618 DISALLOW_COPY_AND_ASSIGN(HLoadString);
3619};
3620
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003621/**
3622 * Performs an initialization check on its Class object input.
3623 */
3624class HClinitCheck : public HExpression<1> {
3625 public:
3626 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
Nicolas Geoffraya0466e12015-03-27 15:00:40 +00003627 : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003628 dex_pc_(dex_pc) {
3629 SetRawInputAt(0, constant);
3630 }
3631
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003632 bool CanBeMoved() const OVERRIDE { return true; }
3633 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3634 UNUSED(other);
3635 return true;
3636 }
3637
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003638 bool NeedsEnvironment() const OVERRIDE {
3639 // May call runtime to initialize the class.
3640 return true;
3641 }
3642
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003643 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003644
3645 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
3646
3647 DECLARE_INSTRUCTION(ClinitCheck);
3648
3649 private:
3650 const uint32_t dex_pc_;
3651
3652 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
3653};
3654
3655class HStaticFieldGet : public HExpression<1> {
3656 public:
3657 HStaticFieldGet(HInstruction* cls,
3658 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003659 MemberOffset field_offset,
3660 bool is_volatile)
Nicolas Geoffray2af23072015-04-30 11:15:40 +00003661 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00003662 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003663 SetRawInputAt(0, cls);
3664 }
3665
Calin Juravle52c48962014-12-16 17:02:57 +00003666
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003667 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003668
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003669 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00003670 HStaticFieldGet* other_get = other->AsStaticFieldGet();
3671 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003672 }
3673
3674 size_t ComputeHashCode() const OVERRIDE {
3675 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3676 }
3677
Calin Juravle52c48962014-12-16 17:02:57 +00003678 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003679 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3680 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003681 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003682
3683 DECLARE_INSTRUCTION(StaticFieldGet);
3684
3685 private:
3686 const FieldInfo field_info_;
3687
3688 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
3689};
3690
3691class HStaticFieldSet : public HTemplateInstruction<2> {
3692 public:
3693 HStaticFieldSet(HInstruction* cls,
3694 HInstruction* value,
3695 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003696 MemberOffset field_offset,
3697 bool is_volatile)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003698 : HTemplateInstruction(SideEffects::ChangesSomething()),
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003699 field_info_(field_offset, field_type, is_volatile),
3700 value_can_be_null_(true) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003701 SetRawInputAt(0, cls);
3702 SetRawInputAt(1, value);
3703 }
3704
Calin Juravle52c48962014-12-16 17:02:57 +00003705 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003706 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3707 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003708 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003709
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003710 HInstruction* GetValue() const { return InputAt(1); }
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003711 bool GetValueCanBeNull() const { return value_can_be_null_; }
3712 void ClearValueCanBeNull() { value_can_be_null_ = false; }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003713
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003714 DECLARE_INSTRUCTION(StaticFieldSet);
3715
3716 private:
3717 const FieldInfo field_info_;
Nicolas Geoffray07276db2015-05-18 14:22:09 +01003718 bool value_can_be_null_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003719
3720 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
3721};
3722
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003723// Implement the move-exception DEX instruction.
3724class HLoadException : public HExpression<0> {
3725 public:
3726 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
3727
3728 DECLARE_INSTRUCTION(LoadException);
3729
3730 private:
3731 DISALLOW_COPY_AND_ASSIGN(HLoadException);
3732};
3733
3734class HThrow : public HTemplateInstruction<1> {
3735 public:
3736 HThrow(HInstruction* exception, uint32_t dex_pc)
3737 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
3738 SetRawInputAt(0, exception);
3739 }
3740
3741 bool IsControlFlow() const OVERRIDE { return true; }
3742
3743 bool NeedsEnvironment() const OVERRIDE { return true; }
3744
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003745 bool CanThrow() const OVERRIDE { return true; }
3746
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003747 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003748
3749 DECLARE_INSTRUCTION(Throw);
3750
3751 private:
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003752 const uint32_t dex_pc_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003753
3754 DISALLOW_COPY_AND_ASSIGN(HThrow);
3755};
3756
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003757class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003758 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003759 HInstanceOf(HInstruction* object,
3760 HLoadClass* constant,
3761 bool class_is_final,
3762 uint32_t dex_pc)
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003763 : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
3764 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003765 must_do_null_check_(true),
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003766 dex_pc_(dex_pc) {
3767 SetRawInputAt(0, object);
3768 SetRawInputAt(1, constant);
3769 }
3770
3771 bool CanBeMoved() const OVERRIDE { return true; }
3772
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003773 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003774 return true;
3775 }
3776
3777 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003778 return false;
3779 }
3780
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003781 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003782
3783 bool IsClassFinal() const { return class_is_final_; }
3784
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003785 // Used only in code generation.
3786 bool MustDoNullCheck() const { return must_do_null_check_; }
3787 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3788
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003789 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003790
3791 private:
3792 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003793 bool must_do_null_check_;
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003794 const uint32_t dex_pc_;
3795
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003796 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
3797};
3798
Calin Juravleb1498f62015-02-16 13:13:29 +00003799class HBoundType : public HExpression<1> {
3800 public:
3801 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type)
3802 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3803 bound_type_(bound_type) {
Calin Juravle61d544b2015-02-23 16:46:57 +00003804 DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
Calin Juravleb1498f62015-02-16 13:13:29 +00003805 SetRawInputAt(0, input);
3806 }
3807
3808 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; }
3809
3810 bool CanBeNull() const OVERRIDE {
3811 // `null instanceof ClassX` always return false so we can't be null.
3812 return false;
3813 }
3814
3815 DECLARE_INSTRUCTION(BoundType);
3816
3817 private:
3818 // Encodes the most upper class that this instruction can have. In other words
3819 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()).
3820 // It is used to bound the type in cases like `if (x instanceof ClassX) {}`
3821 const ReferenceTypeInfo bound_type_;
3822
3823 DISALLOW_COPY_AND_ASSIGN(HBoundType);
3824};
3825
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003826class HCheckCast : public HTemplateInstruction<2> {
3827 public:
3828 HCheckCast(HInstruction* object,
3829 HLoadClass* constant,
3830 bool class_is_final,
3831 uint32_t dex_pc)
3832 : HTemplateInstruction(SideEffects::None()),
3833 class_is_final_(class_is_final),
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003834 must_do_null_check_(true),
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003835 dex_pc_(dex_pc) {
3836 SetRawInputAt(0, object);
3837 SetRawInputAt(1, constant);
3838 }
3839
3840 bool CanBeMoved() const OVERRIDE { return true; }
3841
3842 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3843 return true;
3844 }
3845
3846 bool NeedsEnvironment() const OVERRIDE {
3847 // Instruction may throw a CheckCastError.
3848 return true;
3849 }
3850
3851 bool CanThrow() const OVERRIDE { return true; }
3852
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003853 bool MustDoNullCheck() const { return must_do_null_check_; }
3854 void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3855
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003856 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003857
3858 bool IsClassFinal() const { return class_is_final_; }
3859
3860 DECLARE_INSTRUCTION(CheckCast);
3861
3862 private:
3863 const bool class_is_final_;
Guillaume "Vermeille" Sanchezaf888352015-04-20 14:41:30 +01003864 bool must_do_null_check_;
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003865 const uint32_t dex_pc_;
3866
3867 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003868};
3869
Calin Juravle27df7582015-04-17 19:12:31 +01003870class HMemoryBarrier : public HTemplateInstruction<0> {
3871 public:
3872 explicit HMemoryBarrier(MemBarrierKind barrier_kind)
3873 : HTemplateInstruction(SideEffects::None()),
3874 barrier_kind_(barrier_kind) {}
3875
3876 MemBarrierKind GetBarrierKind() { return barrier_kind_; }
3877
3878 DECLARE_INSTRUCTION(MemoryBarrier);
3879
3880 private:
3881 const MemBarrierKind barrier_kind_;
3882
3883 DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier);
3884};
3885
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003886class HMonitorOperation : public HTemplateInstruction<1> {
3887 public:
3888 enum OperationKind {
3889 kEnter,
3890 kExit,
3891 };
3892
3893 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
3894 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
3895 SetRawInputAt(0, object);
3896 }
3897
3898 // Instruction may throw a Java exception, so we need an environment.
3899 bool NeedsEnvironment() const OVERRIDE { return true; }
3900 bool CanThrow() const OVERRIDE { return true; }
3901
Nicolas Geoffray0a23d742015-05-07 11:57:35 +01003902 uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003903
3904 bool IsEnter() const { return kind_ == kEnter; }
3905
3906 DECLARE_INSTRUCTION(MonitorOperation);
3907
Calin Juravle52c48962014-12-16 17:02:57 +00003908 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003909 const OperationKind kind_;
3910 const uint32_t dex_pc_;
3911
3912 private:
3913 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
3914};
3915
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003916class MoveOperands : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003917 public:
Nicolas Geoffray90218252015-04-15 11:56:51 +01003918 MoveOperands(Location source,
3919 Location destination,
3920 Primitive::Type type,
3921 HInstruction* instruction)
3922 : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003923
3924 Location GetSource() const { return source_; }
3925 Location GetDestination() const { return destination_; }
3926
3927 void SetSource(Location value) { source_ = value; }
3928 void SetDestination(Location value) { destination_ = value; }
3929
3930 // The parallel move resolver marks moves as "in-progress" by clearing the
3931 // destination (but not the source).
3932 Location MarkPending() {
3933 DCHECK(!IsPending());
3934 Location dest = destination_;
3935 destination_ = Location::NoLocation();
3936 return dest;
3937 }
3938
3939 void ClearPending(Location dest) {
3940 DCHECK(IsPending());
3941 destination_ = dest;
3942 }
3943
3944 bool IsPending() const {
3945 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3946 return destination_.IsInvalid() && !source_.IsInvalid();
3947 }
3948
3949 // True if this blocks a move from the given location.
3950 bool Blocks(Location loc) const {
Zheng Xuad4450e2015-04-17 18:48:56 +08003951 return !IsEliminated() && source_.OverlapsWith(loc);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003952 }
3953
3954 // A move is redundant if it's been eliminated, if its source and
3955 // destination are the same, or if its destination is unneeded.
3956 bool IsRedundant() const {
3957 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
3958 }
3959
3960 // We clear both operands to indicate move that's been eliminated.
3961 void Eliminate() {
3962 source_ = destination_ = Location::NoLocation();
3963 }
3964
3965 bool IsEliminated() const {
3966 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3967 return source_.IsInvalid();
3968 }
3969
Nicolas Geoffray90218252015-04-15 11:56:51 +01003970 bool Is64BitMove() const {
3971 return Primitive::Is64BitType(type_);
3972 }
3973
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003974 HInstruction* GetInstruction() const { return instruction_; }
3975
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003976 private:
3977 Location source_;
3978 Location destination_;
Nicolas Geoffray90218252015-04-15 11:56:51 +01003979 // The type this move is for.
3980 Primitive::Type type_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003981 // The instruction this move is assocatied with. Null when this move is
3982 // for moving an input in the expected locations of user (including a phi user).
3983 // This is only used in debug mode, to ensure we do not connect interval siblings
3984 // in the same parallel move.
3985 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003986};
3987
3988static constexpr size_t kDefaultNumberOfMoves = 4;
3989
3990class HParallelMove : public HTemplateInstruction<0> {
3991 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003992 explicit HParallelMove(ArenaAllocator* arena)
3993 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003994
Nicolas Geoffray90218252015-04-15 11:56:51 +01003995 void AddMove(Location source,
3996 Location destination,
3997 Primitive::Type type,
3998 HInstruction* instruction) {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003999 DCHECK(source.IsValid());
4000 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004001 if (kIsDebugBuild) {
4002 if (instruction != nullptr) {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004003 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00004004 if (moves_.Get(i).GetInstruction() == instruction) {
4005 // Special case the situation where the move is for the spill slot
4006 // of the instruction.
4007 if ((GetPrevious() == instruction)
4008 || ((GetPrevious() == nullptr)
4009 && instruction->IsPhi()
4010 && instruction->GetBlock() == GetBlock())) {
4011 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind())
4012 << "Doing parallel moves for the same instruction.";
4013 } else {
4014 DCHECK(false) << "Doing parallel moves for the same instruction.";
4015 }
4016 }
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00004017 }
4018 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004019 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Zheng Xuad4450e2015-04-17 18:48:56 +08004020 DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination()))
Guillaume "Vermeille" Sanchez8909baf2015-04-23 21:35:11 +01004021 << "Overlapped destination for two moves in a parallel move: "
4022 << moves_.Get(i).GetSource() << " ==> " << moves_.Get(i).GetDestination() << " and "
4023 << source << " ==> " << destination;
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00004024 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01004025 }
Nicolas Geoffray90218252015-04-15 11:56:51 +01004026 moves_.Add(MoveOperands(source, destination, type, instruction));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004027 }
4028
4029 MoveOperands* MoveOperandsAt(size_t index) const {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004030 return moves_.GetRawStorage() + index;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004031 }
4032
4033 size_t NumMoves() const { return moves_.Size(); }
4034
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01004035 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004036
4037 private:
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00004038 GrowableArray<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01004039
4040 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
4041};
4042
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004043class HGraphVisitor : public ValueObject {
4044 public:
Dave Allison20dfc792014-06-16 20:44:29 -07004045 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
4046 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004047
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07004048 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004049 virtual void VisitBasicBlock(HBasicBlock* block);
4050
Roland Levillain633021e2014-10-01 14:12:25 +01004051 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004052 void VisitInsertionOrder();
4053
Roland Levillain633021e2014-10-01 14:12:25 +01004054 // Visit the graph following dominator tree reverse post-order.
4055 void VisitReversePostOrder();
4056
Nicolas Geoffray787c3072014-03-17 10:20:19 +00004057 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00004058
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004059 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004060#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004061 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
4062
4063 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4064
4065#undef DECLARE_VISIT_INSTRUCTION
4066
4067 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07004068 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004069
4070 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
4071};
4072
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004073class HGraphDelegateVisitor : public HGraphVisitor {
4074 public:
4075 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
4076 virtual ~HGraphDelegateVisitor() {}
4077
4078 // Visit functions that delegate to to super class.
4079#define DECLARE_VISIT_INSTRUCTION(name, super) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00004080 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
Nicolas Geoffray360231a2014-10-08 21:07:48 +01004081
4082 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
4083
4084#undef DECLARE_VISIT_INSTRUCTION
4085
4086 private:
4087 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
4088};
4089
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004090class HInsertionOrderIterator : public ValueObject {
4091 public:
4092 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
4093
4094 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
4095 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
4096 void Advance() { ++index_; }
4097
4098 private:
4099 const HGraph& graph_;
4100 size_t index_;
4101
4102 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
4103};
4104
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004105class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004106 public:
David Brazdil10f56cb2015-03-24 18:49:14 +00004107 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
4108 // Check that reverse post order of the graph has been built.
4109 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4110 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004111
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004112 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
4113 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004114 void Advance() { ++index_; }
4115
4116 private:
4117 const HGraph& graph_;
4118 size_t index_;
4119
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004120 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004121};
4122
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004123class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004124 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004125 explicit HPostOrderIterator(const HGraph& graph)
David Brazdil10f56cb2015-03-24 18:49:14 +00004126 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {
4127 // Check that reverse post order of the graph has been built.
4128 DCHECK(!graph.GetReversePostOrder().IsEmpty());
4129 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004130
4131 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004132 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004133 void Advance() { --index_; }
4134
4135 private:
4136 const HGraph& graph_;
4137 size_t index_;
4138
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01004139 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01004140};
4141
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01004142class HLinearPostOrderIterator : public ValueObject {
4143 public:
4144 explicit HLinearPostOrderIterator(const HGraph& graph)
4145 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {}
4146
4147 bool Done() const { return index_ == 0; }
4148
4149 HBasicBlock* Current() const { return order_.Get(index_ -1); }
4150
4151 void Advance() {
4152 --index_;
4153 DCHECK_GE(index_, 0U);
4154 }
4155
4156 private:
4157 const GrowableArray<HBasicBlock*>& order_;
4158 size_t index_;
4159
4160 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
4161};
4162
4163class HLinearOrderIterator : public ValueObject {
4164 public:
4165 explicit HLinearOrderIterator(const HGraph& graph)
4166 : order_(graph.GetLinearOrder()), index_(0) {}
4167
4168 bool Done() const { return index_ == order_.Size(); }
4169 HBasicBlock* Current() const { return order_.Get(index_); }
4170 void Advance() { ++index_; }
4171
4172 private:
4173 const GrowableArray<HBasicBlock*>& order_;
4174 size_t index_;
4175
4176 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
4177};
4178
Nicolas Geoffray82091da2015-01-26 10:02:45 +00004179// Iterator over the blocks that art part of the loop. Includes blocks part
4180// of an inner loop. The order in which the blocks are iterated is on their
4181// block id.
4182class HBlocksInLoopIterator : public ValueObject {
4183 public:
4184 explicit HBlocksInLoopIterator(const HLoopInformation& info)
4185 : blocks_in_loop_(info.GetBlocks()),
4186 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
4187 index_(0) {
4188 if (!blocks_in_loop_.IsBitSet(index_)) {
4189 Advance();
4190 }
4191 }
4192
4193 bool Done() const { return index_ == blocks_.Size(); }
4194 HBasicBlock* Current() const { return blocks_.Get(index_); }
4195 void Advance() {
4196 ++index_;
4197 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4198 if (blocks_in_loop_.IsBitSet(index_)) {
4199 break;
4200 }
4201 }
4202 }
4203
4204 private:
4205 const BitVector& blocks_in_loop_;
4206 const GrowableArray<HBasicBlock*>& blocks_;
4207 size_t index_;
4208
4209 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
4210};
4211
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00004212inline int64_t Int64FromConstant(HConstant* constant) {
4213 DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
4214 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
4215 : constant->AsLongConstant()->GetValue();
4216}
4217
Nicolas Geoffray818f2102014-02-18 16:43:35 +00004218} // namespace art
4219
4220#endif // ART_COMPILER_OPTIMIZING_NODES_H_