blob: b406cbb8a4b57c3278722e697a78b9fd366e23a6 [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"
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +000022#include "entrypoints/quick/quick_entrypoints_enum.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000023#include "handle.h"
24#include "handle_scope.h"
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000025#include "invoke_type.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010026#include "locations.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000027#include "mirror/class.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010028#include "offsets.h"
Ian Rogerse63db272014-07-15 15:36:11 -070029#include "primitive.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000030#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000031#include "utils/growable_array.h"
32
33namespace art {
34
David Brazdil1abb4192015-02-17 18:33:36 +000035class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000036class HBasicBlock;
David Brazdil8d5b8b22015-03-24 10:51:52 +000037class HDoubleConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010038class HEnvironment;
David Brazdil8d5b8b22015-03-24 10:51:52 +000039class HFloatConstant;
40class HGraphVisitor;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000041class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000042class HIntConstant;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000043class HInvoke;
David Brazdil8d5b8b22015-03-24 10:51:52 +000044class HLongConstant;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +000045class HNullConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010046class HPhi;
Nicolas Geoffray3c049742014-09-24 18:10:46 +010047class HSuspendCheck;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010048class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000049class LocationSummary;
David Brazdil8d5b8b22015-03-24 10:51:52 +000050class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000051
52static const int kDefaultNumberOfBlocks = 8;
53static const int kDefaultNumberOfSuccessors = 2;
54static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010055static const int kDefaultNumberOfDominatedBlocks = 1;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000056static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000057
Calin Juravle9aec02f2014-11-18 23:06:35 +000058static constexpr uint32_t kMaxIntShiftValue = 0x1f;
59static constexpr uint64_t kMaxLongShiftValue = 0x3f;
60
Dave Allison20dfc792014-06-16 20:44:29 -070061enum IfCondition {
62 kCondEQ,
63 kCondNE,
64 kCondLT,
65 kCondLE,
66 kCondGT,
67 kCondGE,
68};
69
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010070class HInstructionList {
71 public:
72 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
73
74 void AddInstruction(HInstruction* instruction);
75 void RemoveInstruction(HInstruction* instruction);
76
Roland Levillain6b469232014-09-25 10:10:38 +010077 // Return true if this list contains `instruction`.
78 bool Contains(HInstruction* instruction) const;
79
Roland Levillainccc07a92014-09-16 14:48:16 +010080 // Return true if `instruction1` is found before `instruction2` in
81 // this instruction list and false otherwise. Abort if none
82 // of these instructions is found.
83 bool FoundBefore(const HInstruction* instruction1,
84 const HInstruction* instruction2) const;
85
Nicolas Geoffray276d9da2015-02-02 18:24:11 +000086 bool IsEmpty() const { return first_instruction_ == nullptr; }
87 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
88
89 // Update the block of all instructions to be `block`.
90 void SetBlockOfInstructions(HBasicBlock* block) const;
91
92 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
93 void Add(const HInstructionList& instruction_list);
94
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010095 private:
96 HInstruction* first_instruction_;
97 HInstruction* last_instruction_;
98
99 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000100 friend class HGraph;
101 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100102 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100103 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100104
105 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
106};
107
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000108// Control-flow graph of a method. Contains a list of basic blocks.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700109class HGraph : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000110 public:
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000111 HGraph(ArenaAllocator* arena, bool debuggable = false, int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000112 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100114 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100115 linear_order_(arena, kDefaultNumberOfBlocks),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700116 entry_block_(nullptr),
117 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100118 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100119 number_of_vregs_(0),
120 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000121 temporaries_vreg_slots_(0),
Mingyao Yange4335eb2015-03-02 15:14:13 -0800122 has_array_accesses_(false),
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000123 debuggable_(debuggable),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000124 current_instruction_id_(start_instruction_id),
125 cached_null_constant_(nullptr),
126 cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
127 cached_long_constants_(std::less<int64_t>(), arena->Adapter()) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000128
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000129 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100130 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Roland Levillain93445682014-10-06 19:24:02 +0100131 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000132
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000133 HBasicBlock* GetEntryBlock() const { return entry_block_; }
134 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000135
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000136 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
137 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000138
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000139 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100140
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000141 // Try building the SSA form of this graph, with dominance computation and loop
142 // recognition. Returns whether it was successful in doing all these steps.
143 bool TryBuildingSsa() {
144 BuildDominatorTree();
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000145 // The SSA builder requires loops to all be natural. Specifically, the dead phi
146 // elimination phase checks the consistency of the graph when doing a post-order
147 // visit for eliminating dead phis: a dead phi can only have loop header phi
148 // users remaining when being visited.
149 if (!AnalyzeNaturalLoops()) return false;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000150 TransformToSsa();
Nicolas Geoffrayd3350832015-03-12 11:16:23 +0000151 return true;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000152 }
153
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000154 void BuildDominatorTree();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000155 void TransformToSsa();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100156 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000157
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000158 // Analyze all natural loops in this graph. Returns false if one
159 // loop is not natural, that is the header does not dominate the
160 // back edge.
161 bool AnalyzeNaturalLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100162
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000163 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
164 void InlineInto(HGraph* outer_graph, HInvoke* invoke);
165
David Brazdil46e2a392015-03-16 17:31:52 +0000166 void MergeEmptyBranches(HBasicBlock* start_block, HBasicBlock* end_block);
167
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100168 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
169 void SimplifyLoop(HBasicBlock* header);
170
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000171 int32_t GetNextInstructionId() {
172 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000173 return current_instruction_id_++;
174 }
175
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000176 int32_t GetCurrentInstructionId() const {
177 return current_instruction_id_;
178 }
179
180 void SetCurrentInstructionId(int32_t id) {
181 current_instruction_id_ = id;
182 }
183
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100184 uint16_t GetMaximumNumberOfOutVRegs() const {
185 return maximum_number_of_out_vregs_;
186 }
187
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000188 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
189 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100190 }
191
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000192 void UpdateTemporariesVRegSlots(size_t slots) {
193 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100194 }
195
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000196 size_t GetTemporariesVRegSlots() const {
197 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100198 }
199
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100200 void SetNumberOfVRegs(uint16_t number_of_vregs) {
201 number_of_vregs_ = number_of_vregs;
202 }
203
204 uint16_t GetNumberOfVRegs() const {
205 return number_of_vregs_;
206 }
207
208 void SetNumberOfInVRegs(uint16_t value) {
209 number_of_in_vregs_ = value;
210 }
211
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100212 uint16_t GetNumberOfLocalVRegs() const {
213 return number_of_vregs_ - number_of_in_vregs_;
214 }
215
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100216 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
217 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100218 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100219
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100220 const GrowableArray<HBasicBlock*>& GetLinearOrder() const {
221 return linear_order_;
222 }
223
Mingyao Yange4335eb2015-03-02 15:14:13 -0800224 bool HasArrayAccesses() const {
225 return has_array_accesses_;
226 }
227
228 void SetHasArrayAccesses(bool value) {
229 has_array_accesses_ = value;
230 }
231
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000232 bool IsDebuggable() const { return debuggable_; }
233
David Brazdil8d5b8b22015-03-24 10:51:52 +0000234 // Returns a constant of the given type and value. If it does not exist
235 // already, it is created and inserted into the graph. Only integral types
236 // are currently supported.
237 HConstant* GetConstant(Primitive::Type type, int64_t value);
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000238 HNullConstant* GetNullConstant();
David Brazdil8d5b8b22015-03-24 10:51:52 +0000239 HIntConstant* GetIntConstant(int32_t value) {
240 return CreateConstant(value, &cached_int_constants_);
241 }
242 HLongConstant* GetLongConstant(int64_t value) {
243 return CreateConstant(value, &cached_long_constants_);
244 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000245
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000246 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000247 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
248 void VisitBlockForDominatorTree(HBasicBlock* block,
249 HBasicBlock* predecessor,
250 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100251 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000252 void VisitBlockForBackEdges(HBasicBlock* block,
253 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100254 ArenaBitVector* visiting);
Roland Levillainfc600dc2014-12-02 17:16:31 +0000255 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000256 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
257
David Brazdil8d5b8b22015-03-24 10:51:52 +0000258 template <class InstType, typename ValueType>
259 InstType* CreateConstant(ValueType value, ArenaSafeMap<ValueType, InstType*>* cache);
260 void InsertConstant(HConstant* instruction);
261
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000262 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000263
264 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000265 GrowableArray<HBasicBlock*> blocks_;
266
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100267 // List of blocks to perform a reverse post order tree traversal.
268 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000269
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100270 // List of blocks to perform a linear order tree traversal.
271 GrowableArray<HBasicBlock*> linear_order_;
272
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000273 HBasicBlock* entry_block_;
274 HBasicBlock* exit_block_;
275
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100276 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100277 uint16_t maximum_number_of_out_vregs_;
278
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100279 // The number of virtual registers in this method. Contains the parameters.
280 uint16_t number_of_vregs_;
281
282 // The number of virtual registers used by parameters of this method.
283 uint16_t number_of_in_vregs_;
284
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000285 // Number of vreg size slots that the temporaries use (used in baseline compiler).
286 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100287
Mingyao Yange4335eb2015-03-02 15:14:13 -0800288 // Has array accesses. We can totally skip BCE if it's false.
289 bool has_array_accesses_;
290
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000291 // Indicates whether the graph should be compiled in a way that
292 // ensures full debuggability. If false, we can apply more
293 // aggressive optimizations that may limit the level of debugging.
294 const bool debuggable_;
295
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000296 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000297 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000298
David Brazdil46e2a392015-03-16 17:31:52 +0000299 // Cached common constants often needed by optimization passes.
David Brazdil8d5b8b22015-03-24 10:51:52 +0000300 HNullConstant* cached_null_constant_;
301 ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
302 ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
David Brazdil46e2a392015-03-16 17:31:52 +0000303
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +0100304 friend class SsaLivenessAnalysis; // For the linear order.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000305 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000306 DISALLOW_COPY_AND_ASSIGN(HGraph);
307};
308
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700309class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000310 public:
311 HLoopInformation(HBasicBlock* header, HGraph* graph)
312 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100313 suspend_check_(nullptr),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100314 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100315 // Make bit vector growable, as the number of blocks may change.
316 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100317
318 HBasicBlock* GetHeader() const {
319 return header_;
320 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000321
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000322 void SetHeader(HBasicBlock* block) {
323 header_ = block;
324 }
325
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100326 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
327 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
328 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
329
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000330 void AddBackEdge(HBasicBlock* back_edge) {
331 back_edges_.Add(back_edge);
332 }
333
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100334 void RemoveBackEdge(HBasicBlock* back_edge) {
335 back_edges_.Delete(back_edge);
336 }
337
David Brazdil46e2a392015-03-16 17:31:52 +0000338 bool IsBackEdge(const HBasicBlock& block) const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100339 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
David Brazdil46e2a392015-03-16 17:31:52 +0000340 if (back_edges_.Get(i) == &block) return true;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100341 }
342 return false;
343 }
344
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000345 size_t NumberOfBackEdges() const {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000346 return back_edges_.Size();
347 }
348
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100349 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100350
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100351 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
352 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100353 }
354
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100355 void ClearBackEdges() {
356 back_edges_.Reset();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100357 }
358
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100359 // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
360 // that is the header dominates the back edge.
361 bool Populate();
362
363 // Returns whether this loop information contains `block`.
364 // Note that this loop information *must* be populated before entering this function.
365 bool Contains(const HBasicBlock& block) const;
366
367 // Returns whether this loop information is an inner loop of `other`.
368 // Note that `other` *must* be populated before entering this function.
369 bool IsIn(const HLoopInformation& other) const;
370
371 const ArenaBitVector& GetBlocks() const { return blocks_; }
372
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000373 void Add(HBasicBlock* block);
David Brazdil46e2a392015-03-16 17:31:52 +0000374 void Remove(HBasicBlock* block);
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000375
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000376 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100377 // Internal recursive implementation of `Populate`.
378 void PopulateRecursive(HBasicBlock* block);
379
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000380 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100381 HSuspendCheck* suspend_check_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000382 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100383 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000384
385 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
386};
387
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100388static constexpr size_t kNoLifetime = -1;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100389static constexpr uint32_t kNoDexPc = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100390
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000391// A block in a method. Contains the list of instructions represented
392// as a double linked list. Each block knows its predecessors and
393// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100394
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700395class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000396 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100397 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000398 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000399 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
400 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000401 loop_information_(nullptr),
402 dominator_(nullptr),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100403 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100404 block_id_(-1),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100405 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100406 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000407 lifetime_end_(kNoLifetime),
408 is_catch_block_(false) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000409
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100410 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
411 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000412 }
413
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100414 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
415 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000416 }
417
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100418 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
419 return dominated_blocks_;
420 }
421
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100422 bool IsEntryBlock() const {
423 return graph_->GetEntryBlock() == this;
424 }
425
426 bool IsExitBlock() const {
427 return graph_->GetExitBlock() == this;
428 }
429
David Brazdil46e2a392015-03-16 17:31:52 +0000430 bool IsSingleGoto() const;
431
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000432 void AddBackEdge(HBasicBlock* back_edge) {
433 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000434 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000435 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100436 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000437 loop_information_->AddBackEdge(back_edge);
438 }
439
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000440 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000441 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000442
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000443 int GetBlockId() const { return block_id_; }
444 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000445
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000446 HBasicBlock* GetDominator() const { return dominator_; }
447 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100448 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000449 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
450 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
451 if (dominated_blocks_.Get(i) == existing) {
452 dominated_blocks_.Put(i, new_block);
453 return;
454 }
455 }
456 LOG(FATAL) << "Unreachable";
457 UNREACHABLE();
458 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000459
460 int NumberOfBackEdges() const {
461 return loop_information_ == nullptr
462 ? 0
463 : loop_information_->NumberOfBackEdges();
464 }
465
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100466 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
467 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100468 const HInstructionList& GetInstructions() const { return instructions_; }
469 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100470 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000471
472 void AddSuccessor(HBasicBlock* block) {
473 successors_.Add(block);
474 block->predecessors_.Add(this);
475 }
476
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100477 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
478 size_t successor_index = GetSuccessorIndexOf(existing);
479 DCHECK_NE(successor_index, static_cast<size_t>(-1));
480 existing->RemovePredecessor(this);
481 new_block->predecessors_.Add(this);
482 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000483 }
484
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000485 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
486 size_t predecessor_index = GetPredecessorIndexOf(existing);
487 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
488 existing->RemoveSuccessor(this);
489 new_block->successors_.Add(this);
490 predecessors_.Put(predecessor_index, new_block);
491 }
492
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100493 void RemovePredecessor(HBasicBlock* block) {
494 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100495 }
496
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000497 void RemoveSuccessor(HBasicBlock* block) {
498 successors_.Delete(block);
499 }
500
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100501 void ClearAllPredecessors() {
502 predecessors_.Reset();
503 }
504
505 void AddPredecessor(HBasicBlock* block) {
506 predecessors_.Add(block);
507 block->successors_.Add(this);
508 }
509
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100510 void SwapPredecessors() {
Nicolas Geoffrayc83d4412014-09-18 16:46:20 +0100511 DCHECK_EQ(predecessors_.Size(), 2u);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100512 HBasicBlock* temp = predecessors_.Get(0);
513 predecessors_.Put(0, predecessors_.Get(1));
514 predecessors_.Put(1, temp);
515 }
516
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100517 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
518 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
519 if (predecessors_.Get(i) == predecessor) {
520 return i;
521 }
522 }
523 return -1;
524 }
525
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100526 size_t GetSuccessorIndexOf(HBasicBlock* successor) {
527 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
528 if (successors_.Get(i) == successor) {
529 return i;
530 }
531 }
532 return -1;
533 }
534
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000535 // Split the block into two blocks just after `cursor`. Returns the newly
536 // created block. Note that this method just updates raw block information,
537 // like predecessors, successors, dominators, and instruction list. It does not
538 // update the graph, reverse post order, loop information, nor make sure the
539 // blocks are consistent (for example ending with a control flow instruction).
540 HBasicBlock* SplitAfter(HInstruction* cursor);
541
542 // Merge `other` at the end of `this`. Successors and dominated blocks of
543 // `other` are changed to be successors and dominated blocks of `this`. Note
544 // that this method does not update the graph, reverse post order, loop
545 // information, nor make sure the blocks are consistent (for example ending
546 // with a control flow instruction).
547 void MergeWith(HBasicBlock* other);
548
549 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
550 // of `this` are moved to `other`.
551 // Note that this method does not update the graph, reverse post order, loop
552 // information, nor make sure the blocks are consistent (for example ending
David Brazdil46e2a392015-03-16 17:31:52 +0000553 // with a control flow instruction).
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000554 void ReplaceWith(HBasicBlock* other);
555
David Brazdil46e2a392015-03-16 17:31:52 +0000556 // Disconnects `this` from all its predecessors, successors and the dominator.
557 // It assumes that `this` does not dominate any blocks.
558 // Note that this method does not update the graph, reverse post order, loop
559 // information, nor make sure the blocks are consistent (for example ending
560 // with a control flow instruction).
561 void DisconnectFromAll();
562
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000563 void AddInstruction(HInstruction* instruction);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100564 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +0100565 // Replace instruction `initial` with `replacement` within this block.
566 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
567 HInstruction* replacement);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100568 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100569 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
David Brazdil1abb4192015-02-17 18:33:36 +0000570 // RemoveInstruction and RemovePhi delete a given instruction from the respective
571 // instruction list. With 'ensure_safety' set to true, it verifies that the
572 // instruction is not in use and removes it from the use lists of its inputs.
573 void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
574 void RemovePhi(HPhi* phi, bool ensure_safety = true);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100575
576 bool IsLoopHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100577 return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100578 }
579
Roland Levillain6b879dd2014-09-22 17:13:44 +0100580 bool IsLoopPreHeaderFirstPredecessor() const {
581 DCHECK(IsLoopHeader());
582 DCHECK(!GetPredecessors().IsEmpty());
583 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
584 }
585
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100586 HLoopInformation* GetLoopInformation() const {
587 return loop_information_;
588 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000589
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000590 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100591 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000592 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100593 void SetInLoop(HLoopInformation* info) {
594 if (IsLoopHeader()) {
595 // Nothing to do. This just means `info` is an outer loop.
596 } else if (loop_information_ == nullptr) {
597 loop_information_ = info;
598 } else if (loop_information_->Contains(*info->GetHeader())) {
599 // Block is currently part of an outer loop. Make it part of this inner loop.
600 // Note that a non loop header having a loop information means this loop information
601 // has already been populated
602 loop_information_ = info;
603 } else {
604 // Block is part of an inner loop. Do not update the loop information.
605 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
606 // at this point, because this method is being called while populating `info`.
607 }
608 }
609
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000610 // Raw update of the loop information.
611 void SetLoopInformation(HLoopInformation* info) {
612 loop_information_ = info;
613 }
614
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100615 bool IsInLoop() const { return loop_information_ != nullptr; }
616
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100617 // Returns wheter this block dominates the blocked passed as parameter.
618 bool Dominates(HBasicBlock* block) const;
619
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100620 size_t GetLifetimeStart() const { return lifetime_start_; }
621 size_t GetLifetimeEnd() const { return lifetime_end_; }
622
623 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
624 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
625
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100626 uint32_t GetDexPc() const { return dex_pc_; }
627
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000628 bool IsCatchBlock() const { return is_catch_block_; }
629 void SetIsCatchBlock() { is_catch_block_ = true; }
630
David Brazdil8d5b8b22015-03-24 10:51:52 +0000631 bool EndsWithControlFlowInstruction() const;
David Brazdilb2bd1c52015-03-25 11:17:37 +0000632 bool EndsWithIf() const;
633 bool HasSinglePhi() const;
634
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000635 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000636 HGraph* graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000637 GrowableArray<HBasicBlock*> predecessors_;
638 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100639 HInstructionList instructions_;
640 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000641 HLoopInformation* loop_information_;
642 HBasicBlock* dominator_;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100643 GrowableArray<HBasicBlock*> dominated_blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000644 int block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100645 // The dex program counter of the first instruction of this block.
646 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100647 size_t lifetime_start_;
648 size_t lifetime_end_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000649 bool is_catch_block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000650
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000651 friend class HGraph;
652 friend class HInstruction;
653
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000654 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
655};
656
David Brazdilb2bd1c52015-03-25 11:17:37 +0000657// Iterates over the LoopInformation of all loops which contain 'block'
658// from the innermost to the outermost.
659class HLoopInformationOutwardIterator : public ValueObject {
660 public:
661 explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
662 : current_(block.GetLoopInformation()) {}
663
664 bool Done() const { return current_ == nullptr; }
665
666 void Advance() {
667 DCHECK(!Done());
668 current_ = current_->GetHeader()->GetDominator()->GetLoopInformation();
669 }
670
671 HLoopInformation* Current() const {
672 DCHECK(!Done());
673 return current_;
674 }
675
676 private:
677 HLoopInformation* current_;
678
679 DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
680};
681
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100682#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
683 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000684 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000685 M(ArrayGet, Instruction) \
686 M(ArrayLength, Instruction) \
687 M(ArraySet, Instruction) \
688 M(BoundsCheck, Instruction) \
Calin Juravleb1498f62015-02-16 13:13:29 +0000689 M(BoundType, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000690 M(CheckCast, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100691 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000692 M(Compare, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100693 M(Condition, BinaryOperation) \
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700694 M(Deoptimize, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000695 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +0000696 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000697 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100698 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000699 M(Exit, Instruction) \
700 M(FloatConstant, Constant) \
701 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100702 M(GreaterThan, Condition) \
703 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100704 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000705 M(InstanceFieldGet, Instruction) \
706 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000707 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100708 M(IntConstant, Constant) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000709 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000710 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100711 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000712 M(LessThan, Condition) \
713 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000714 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000715 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100716 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000717 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100718 M(Local, Instruction) \
719 M(LongConstant, Constant) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +0000720 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000721 M(Mul, BinaryOperation) \
722 M(Neg, UnaryOperation) \
723 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100724 M(NewInstance, Instruction) \
Roland Levillain1cc5f252014-10-22 18:06:21 +0100725 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000726 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000727 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000728 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000729 M(Or, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100730 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000731 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100732 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000733 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100734 M(Return, Instruction) \
735 M(ReturnVoid, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000736 M(Shl, BinaryOperation) \
737 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100738 M(StaticFieldGet, Instruction) \
739 M(StaticFieldSet, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100740 M(StoreLocal, Instruction) \
741 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100742 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000743 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000744 M(Throw, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +0000745 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000746 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000747 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000748
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100749#define FOR_EACH_INSTRUCTION(M) \
750 FOR_EACH_CONCRETE_INSTRUCTION(M) \
751 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +0100752 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +0100753 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100754 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -0700755
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100756#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000757FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
758#undef FORWARD_DECLARATION
759
Roland Levillainccc07a92014-09-16 14:48:16 +0100760#define DECLARE_INSTRUCTION(type) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000761 InstructionKind GetKind() const OVERRIDE { return k##type; } \
762 const char* DebugName() const OVERRIDE { return #type; } \
763 const H##type* As##type() const OVERRIDE { return this; } \
764 H##type* As##type() OVERRIDE { return this; } \
765 bool InstructionTypeEquals(HInstruction* other) const OVERRIDE { \
Roland Levillainccc07a92014-09-16 14:48:16 +0100766 return other->Is##type(); \
767 } \
Alexandre Rames2ed20af2015-03-06 13:55:35 +0000768 void Accept(HGraphVisitor* visitor) OVERRIDE
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000769
David Brazdiled596192015-01-23 10:39:45 +0000770template <typename T> class HUseList;
771
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100772template <typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700773class HUseListNode : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000774 public:
David Brazdiled596192015-01-23 10:39:45 +0000775 HUseListNode* GetPrevious() const { return prev_; }
776 HUseListNode* GetNext() const { return next_; }
777 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100778 size_t GetIndex() const { return index_; }
779
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000780 private:
David Brazdiled596192015-01-23 10:39:45 +0000781 HUseListNode(T user, size_t index)
782 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
783
784 T const user_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100785 const size_t index_;
David Brazdiled596192015-01-23 10:39:45 +0000786 HUseListNode<T>* prev_;
787 HUseListNode<T>* next_;
788
789 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000790
791 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
792};
793
David Brazdiled596192015-01-23 10:39:45 +0000794template <typename T>
795class HUseList : public ValueObject {
796 public:
797 HUseList() : first_(nullptr) {}
798
799 void Clear() {
800 first_ = nullptr;
801 }
802
803 // Adds a new entry at the beginning of the use list and returns
804 // the newly created node.
805 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +0000806 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +0000807 if (IsEmpty()) {
808 first_ = new_node;
809 } else {
810 first_->prev_ = new_node;
811 new_node->next_ = first_;
812 first_ = new_node;
813 }
814 return new_node;
815 }
816
817 HUseListNode<T>* GetFirst() const {
818 return first_;
819 }
820
821 void Remove(HUseListNode<T>* node) {
David Brazdil1abb4192015-02-17 18:33:36 +0000822 DCHECK(node != nullptr);
823 DCHECK(Contains(node));
824
David Brazdiled596192015-01-23 10:39:45 +0000825 if (node->prev_ != nullptr) {
826 node->prev_->next_ = node->next_;
827 }
828 if (node->next_ != nullptr) {
829 node->next_->prev_ = node->prev_;
830 }
831 if (node == first_) {
832 first_ = node->next_;
833 }
834 }
835
David Brazdil1abb4192015-02-17 18:33:36 +0000836 bool Contains(const HUseListNode<T>* node) const {
837 if (node == nullptr) {
838 return false;
839 }
840 for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
841 if (current == node) {
842 return true;
843 }
844 }
845 return false;
846 }
847
David Brazdiled596192015-01-23 10:39:45 +0000848 bool IsEmpty() const {
849 return first_ == nullptr;
850 }
851
852 bool HasOnlyOneUse() const {
853 return first_ != nullptr && first_->next_ == nullptr;
854 }
855
856 private:
857 HUseListNode<T>* first_;
858};
859
860template<typename T>
861class HUseIterator : public ValueObject {
862 public:
863 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
864
865 bool Done() const { return current_ == nullptr; }
866
867 void Advance() {
868 DCHECK(!Done());
869 current_ = current_->GetNext();
870 }
871
872 HUseListNode<T>* Current() const {
873 DCHECK(!Done());
874 return current_;
875 }
876
877 private:
878 HUseListNode<T>* current_;
879
880 friend class HValue;
881};
882
David Brazdil1abb4192015-02-17 18:33:36 +0000883// This class is used by HEnvironment and HInstruction classes to record the
884// instructions they use and pointers to the corresponding HUseListNodes kept
885// by the used instructions.
886template <typename T>
887class HUserRecord : public ValueObject {
888 public:
889 HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
890 explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
891
892 HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
893 : instruction_(old_record.instruction_), use_node_(use_node) {
894 DCHECK(instruction_ != nullptr);
895 DCHECK(use_node_ != nullptr);
896 DCHECK(old_record.use_node_ == nullptr);
897 }
898
899 HInstruction* GetInstruction() const { return instruction_; }
900 HUseListNode<T>* GetUseNode() const { return use_node_; }
901
902 private:
903 // Instruction used by the user.
904 HInstruction* instruction_;
905
906 // Corresponding entry in the use list kept by 'instruction_'.
907 HUseListNode<T>* use_node_;
908};
909
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100910// Represents the side effects an instruction may have.
911class SideEffects : public ValueObject {
912 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100913 SideEffects() : flags_(0) {}
914
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100915 static SideEffects None() {
916 return SideEffects(0);
917 }
918
919 static SideEffects All() {
920 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
921 }
922
923 static SideEffects ChangesSomething() {
924 return SideEffects((1 << kFlagChangesCount) - 1);
925 }
926
927 static SideEffects DependsOnSomething() {
928 int count = kFlagDependsOnCount - kFlagChangesCount;
929 return SideEffects(((1 << count) - 1) << kFlagChangesCount);
930 }
931
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100932 SideEffects Union(SideEffects other) const {
933 return SideEffects(flags_ | other.flags_);
934 }
935
Roland Levillain72bceff2014-09-15 18:29:00 +0100936 bool HasSideEffects() const {
937 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
938 return (flags_ & all_bits_set) != 0;
939 }
940
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100941 bool HasAllSideEffects() const {
942 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
943 return all_bits_set == (flags_ & all_bits_set);
944 }
945
946 bool DependsOn(SideEffects other) const {
947 size_t depends_flags = other.ComputeDependsFlags();
948 return (flags_ & depends_flags) != 0;
949 }
950
951 bool HasDependencies() const {
952 int count = kFlagDependsOnCount - kFlagChangesCount;
953 size_t all_bits_set = (1 << count) - 1;
954 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
955 }
956
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100957 private:
958 static constexpr int kFlagChangesSomething = 0;
959 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
960
961 static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
962 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
963
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100964 explicit SideEffects(size_t flags) : flags_(flags) {}
965
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100966 size_t ComputeDependsFlags() const {
967 return flags_ << kFlagChangesCount;
968 }
969
970 size_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100971};
972
David Brazdiled596192015-01-23 10:39:45 +0000973// A HEnvironment object contains the values of virtual registers at a given location.
974class HEnvironment : public ArenaObject<kArenaAllocMisc> {
975 public:
976 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs)
977 : vregs_(arena, number_of_vregs) {
978 vregs_.SetSize(number_of_vregs);
979 for (size_t i = 0; i < number_of_vregs; i++) {
David Brazdil1abb4192015-02-17 18:33:36 +0000980 vregs_.Put(i, HUserRecord<HEnvironment*>());
David Brazdiled596192015-01-23 10:39:45 +0000981 }
982 }
983
984 void CopyFrom(HEnvironment* env);
985
986 void SetRawEnvAt(size_t index, HInstruction* instruction) {
David Brazdil1abb4192015-02-17 18:33:36 +0000987 vregs_.Put(index, HUserRecord<HEnvironment*>(instruction));
David Brazdiled596192015-01-23 10:39:45 +0000988 }
989
990 HInstruction* GetInstructionAt(size_t index) const {
David Brazdil1abb4192015-02-17 18:33:36 +0000991 return vregs_.Get(index).GetInstruction();
David Brazdiled596192015-01-23 10:39:45 +0000992 }
993
David Brazdil1abb4192015-02-17 18:33:36 +0000994 void RemoveAsUserOfInput(size_t index) const;
David Brazdiled596192015-01-23 10:39:45 +0000995
996 size_t Size() const { return vregs_.Size(); }
997
998 private:
David Brazdil1abb4192015-02-17 18:33:36 +0000999 // Record instructions' use entries of this environment for constant-time removal.
1000 // It should only be called by HInstruction when a new environment use is added.
1001 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1002 DCHECK(env_use->GetUser() == this);
1003 size_t index = env_use->GetIndex();
1004 vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use));
1005 }
David Brazdiled596192015-01-23 10:39:45 +00001006
David Brazdil1abb4192015-02-17 18:33:36 +00001007 GrowableArray<HUserRecord<HEnvironment*> > vregs_;
David Brazdiled596192015-01-23 10:39:45 +00001008
David Brazdil1abb4192015-02-17 18:33:36 +00001009 friend HInstruction;
David Brazdiled596192015-01-23 10:39:45 +00001010
1011 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1012};
1013
Calin Juravleacf735c2015-02-12 15:25:22 +00001014class ReferenceTypeInfo : ValueObject {
1015 public:
Calin Juravleb1498f62015-02-16 13:13:29 +00001016 typedef Handle<mirror::Class> TypeHandle;
1017
1018 static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
1019 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1020 if (type_handle->IsObjectClass()) {
1021 // Override the type handle to be consistent with the case when we get to
1022 // Top but don't have the Object class available. It avoids having to guess
1023 // what value the type_handle has when it's Top.
1024 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1025 } else {
1026 return ReferenceTypeInfo(type_handle, is_exact, false);
1027 }
1028 }
1029
1030 static ReferenceTypeInfo CreateTop(bool is_exact) {
1031 return ReferenceTypeInfo(TypeHandle(), is_exact, true);
Calin Juravleacf735c2015-02-12 15:25:22 +00001032 }
1033
1034 bool IsExact() const { return is_exact_; }
1035 bool IsTop() const { return is_top_; }
1036
1037 Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
1038
Calin Juravleb1498f62015-02-16 13:13:29 +00001039 bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Calin Juravleacf735c2015-02-12 15:25:22 +00001040 if (IsTop()) {
1041 // Top (equivalent for java.lang.Object) is supertype of anything.
1042 return true;
1043 }
1044 if (rti.IsTop()) {
1045 // If we get here `this` is not Top() so it can't be a supertype.
1046 return false;
1047 }
1048 return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
1049 }
1050
1051 // Returns true if the type information provide the same amount of details.
1052 // Note that it does not mean that the instructions have the same actual type
1053 // (e.g. tops are equal but they can be the result of a merge).
1054 bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1055 if (IsExact() != rti.IsExact()) {
1056 return false;
1057 }
1058 if (IsTop() && rti.IsTop()) {
1059 // `Top` means java.lang.Object, so the types are equivalent.
1060 return true;
1061 }
1062 if (IsTop() || rti.IsTop()) {
1063 // If only one is top or object than they are not equivalent.
1064 // NB: We need this extra check because the type_handle of `Top` is invalid
1065 // and we cannot inspect its reference.
1066 return false;
1067 }
1068
1069 // Finally check the types.
1070 return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
1071 }
1072
1073 private:
Calin Juravleb1498f62015-02-16 13:13:29 +00001074 ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
1075 ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
1076 : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
1077
Calin Juravleacf735c2015-02-12 15:25:22 +00001078 // The class of the object.
Calin Juravleb1498f62015-02-16 13:13:29 +00001079 TypeHandle type_handle_;
Calin Juravleacf735c2015-02-12 15:25:22 +00001080 // Whether or not the type is exact or a superclass of the actual type.
Calin Juravleb1498f62015-02-16 13:13:29 +00001081 // Whether or not we have any information about this type.
Calin Juravleacf735c2015-02-12 15:25:22 +00001082 bool is_exact_;
1083 // A true value here means that the object type should be java.lang.Object.
1084 // We don't have access to the corresponding mirror object every time so this
1085 // flag acts as a substitute. When true, the TypeHandle refers to a null
1086 // pointer and should not be used.
1087 bool is_top_;
1088};
1089
1090std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
1091
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001092class HInstruction : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001093 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001094 explicit HInstruction(SideEffects side_effects)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001095 : previous_(nullptr),
1096 next_(nullptr),
1097 block_(nullptr),
1098 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001099 ssa_index_(-1),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001100 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001101 locations_(nullptr),
1102 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001103 lifetime_position_(kNoLifetime),
Calin Juravleb1498f62015-02-16 13:13:29 +00001104 side_effects_(side_effects),
1105 reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001106
Dave Allison20dfc792014-06-16 20:44:29 -07001107 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001108
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001109#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001110 enum InstructionKind {
1111 FOR_EACH_INSTRUCTION(DECLARE_KIND)
1112 };
1113#undef DECLARE_KIND
1114
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001115 HInstruction* GetNext() const { return next_; }
1116 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001117
Calin Juravle77520bc2015-01-12 18:45:46 +00001118 HInstruction* GetNextDisregardingMoves() const;
1119 HInstruction* GetPreviousDisregardingMoves() const;
1120
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001121 HBasicBlock* GetBlock() const { return block_; }
1122 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001123 bool IsInBlock() const { return block_ != nullptr; }
1124 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray3ac17fc2014-08-06 23:02:54 +01001125 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001126
Roland Levillain6b879dd2014-09-22 17:13:44 +01001127 virtual size_t InputCount() const = 0;
David Brazdil1abb4192015-02-17 18:33:36 +00001128 HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001129
1130 virtual void Accept(HGraphVisitor* visitor) = 0;
1131 virtual const char* DebugName() const = 0;
1132
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001133 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
David Brazdil1abb4192015-02-17 18:33:36 +00001134 void SetRawInputAt(size_t index, HInstruction* input) {
1135 SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1136 }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001137
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001138 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001139 virtual bool IsControlFlow() const { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01001140 virtual bool CanThrow() const { return false; }
Roland Levillain72bceff2014-09-15 18:29:00 +01001141 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001142
Calin Juravle61d544b2015-02-23 16:46:57 +00001143 virtual bool ActAsNullConstant() const { return false; }
1144
Calin Juravle10e244f2015-01-26 18:54:32 +00001145 // Does not apply for all instructions, but having this at top level greatly
1146 // simplifies the null check elimination.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001147 virtual bool CanBeNull() const {
1148 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1149 return true;
1150 }
Calin Juravle10e244f2015-01-26 18:54:32 +00001151
Calin Juravle77520bc2015-01-12 18:45:46 +00001152 virtual bool CanDoImplicitNullCheck() const { return false; }
1153
Calin Juravleacf735c2015-02-12 15:25:22 +00001154 void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
Calin Juravle61d544b2015-02-23 16:46:57 +00001155 DCHECK_EQ(GetType(), Primitive::kPrimNot);
Calin Juravleacf735c2015-02-12 15:25:22 +00001156 reference_type_info_ = reference_type_info;
1157 }
1158
Calin Juravle61d544b2015-02-23 16:46:57 +00001159 ReferenceTypeInfo GetReferenceTypeInfo() const {
1160 DCHECK_EQ(GetType(), Primitive::kPrimNot);
1161 return reference_type_info_;
1162 }
Calin Juravleacf735c2015-02-12 15:25:22 +00001163
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001164 void AddUseAt(HInstruction* user, size_t index) {
David Brazdil1abb4192015-02-17 18:33:36 +00001165 DCHECK(user != nullptr);
1166 HUseListNode<HInstruction*>* use =
1167 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1168 user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001169 }
1170
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001171 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +01001172 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +00001173 HUseListNode<HEnvironment*>* env_use =
1174 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1175 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001176 }
1177
David Brazdil1abb4192015-02-17 18:33:36 +00001178 void RemoveAsUserOfInput(size_t input) {
1179 HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1180 input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1181 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001182
David Brazdil1abb4192015-02-17 18:33:36 +00001183 const HUseList<HInstruction*>& GetUses() const { return uses_; }
1184 const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001185
David Brazdiled596192015-01-23 10:39:45 +00001186 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
1187 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray915b9d02015-03-11 15:11:19 +00001188 bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
Alexandre Rames188d4312015-04-09 18:30:21 +01001189 bool HasOnlyOneNonEnvironmentUse() const {
1190 return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1191 }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001192
Roland Levillain6c82d402014-10-13 16:10:27 +01001193 // Does this instruction strictly dominate `other_instruction`?
1194 // Returns false if this instruction and `other_instruction` are the same.
1195 // Aborts if this instruction and `other_instruction` are both phis.
1196 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +01001197
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001198 int GetId() const { return id_; }
1199 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001200
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001201 int GetSsaIndex() const { return ssa_index_; }
1202 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
1203 bool HasSsaIndex() const { return ssa_index_ != -1; }
1204
1205 bool HasEnvironment() const { return environment_ != nullptr; }
1206 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001207 // Set the `environment_` field. Raw because this method does not
1208 // update the uses lists.
1209 void SetRawEnvironment(HEnvironment* environment) { environment_ = environment; }
1210
1211 // Set the environment of this instruction, copying it from `environment`. While
1212 // copying, the uses lists are being updated.
1213 void CopyEnvironmentFrom(HEnvironment* environment) {
1214 ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
1215 environment_ = new (allocator) HEnvironment(allocator, environment->Size());
1216 environment_->CopyFrom(environment);
1217 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001218
Nicolas Geoffray39468442014-09-02 15:17:15 +01001219 // Returns the number of entries in the environment. Typically, that is the
1220 // number of dex registers in a method. It could be more in case of inlining.
1221 size_t EnvironmentSize() const;
1222
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001223 LocationSummary* GetLocations() const { return locations_; }
1224 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001225
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001226 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001227 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001228
Alexandre Rames188d4312015-04-09 18:30:21 +01001229 // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1230 // uses of this instruction by `other` are *not* updated.
1231 void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
1232 ReplaceWith(other);
1233 other->ReplaceInput(this, use_index);
1234 }
1235
Nicolas Geoffray82091da2015-01-26 10:02:45 +00001236 // Move `this` instruction before `cursor`.
1237 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001238
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001239#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +01001240 bool Is##type() const { return (As##type() != nullptr); } \
1241 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001242 virtual H##type* As##type() { return nullptr; }
1243
1244 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
1245#undef INSTRUCTION_TYPE_CHECK
1246
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001247 // Returns whether the instruction can be moved within the graph.
1248 virtual bool CanBeMoved() const { return false; }
1249
1250 // Returns whether the two instructions are of the same kind.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001251 virtual bool InstructionTypeEquals(HInstruction* other) const {
1252 UNUSED(other);
1253 return false;
1254 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001255
1256 // Returns whether any data encoded in the two instructions is equal.
1257 // This method does not look at the inputs. Both instructions must be
1258 // of the same type, otherwise the method has undefined behavior.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001259 virtual bool InstructionDataEquals(HInstruction* other) const {
1260 UNUSED(other);
1261 return false;
1262 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001263
1264 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00001265 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001266 // 2) Their inputs are identical.
1267 bool Equals(HInstruction* other) const;
1268
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001269 virtual InstructionKind GetKind() const = 0;
1270
1271 virtual size_t ComputeHashCode() const {
1272 size_t result = GetKind();
1273 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1274 result = (result * 31) + InputAt(i)->GetId();
1275 }
1276 return result;
1277 }
1278
1279 SideEffects GetSideEffects() const { return side_effects_; }
1280
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001281 size_t GetLifetimePosition() const { return lifetime_position_; }
1282 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
1283 LiveInterval* GetLiveInterval() const { return live_interval_; }
1284 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
1285 bool HasLiveInterval() const { return live_interval_ != nullptr; }
1286
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00001287 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1288
1289 // Returns whether the code generation of the instruction will require to have access
1290 // to the current method. Such instructions are:
1291 // (1): Instructions that require an environment, as calling the runtime requires
1292 // to walk the stack and have the current method stored at a specific stack address.
1293 // (2): Object literals like classes and strings, that are loaded from the dex cache
1294 // fields of the current method.
1295 bool NeedsCurrentMethod() const {
1296 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1297 }
1298
Nicolas Geoffray9437b782015-03-25 10:08:51 +00001299 virtual bool NeedsDexCache() const { return false; }
1300
David Brazdil1abb4192015-02-17 18:33:36 +00001301 protected:
1302 virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
1303 virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
1304
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001305 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001306 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
1307
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001308 HInstruction* previous_;
1309 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001310 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001311
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001312 // An instruction gets an id when it is added to the graph.
1313 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01001314 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001315 int id_;
1316
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001317 // When doing liveness analysis, instructions that have uses get an SSA index.
1318 int ssa_index_;
1319
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001320 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00001321 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001322
1323 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00001324 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001325
Nicolas Geoffray39468442014-09-02 15:17:15 +01001326 // The environment associated with this instruction. Not null if the instruction
1327 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001328 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001329
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001330 // Set by the code generator.
1331 LocationSummary* locations_;
1332
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001333 // Set by the liveness analysis.
1334 LiveInterval* live_interval_;
1335
1336 // Set by the liveness analysis, this is the position in a linear
1337 // order of blocks where this instruction's live interval start.
1338 size_t lifetime_position_;
1339
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001340 const SideEffects side_effects_;
1341
Calin Juravleacf735c2015-02-12 15:25:22 +00001342 // TODO: for primitive types this should be marked as invalid.
1343 ReferenceTypeInfo reference_type_info_;
1344
David Brazdil1abb4192015-02-17 18:33:36 +00001345 friend class GraphChecker;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001346 friend class HBasicBlock;
David Brazdil1abb4192015-02-17 18:33:36 +00001347 friend class HEnvironment;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001348 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001349 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001350
1351 DISALLOW_COPY_AND_ASSIGN(HInstruction);
1352};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001353std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001354
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001355class HInputIterator : public ValueObject {
1356 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001357 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001358
1359 bool Done() const { return index_ == instruction_->InputCount(); }
1360 HInstruction* Current() const { return instruction_->InputAt(index_); }
1361 void Advance() { index_++; }
1362
1363 private:
1364 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001365 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001366
1367 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1368};
1369
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001370class HInstructionIterator : public ValueObject {
1371 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001372 explicit HInstructionIterator(const HInstructionList& instructions)
1373 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001374 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001375 }
1376
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001377 bool Done() const { return instruction_ == nullptr; }
1378 HInstruction* Current() const { return instruction_; }
1379 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001380 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001381 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001382 }
1383
1384 private:
1385 HInstruction* instruction_;
1386 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001387
1388 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001389};
1390
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001391class HBackwardInstructionIterator : public ValueObject {
1392 public:
1393 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1394 : instruction_(instructions.last_instruction_) {
1395 next_ = Done() ? nullptr : instruction_->GetPrevious();
1396 }
1397
1398 bool Done() const { return instruction_ == nullptr; }
1399 HInstruction* Current() const { return instruction_; }
1400 void Advance() {
1401 instruction_ = next_;
1402 next_ = Done() ? nullptr : instruction_->GetPrevious();
1403 }
1404
1405 private:
1406 HInstruction* instruction_;
1407 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001408
1409 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001410};
1411
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001412// An embedded container with N elements of type T. Used (with partial
1413// specialization for N=0) because embedded arrays cannot have size 0.
1414template<typename T, intptr_t N>
1415class EmbeddedArray {
1416 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001417 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001418
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001419 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001420
1421 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001422 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001423 return elements_[i];
1424 }
1425
1426 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001427 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001428 return elements_[i];
1429 }
1430
1431 const T& At(intptr_t i) const {
1432 return (*this)[i];
1433 }
1434
1435 void SetAt(intptr_t i, const T& val) {
1436 (*this)[i] = val;
1437 }
1438
1439 private:
1440 T elements_[N];
1441};
1442
1443template<typename T>
1444class EmbeddedArray<T, 0> {
1445 public:
1446 intptr_t length() const { return 0; }
1447 const T& operator[](intptr_t i) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001448 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001449 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001450 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001451 }
1452 T& operator[](intptr_t i) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001453 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001454 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001455 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001456 }
1457};
1458
1459template<intptr_t N>
1460class HTemplateInstruction: public HInstruction {
1461 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001462 HTemplateInstruction<N>(SideEffects side_effects)
1463 : HInstruction(side_effects), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07001464 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001465
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001466 size_t InputCount() const OVERRIDE { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001467
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001468 protected:
David Brazdil1abb4192015-02-17 18:33:36 +00001469 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; }
1470
1471 void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
1472 inputs_[i] = input;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001473 }
1474
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001475 private:
David Brazdil1abb4192015-02-17 18:33:36 +00001476 EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001477
1478 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001479};
1480
Dave Allison20dfc792014-06-16 20:44:29 -07001481template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001482class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07001483 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001484 HExpression<N>(Primitive::Type type, SideEffects side_effects)
1485 : HTemplateInstruction<N>(side_effects), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07001486 virtual ~HExpression() {}
1487
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001488 Primitive::Type GetType() const OVERRIDE { return type_; }
Dave Allison20dfc792014-06-16 20:44:29 -07001489
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001490 protected:
1491 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07001492};
1493
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001494// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1495// instruction that branches to the exit block.
1496class HReturnVoid : public HTemplateInstruction<0> {
1497 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001498 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001499
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001500 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001501
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001502 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001503
1504 private:
1505 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1506};
1507
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001508// Represents dex's RETURN opcodes. A HReturn is a control flow
1509// instruction that branches to the exit block.
1510class HReturn : public HTemplateInstruction<1> {
1511 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001512 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001513 SetRawInputAt(0, value);
1514 }
1515
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001516 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001517
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001518 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001519
1520 private:
1521 DISALLOW_COPY_AND_ASSIGN(HReturn);
1522};
1523
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001524// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001525// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001526// exit block.
1527class HExit : public HTemplateInstruction<0> {
1528 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001529 HExit() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001530
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001531 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001532
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001533 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001534
1535 private:
1536 DISALLOW_COPY_AND_ASSIGN(HExit);
1537};
1538
1539// Jumps from one block to another.
1540class HGoto : public HTemplateInstruction<0> {
1541 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001542 HGoto() : HTemplateInstruction(SideEffects::None()) {}
1543
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001544 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001545
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001546 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001547 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001548 }
1549
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001550 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001551
1552 private:
1553 DISALLOW_COPY_AND_ASSIGN(HGoto);
1554};
1555
Dave Allison20dfc792014-06-16 20:44:29 -07001556
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001557// Conditional branch. A block ending with an HIf instruction must have
1558// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001559class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001560 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001561 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001562 SetRawInputAt(0, input);
1563 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001564
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001565 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001566
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001567 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001568 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001569 }
1570
1571 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001572 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001573 }
1574
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001575 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001576
1577 private:
1578 DISALLOW_COPY_AND_ASSIGN(HIf);
1579};
1580
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001581// Deoptimize to interpreter, upon checking a condition.
1582class HDeoptimize : public HTemplateInstruction<1> {
1583 public:
1584 HDeoptimize(HInstruction* cond, uint32_t dex_pc)
1585 : HTemplateInstruction(SideEffects::None()),
1586 dex_pc_(dex_pc) {
1587 SetRawInputAt(0, cond);
1588 }
1589
1590 bool NeedsEnvironment() const OVERRIDE { return true; }
1591 bool CanThrow() const OVERRIDE { return true; }
1592 uint32_t GetDexPc() const { return dex_pc_; }
1593
1594 DECLARE_INSTRUCTION(Deoptimize);
1595
1596 private:
1597 uint32_t dex_pc_;
1598
1599 DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
1600};
1601
Roland Levillain88cb1752014-10-20 16:36:47 +01001602class HUnaryOperation : public HExpression<1> {
1603 public:
1604 HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1605 : HExpression(result_type, SideEffects::None()) {
1606 SetRawInputAt(0, input);
1607 }
1608
1609 HInstruction* GetInput() const { return InputAt(0); }
1610 Primitive::Type GetResultType() const { return GetType(); }
1611
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001612 bool CanBeMoved() const OVERRIDE { return true; }
1613 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001614 UNUSED(other);
1615 return true;
1616 }
Roland Levillain88cb1752014-10-20 16:36:47 +01001617
Roland Levillain9240d6a2014-10-20 16:47:04 +01001618 // Try to statically evaluate `operation` and return a HConstant
1619 // containing the result of this evaluation. If `operation` cannot
1620 // be evaluated as a constant, return nullptr.
1621 HConstant* TryStaticEvaluation() const;
1622
1623 // Apply this operation to `x`.
1624 virtual int32_t Evaluate(int32_t x) const = 0;
1625 virtual int64_t Evaluate(int64_t x) const = 0;
1626
Roland Levillain88cb1752014-10-20 16:36:47 +01001627 DECLARE_INSTRUCTION(UnaryOperation);
1628
1629 private:
1630 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1631};
1632
Dave Allison20dfc792014-06-16 20:44:29 -07001633class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001634 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001635 HBinaryOperation(Primitive::Type result_type,
1636 HInstruction* left,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001637 HInstruction* right) : HExpression(result_type, SideEffects::None()) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001638 SetRawInputAt(0, left);
1639 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001640 }
1641
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001642 HInstruction* GetLeft() const { return InputAt(0); }
1643 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07001644 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001645
Mingyao Yangdc5ac732015-02-25 11:28:05 -08001646 virtual bool IsCommutative() const { return false; }
1647
1648 // Put constant on the right.
1649 // Returns whether order is changed.
1650 bool OrderInputsWithConstantOnTheRight() {
1651 HInstruction* left = InputAt(0);
1652 HInstruction* right = InputAt(1);
1653 if (left->IsConstant() && !right->IsConstant()) {
1654 ReplaceInput(right, 0);
1655 ReplaceInput(left, 1);
1656 return true;
1657 }
1658 return false;
1659 }
1660
1661 // Order inputs by instruction id, but favor constant on the right side.
1662 // This helps GVN for commutative ops.
1663 void OrderInputs() {
1664 DCHECK(IsCommutative());
1665 HInstruction* left = InputAt(0);
1666 HInstruction* right = InputAt(1);
1667 if (left == right || (!left->IsConstant() && right->IsConstant())) {
1668 return;
1669 }
1670 if (OrderInputsWithConstantOnTheRight()) {
1671 return;
1672 }
1673 // Order according to instruction id.
1674 if (left->GetId() > right->GetId()) {
1675 ReplaceInput(right, 0);
1676 ReplaceInput(left, 1);
1677 }
1678 }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001679
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001680 bool CanBeMoved() const OVERRIDE { return true; }
1681 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001682 UNUSED(other);
1683 return true;
1684 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001685
Roland Levillain9240d6a2014-10-20 16:47:04 +01001686 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01001687 // containing the result of this evaluation. If `operation` cannot
1688 // be evaluated as a constant, return nullptr.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001689 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01001690
1691 // Apply this operation to `x` and `y`.
1692 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1693 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1694
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001695 // Returns an input that can legally be used as the right input and is
1696 // constant, or nullptr.
1697 HConstant* GetConstantRight() const;
1698
1699 // If `GetConstantRight()` returns one of the input, this returns the other
1700 // one. Otherwise it returns nullptr.
1701 HInstruction* GetLeastConstantLeft() const;
1702
Roland Levillainccc07a92014-09-16 14:48:16 +01001703 DECLARE_INSTRUCTION(BinaryOperation);
1704
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001705 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001706 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1707};
1708
Dave Allison20dfc792014-06-16 20:44:29 -07001709class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001710 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001711 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001712 : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1713 needs_materialization_(true) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001714
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001715 bool NeedsMaterialization() const { return needs_materialization_; }
1716 void ClearNeedsMaterialization() { needs_materialization_ = false; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001717
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001718 // For code generation purposes, returns whether this instruction is just before
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001719 // `instruction`, and disregard moves in between.
1720 bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001721
Dave Allison20dfc792014-06-16 20:44:29 -07001722 DECLARE_INSTRUCTION(Condition);
1723
1724 virtual IfCondition GetCondition() const = 0;
1725
1726 private:
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001727 // For register allocation purposes, returns whether this instruction needs to be
1728 // materialized (that is, not just be in the processor flags).
1729 bool needs_materialization_;
1730
Dave Allison20dfc792014-06-16 20:44:29 -07001731 DISALLOW_COPY_AND_ASSIGN(HCondition);
1732};
1733
1734// Instruction to check if two inputs are equal to each other.
1735class HEqual : public HCondition {
1736 public:
1737 HEqual(HInstruction* first, HInstruction* second)
1738 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001739
Mingyao Yangdc5ac732015-02-25 11:28:05 -08001740 bool IsCommutative() const OVERRIDE { return true; }
1741
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001742 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001743 return x == y ? 1 : 0;
1744 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001745 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001746 return x == y ? 1 : 0;
1747 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001748
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001749 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001750
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001751 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001752 return kCondEQ;
1753 }
1754
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001755 private:
1756 DISALLOW_COPY_AND_ASSIGN(HEqual);
1757};
1758
Dave Allison20dfc792014-06-16 20:44:29 -07001759class HNotEqual : public HCondition {
1760 public:
1761 HNotEqual(HInstruction* first, HInstruction* second)
1762 : HCondition(first, second) {}
1763
Mingyao Yangdc5ac732015-02-25 11:28:05 -08001764 bool IsCommutative() const OVERRIDE { return true; }
1765
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001766 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001767 return x != y ? 1 : 0;
1768 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001769 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001770 return x != y ? 1 : 0;
1771 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001772
Dave Allison20dfc792014-06-16 20:44:29 -07001773 DECLARE_INSTRUCTION(NotEqual);
1774
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001775 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001776 return kCondNE;
1777 }
1778
1779 private:
1780 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
1781};
1782
1783class HLessThan : public HCondition {
1784 public:
1785 HLessThan(HInstruction* first, HInstruction* second)
1786 : HCondition(first, second) {}
1787
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001788 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001789 return x < y ? 1 : 0;
1790 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001791 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001792 return x < y ? 1 : 0;
1793 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001794
Dave Allison20dfc792014-06-16 20:44:29 -07001795 DECLARE_INSTRUCTION(LessThan);
1796
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001797 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001798 return kCondLT;
1799 }
1800
1801 private:
1802 DISALLOW_COPY_AND_ASSIGN(HLessThan);
1803};
1804
1805class HLessThanOrEqual : public HCondition {
1806 public:
1807 HLessThanOrEqual(HInstruction* first, HInstruction* second)
1808 : HCondition(first, second) {}
1809
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001810 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001811 return x <= y ? 1 : 0;
1812 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001813 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001814 return x <= y ? 1 : 0;
1815 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001816
Dave Allison20dfc792014-06-16 20:44:29 -07001817 DECLARE_INSTRUCTION(LessThanOrEqual);
1818
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001819 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001820 return kCondLE;
1821 }
1822
1823 private:
1824 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
1825};
1826
1827class HGreaterThan : public HCondition {
1828 public:
1829 HGreaterThan(HInstruction* first, HInstruction* second)
1830 : HCondition(first, second) {}
1831
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001832 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001833 return x > y ? 1 : 0;
1834 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001835 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001836 return x > y ? 1 : 0;
1837 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001838
Dave Allison20dfc792014-06-16 20:44:29 -07001839 DECLARE_INSTRUCTION(GreaterThan);
1840
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001841 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001842 return kCondGT;
1843 }
1844
1845 private:
1846 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
1847};
1848
1849class HGreaterThanOrEqual : public HCondition {
1850 public:
1851 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
1852 : HCondition(first, second) {}
1853
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001854 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001855 return x >= y ? 1 : 0;
1856 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001857 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01001858 return x >= y ? 1 : 0;
1859 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001860
Dave Allison20dfc792014-06-16 20:44:29 -07001861 DECLARE_INSTRUCTION(GreaterThanOrEqual);
1862
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001863 IfCondition GetCondition() const OVERRIDE {
Dave Allison20dfc792014-06-16 20:44:29 -07001864 return kCondGE;
1865 }
1866
1867 private:
1868 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
1869};
1870
1871
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001872// Instruction to check how two inputs compare to each other.
1873// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
1874class HCompare : public HBinaryOperation {
1875 public:
Calin Juravleddb7df22014-11-25 20:56:51 +00001876 // The bias applies for floating point operations and indicates how NaN
1877 // comparisons are treated:
1878 enum Bias {
1879 kNoBias, // bias is not applicable (i.e. for long operation)
1880 kGtBias, // return 1 for NaN comparisons
1881 kLtBias, // return -1 for NaN comparisons
1882 };
1883
1884 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias)
1885 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001886 DCHECK_EQ(type, first->GetType());
1887 DCHECK_EQ(type, second->GetType());
1888 }
1889
Calin Juravleddb7df22014-11-25 20:56:51 +00001890 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01001891 return
1892 x == y ? 0 :
1893 x > y ? 1 :
1894 -1;
1895 }
Calin Juravleddb7df22014-11-25 20:56:51 +00001896
1897 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01001898 return
1899 x == y ? 0 :
1900 x > y ? 1 :
1901 -1;
1902 }
1903
Calin Juravleddb7df22014-11-25 20:56:51 +00001904 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
1905 return bias_ == other->AsCompare()->bias_;
1906 }
1907
1908 bool IsGtBias() { return bias_ == kGtBias; }
1909
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001910 DECLARE_INSTRUCTION(Compare);
1911
1912 private:
Calin Juravleddb7df22014-11-25 20:56:51 +00001913 const Bias bias_;
1914
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001915 DISALLOW_COPY_AND_ASSIGN(HCompare);
1916};
1917
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001918// A local in the graph. Corresponds to a Dex register.
1919class HLocal : public HTemplateInstruction<0> {
1920 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001921 explicit HLocal(uint16_t reg_number)
1922 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001923
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001924 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001925
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001926 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001927
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001928 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001929 // The Dex register number.
1930 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001931
1932 DISALLOW_COPY_AND_ASSIGN(HLocal);
1933};
1934
1935// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07001936class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001937 public:
Roland Levillain5799fc02014-09-25 12:15:20 +01001938 HLoadLocal(HLocal* local, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001939 : HExpression(type, SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001940 SetRawInputAt(0, local);
1941 }
1942
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001943 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1944
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001945 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001946
1947 private:
1948 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
1949};
1950
1951// Store a value in a given local. This instruction has two inputs: the value
1952// and the local.
1953class HStoreLocal : public HTemplateInstruction<2> {
1954 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001955 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001956 SetRawInputAt(0, local);
1957 SetRawInputAt(1, value);
1958 }
1959
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001960 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1961
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001962 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001963
1964 private:
1965 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
1966};
1967
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001968class HConstant : public HExpression<0> {
1969 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001970 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
1971
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001972 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001973
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001974 virtual bool IsMinusOne() const { return false; }
1975 virtual bool IsZero() const { return false; }
1976 virtual bool IsOne() const { return false; }
1977
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001978 DECLARE_INSTRUCTION(Constant);
1979
1980 private:
1981 DISALLOW_COPY_AND_ASSIGN(HConstant);
1982};
1983
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001984class HFloatConstant : public HConstant {
1985 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001986 float GetValue() const { return value_; }
1987
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001988 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00001989 return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
1990 bit_cast<uint32_t, float>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001991 }
1992
Alexandre Rames2ed20af2015-03-06 13:55:35 +00001993 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001994
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001995 bool IsMinusOne() const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00001996 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
1997 bit_cast<uint32_t, float>((-1.0f));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00001998 }
1999 bool IsZero() const OVERRIDE {
2000 return AsFloatConstant()->GetValue() == 0.0f;
2001 }
2002 bool IsOne() const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002003 return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
2004 bit_cast<uint32_t, float>(1.0f);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002005 }
2006
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002007 DECLARE_INSTRUCTION(FloatConstant);
2008
2009 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002010 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
2011
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002012 const float value_;
2013
David Brazdil8d5b8b22015-03-24 10:51:52 +00002014 // Only the SsaBuilder can currently create floating-point constants. If we
2015 // ever need to create them later in the pipeline, we will have to handle them
2016 // the same way as integral constants.
2017 friend class SsaBuilder;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002018 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2019};
2020
2021class HDoubleConstant : public HConstant {
2022 public:
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002023 double GetValue() const { return value_; }
2024
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002025 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002026 return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
2027 bit_cast<uint64_t, double>(value_);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002028 }
2029
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002030 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002031
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002032 bool IsMinusOne() const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002033 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
2034 bit_cast<uint64_t, double>((-1.0));
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002035 }
2036 bool IsZero() const OVERRIDE {
2037 return AsDoubleConstant()->GetValue() == 0.0;
2038 }
2039 bool IsOne() const OVERRIDE {
Roland Levillainda4d79b2015-03-24 14:36:11 +00002040 return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
2041 bit_cast<uint64_t, double>(1.0);
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002042 }
2043
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002044 DECLARE_INSTRUCTION(DoubleConstant);
2045
2046 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002047 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
2048
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002049 const double value_;
2050
David Brazdil8d5b8b22015-03-24 10:51:52 +00002051 // Only the SsaBuilder can currently create floating-point constants. If we
2052 // ever need to create them later in the pipeline, we will have to handle them
2053 // the same way as integral constants.
2054 friend class SsaBuilder;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002055 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2056};
2057
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002058class HNullConstant : public HConstant {
2059 public:
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002060 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2061 return true;
2062 }
2063
2064 size_t ComputeHashCode() const OVERRIDE { return 0; }
2065
Calin Juravle61d544b2015-02-23 16:46:57 +00002066 bool ActAsNullConstant() const OVERRIDE { return true; }
2067
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002068 DECLARE_INSTRUCTION(NullConstant);
2069
2070 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002071 HNullConstant() : HConstant(Primitive::kPrimNot) {}
2072
2073 friend class HGraph;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00002074 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2075};
2076
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002077// Constants of the type int. Those can be from Dex instructions, or
2078// synthesized (for example with the if-eqz instruction).
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002079class HIntConstant : public HConstant {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002080 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +00002081 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00002082
Calin Juravle61d544b2015-02-23 16:46:57 +00002083 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002084 return other->AsIntConstant()->value_ == value_;
2085 }
2086
Calin Juravle61d544b2015-02-23 16:46:57 +00002087 size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2088
2089 // TODO: Null is represented by the `0` constant. In most cases we replace it
2090 // with a HNullConstant but we don't do it when comparing (a != null). This
2091 // method is an workaround until we fix the above.
2092 bool ActAsNullConstant() const OVERRIDE { return value_ == 0; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002093
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002094 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2095 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2096 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2097
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002098 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002099
2100 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002101 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
2102
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002103 const int32_t value_;
2104
David Brazdil8d5b8b22015-03-24 10:51:52 +00002105 friend class HGraph;
2106 ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
2107 ART_FRIEND_TEST(ParallelMoveTest, ConstantLast);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00002108 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2109};
2110
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002111class HLongConstant : public HConstant {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002112 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002113 int64_t GetValue() const { return value_; }
2114
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002115 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002116 return other->AsLongConstant()->value_ == value_;
2117 }
2118
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002119 size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002120
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00002121 bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
2122 bool IsZero() const OVERRIDE { return GetValue() == 0; }
2123 bool IsOne() const OVERRIDE { return GetValue() == 1; }
2124
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002125 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002126
2127 private:
David Brazdil8d5b8b22015-03-24 10:51:52 +00002128 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
2129
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002130 const int64_t value_;
2131
David Brazdil8d5b8b22015-03-24 10:51:52 +00002132 friend class HGraph;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002133 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2134};
2135
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002136enum class Intrinsics {
2137#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
2138#include "intrinsics_list.h"
2139 kNone,
2140 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
2141#undef INTRINSICS_LIST
2142#undef OPTIMIZING_INTRINSICS
2143};
2144std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
2145
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002146class HInvoke : public HInstruction {
2147 public:
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002148 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002149
2150 // Runtime needs to walk the stack, so Dex -> Dex calls need to
2151 // know their environment.
Calin Juravle77520bc2015-01-12 18:45:46 +00002152 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002153
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01002154 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002155 SetRawInputAt(index, argument);
2156 }
2157
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002158 Primitive::Type GetType() const OVERRIDE { return return_type_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002159
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002160 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002161
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002162 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2163
2164 Intrinsics GetIntrinsic() {
2165 return intrinsic_;
2166 }
2167
2168 void SetIntrinsic(Intrinsics intrinsic) {
2169 intrinsic_ = intrinsic;
2170 }
2171
Nicolas Geoffray360231a2014-10-08 21:07:48 +01002172 DECLARE_INSTRUCTION(Invoke);
2173
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002174 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002175 HInvoke(ArenaAllocator* arena,
2176 uint32_t number_of_arguments,
2177 Primitive::Type return_type,
2178 uint32_t dex_pc,
2179 uint32_t dex_method_index)
2180 : HInstruction(SideEffects::All()),
2181 inputs_(arena, number_of_arguments),
2182 return_type_(return_type),
2183 dex_pc_(dex_pc),
2184 dex_method_index_(dex_method_index),
2185 intrinsic_(Intrinsics::kNone) {
2186 inputs_.SetSize(number_of_arguments);
2187 }
2188
David Brazdil1abb4192015-02-17 18:33:36 +00002189 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
2190 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2191 inputs_.Put(index, input);
2192 }
2193
2194 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01002195 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002196 const uint32_t dex_pc_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002197 const uint32_t dex_method_index_;
2198 Intrinsics intrinsic_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002199
2200 private:
2201 DISALLOW_COPY_AND_ASSIGN(HInvoke);
2202};
2203
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002204class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002205 public:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002206 HInvokeStaticOrDirect(ArenaAllocator* arena,
2207 uint32_t number_of_arguments,
2208 Primitive::Type return_type,
2209 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002210 uint32_t dex_method_index,
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002211 bool is_recursive,
Nicolas Geoffray79041292015-03-26 10:05:54 +00002212 InvokeType original_invoke_type,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002213 InvokeType invoke_type)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002214 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffray79041292015-03-26 10:05:54 +00002215 original_invoke_type_(original_invoke_type),
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002216 invoke_type_(invoke_type),
2217 is_recursive_(is_recursive) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002218
Calin Juravle77520bc2015-01-12 18:45:46 +00002219 bool CanDoImplicitNullCheck() const OVERRIDE {
2220 // We access the method via the dex cache so we can't do an implicit null check.
2221 // TODO: for intrinsics we can generate implicit null checks.
2222 return false;
2223 }
2224
Nicolas Geoffray79041292015-03-26 10:05:54 +00002225 InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002226 InvokeType GetInvokeType() const { return invoke_type_; }
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002227 bool IsRecursive() const { return is_recursive_; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00002228 bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002229
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002230 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002231
2232 private:
Nicolas Geoffray79041292015-03-26 10:05:54 +00002233 const InvokeType original_invoke_type_;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002234 const InvokeType invoke_type_;
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00002235 const bool is_recursive_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002236
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002237 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00002238};
2239
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002240class HInvokeVirtual : public HInvoke {
2241 public:
2242 HInvokeVirtual(ArenaAllocator* arena,
2243 uint32_t number_of_arguments,
2244 Primitive::Type return_type,
2245 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002246 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002247 uint32_t vtable_index)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002248 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002249 vtable_index_(vtable_index) {}
2250
Calin Juravle77520bc2015-01-12 18:45:46 +00002251 bool CanDoImplicitNullCheck() const OVERRIDE {
2252 // TODO: Add implicit null checks in intrinsics.
2253 return !GetLocations()->Intrinsified();
2254 }
2255
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01002256 uint32_t GetVTableIndex() const { return vtable_index_; }
2257
2258 DECLARE_INSTRUCTION(InvokeVirtual);
2259
2260 private:
2261 const uint32_t vtable_index_;
2262
2263 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
2264};
2265
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002266class HInvokeInterface : public HInvoke {
2267 public:
2268 HInvokeInterface(ArenaAllocator* arena,
2269 uint32_t number_of_arguments,
2270 Primitive::Type return_type,
2271 uint32_t dex_pc,
2272 uint32_t dex_method_index,
2273 uint32_t imt_index)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08002274 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002275 imt_index_(imt_index) {}
2276
Calin Juravle77520bc2015-01-12 18:45:46 +00002277 bool CanDoImplicitNullCheck() const OVERRIDE {
2278 // TODO: Add implicit null checks in intrinsics.
2279 return !GetLocations()->Intrinsified();
2280 }
2281
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002282 uint32_t GetImtIndex() const { return imt_index_; }
2283 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2284
2285 DECLARE_INSTRUCTION(InvokeInterface);
2286
2287 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00002288 const uint32_t imt_index_;
2289
2290 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
2291};
2292
Dave Allison20dfc792014-06-16 20:44:29 -07002293class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002294 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002295 HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002296 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2297 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002298 type_index_(type_index),
2299 entrypoint_(entrypoint) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002300
2301 uint32_t GetDexPc() const { return dex_pc_; }
2302 uint16_t GetTypeIndex() const { return type_index_; }
2303
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002304 // Calls runtime so needs an environment.
Calin Juravle92a6ed22014-12-02 18:58:03 +00002305 bool NeedsEnvironment() const OVERRIDE { return true; }
2306 // It may throw when called on:
2307 // - interfaces
2308 // - abstract/innaccessible/unknown classes
2309 // TODO: optimize when possible.
2310 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002311
Calin Juravle10e244f2015-01-26 18:54:32 +00002312 bool CanBeNull() const OVERRIDE { return false; }
2313
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002314 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2315
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002316 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002317
2318 private:
2319 const uint32_t dex_pc_;
2320 const uint16_t type_index_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002321 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01002322
2323 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
2324};
2325
Roland Levillain88cb1752014-10-20 16:36:47 +01002326class HNeg : public HUnaryOperation {
2327 public:
2328 explicit HNeg(Primitive::Type result_type, HInstruction* input)
2329 : HUnaryOperation(result_type, input) {}
2330
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002331 int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
2332 int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
Roland Levillain9240d6a2014-10-20 16:47:04 +01002333
Roland Levillain88cb1752014-10-20 16:36:47 +01002334 DECLARE_INSTRUCTION(Neg);
2335
2336 private:
2337 DISALLOW_COPY_AND_ASSIGN(HNeg);
2338};
2339
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002340class HNewArray : public HExpression<1> {
2341 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002342 HNewArray(HInstruction* length,
2343 uint32_t dex_pc,
2344 uint16_t type_index,
2345 QuickEntrypointEnum entrypoint)
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002346 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2347 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002348 type_index_(type_index),
2349 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002350 SetRawInputAt(0, length);
2351 }
2352
2353 uint32_t GetDexPc() const { return dex_pc_; }
2354 uint16_t GetTypeIndex() const { return type_index_; }
2355
2356 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00002357 bool NeedsEnvironment() const OVERRIDE { return true; }
2358
Mingyao Yang0c365e62015-03-31 15:09:29 -07002359 // May throw NegativeArraySizeException, OutOfMemoryError, etc.
2360 bool CanThrow() const OVERRIDE { return true; }
2361
Calin Juravle10e244f2015-01-26 18:54:32 +00002362 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002363
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002364 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2365
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002366 DECLARE_INSTRUCTION(NewArray);
2367
2368 private:
2369 const uint32_t dex_pc_;
2370 const uint16_t type_index_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00002371 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01002372
2373 DISALLOW_COPY_AND_ASSIGN(HNewArray);
2374};
2375
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002376class HAdd : public HBinaryOperation {
2377 public:
2378 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2379 : HBinaryOperation(result_type, left, right) {}
2380
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002381 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002382
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002383 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002384 return x + y;
2385 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002386 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002387 return x + y;
2388 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002389
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00002390 DECLARE_INSTRUCTION(Add);
2391
2392 private:
2393 DISALLOW_COPY_AND_ASSIGN(HAdd);
2394};
2395
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002396class HSub : public HBinaryOperation {
2397 public:
2398 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2399 : HBinaryOperation(result_type, left, right) {}
2400
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002401 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002402 return x - y;
2403 }
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002404 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain93445682014-10-06 19:24:02 +01002405 return x - y;
2406 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002407
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002408 DECLARE_INSTRUCTION(Sub);
2409
2410 private:
2411 DISALLOW_COPY_AND_ASSIGN(HSub);
2412};
2413
Calin Juravle34bacdf2014-10-07 20:23:36 +01002414class HMul : public HBinaryOperation {
2415 public:
2416 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2417 : HBinaryOperation(result_type, left, right) {}
2418
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002419 bool IsCommutative() const OVERRIDE { return true; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002420
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002421 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
2422 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
Calin Juravle34bacdf2014-10-07 20:23:36 +01002423
2424 DECLARE_INSTRUCTION(Mul);
2425
2426 private:
2427 DISALLOW_COPY_AND_ASSIGN(HMul);
2428};
2429
Calin Juravle7c4954d2014-10-28 16:57:40 +00002430class HDiv : public HBinaryOperation {
2431 public:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002432 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2433 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00002434
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002435 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002436 // Our graph structure ensures we never have 0 for `y` during constant folding.
2437 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00002438 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002439 return (y == -1) ? -x : x / y;
2440 }
Calin Juravlebacfec32014-11-14 15:54:36 +00002441
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002442 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002443 DCHECK_NE(y, 0);
2444 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2445 return (y == -1) ? -x : x / y;
2446 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00002447
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002448 uint32_t GetDexPc() const { return dex_pc_; }
2449
Calin Juravle7c4954d2014-10-28 16:57:40 +00002450 DECLARE_INSTRUCTION(Div);
2451
2452 private:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002453 const uint32_t dex_pc_;
2454
Calin Juravle7c4954d2014-10-28 16:57:40 +00002455 DISALLOW_COPY_AND_ASSIGN(HDiv);
2456};
2457
Calin Juravlebacfec32014-11-14 15:54:36 +00002458class HRem : public HBinaryOperation {
2459 public:
2460 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2461 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2462
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002463 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002464 DCHECK_NE(y, 0);
2465 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2466 return (y == -1) ? 0 : x % y;
2467 }
2468
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002469 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Calin Juravlebacfec32014-11-14 15:54:36 +00002470 DCHECK_NE(y, 0);
2471 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2472 return (y == -1) ? 0 : x % y;
2473 }
2474
2475 uint32_t GetDexPc() const { return dex_pc_; }
2476
2477 DECLARE_INSTRUCTION(Rem);
2478
2479 private:
2480 const uint32_t dex_pc_;
2481
2482 DISALLOW_COPY_AND_ASSIGN(HRem);
2483};
2484
Calin Juravled0d48522014-11-04 16:40:20 +00002485class HDivZeroCheck : public HExpression<1> {
2486 public:
2487 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
2488 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2489 SetRawInputAt(0, value);
2490 }
2491
2492 bool CanBeMoved() const OVERRIDE { return true; }
2493
2494 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2495 UNUSED(other);
2496 return true;
2497 }
2498
2499 bool NeedsEnvironment() const OVERRIDE { return true; }
2500 bool CanThrow() const OVERRIDE { return true; }
2501
2502 uint32_t GetDexPc() const { return dex_pc_; }
2503
2504 DECLARE_INSTRUCTION(DivZeroCheck);
2505
2506 private:
2507 const uint32_t dex_pc_;
2508
2509 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
2510};
2511
Calin Juravle9aec02f2014-11-18 23:06:35 +00002512class HShl : public HBinaryOperation {
2513 public:
2514 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2515 : HBinaryOperation(result_type, left, right) {}
2516
2517 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
2518 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
2519
2520 DECLARE_INSTRUCTION(Shl);
2521
2522 private:
2523 DISALLOW_COPY_AND_ASSIGN(HShl);
2524};
2525
2526class HShr : public HBinaryOperation {
2527 public:
2528 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2529 : HBinaryOperation(result_type, left, right) {}
2530
2531 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
2532 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
2533
2534 DECLARE_INSTRUCTION(Shr);
2535
2536 private:
2537 DISALLOW_COPY_AND_ASSIGN(HShr);
2538};
2539
2540class HUShr : public HBinaryOperation {
2541 public:
2542 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2543 : HBinaryOperation(result_type, left, right) {}
2544
2545 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2546 uint32_t ux = static_cast<uint32_t>(x);
2547 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
2548 return static_cast<int32_t>(ux >> uy);
2549 }
2550
2551 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2552 uint64_t ux = static_cast<uint64_t>(x);
2553 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
2554 return static_cast<int64_t>(ux >> uy);
2555 }
2556
2557 DECLARE_INSTRUCTION(UShr);
2558
2559 private:
2560 DISALLOW_COPY_AND_ASSIGN(HUShr);
2561};
2562
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002563class HAnd : public HBinaryOperation {
2564 public:
2565 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2566 : HBinaryOperation(result_type, left, right) {}
2567
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002568 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002569
2570 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
2571 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
2572
2573 DECLARE_INSTRUCTION(And);
2574
2575 private:
2576 DISALLOW_COPY_AND_ASSIGN(HAnd);
2577};
2578
2579class HOr : public HBinaryOperation {
2580 public:
2581 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2582 : HBinaryOperation(result_type, left, right) {}
2583
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002584 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002585
2586 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
2587 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
2588
2589 DECLARE_INSTRUCTION(Or);
2590
2591 private:
2592 DISALLOW_COPY_AND_ASSIGN(HOr);
2593};
2594
2595class HXor : public HBinaryOperation {
2596 public:
2597 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2598 : HBinaryOperation(result_type, left, right) {}
2599
Mingyao Yangdc5ac732015-02-25 11:28:05 -08002600 bool IsCommutative() const OVERRIDE { return true; }
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002601
2602 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
2603 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
2604
2605 DECLARE_INSTRUCTION(Xor);
2606
2607 private:
2608 DISALLOW_COPY_AND_ASSIGN(HXor);
2609};
2610
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002611// The value of a parameter in this method. Its location depends on
2612// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07002613class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002614 public:
Calin Juravle10e244f2015-01-26 18:54:32 +00002615 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
2616 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002617
2618 uint8_t GetIndex() const { return index_; }
2619
Calin Juravle10e244f2015-01-26 18:54:32 +00002620 bool CanBeNull() const OVERRIDE { return !is_this_; }
2621
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002622 DECLARE_INSTRUCTION(ParameterValue);
2623
2624 private:
2625 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00002626 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002627 const uint8_t index_;
2628
Calin Juravle10e244f2015-01-26 18:54:32 +00002629 // Whether or not the parameter value corresponds to 'this' argument.
2630 const bool is_this_;
2631
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002632 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
2633};
2634
Roland Levillain1cc5f252014-10-22 18:06:21 +01002635class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002636 public:
Roland Levillain1cc5f252014-10-22 18:06:21 +01002637 explicit HNot(Primitive::Type result_type, HInstruction* input)
2638 : HUnaryOperation(result_type, input) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002639
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002640 bool CanBeMoved() const OVERRIDE { return true; }
2641 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002642 UNUSED(other);
2643 return true;
2644 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002645
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002646 int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
2647 int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
Roland Levillain1cc5f252014-10-22 18:06:21 +01002648
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002649 DECLARE_INSTRUCTION(Not);
2650
2651 private:
2652 DISALLOW_COPY_AND_ASSIGN(HNot);
2653};
2654
Roland Levillaindff1f282014-11-05 14:15:05 +00002655class HTypeConversion : public HExpression<1> {
2656 public:
2657 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00002658 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
2659 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00002660 SetRawInputAt(0, input);
2661 DCHECK_NE(input->GetType(), result_type);
2662 }
2663
2664 HInstruction* GetInput() const { return InputAt(0); }
2665 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
2666 Primitive::Type GetResultType() const { return GetType(); }
2667
Roland Levillain624279f2014-12-04 11:54:28 +00002668 // Required by the x86 and ARM code generators when producing calls
2669 // to the runtime.
2670 uint32_t GetDexPc() const { return dex_pc_; }
2671
Roland Levillaindff1f282014-11-05 14:15:05 +00002672 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00002673 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00002674
2675 DECLARE_INSTRUCTION(TypeConversion);
2676
2677 private:
Roland Levillain624279f2014-12-04 11:54:28 +00002678 const uint32_t dex_pc_;
2679
Roland Levillaindff1f282014-11-05 14:15:05 +00002680 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
2681};
2682
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00002683static constexpr uint32_t kNoRegNumber = -1;
2684
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002685class HPhi : public HInstruction {
2686 public:
2687 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002688 : HInstruction(SideEffects::None()),
2689 inputs_(arena, number_of_inputs),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002690 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002691 type_(type),
Calin Juravle10e244f2015-01-26 18:54:32 +00002692 is_live_(false),
2693 can_be_null_(true) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002694 inputs_.SetSize(number_of_inputs);
2695 }
2696
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +00002697 // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
2698 static Primitive::Type ToPhiType(Primitive::Type type) {
2699 switch (type) {
2700 case Primitive::kPrimBoolean:
2701 case Primitive::kPrimByte:
2702 case Primitive::kPrimShort:
2703 case Primitive::kPrimChar:
2704 return Primitive::kPrimInt;
2705 default:
2706 return type;
2707 }
2708 }
2709
Calin Juravle10e244f2015-01-26 18:54:32 +00002710 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002711
2712 void AddInput(HInstruction* input);
2713
Calin Juravle10e244f2015-01-26 18:54:32 +00002714 Primitive::Type GetType() const OVERRIDE { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002715 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002716
Calin Juravle10e244f2015-01-26 18:54:32 +00002717 bool CanBeNull() const OVERRIDE { return can_be_null_; }
2718 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
2719
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002720 uint32_t GetRegNumber() const { return reg_number_; }
2721
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002722 void SetDead() { is_live_ = false; }
2723 void SetLive() { is_live_ = true; }
2724 bool IsDead() const { return !is_live_; }
2725 bool IsLive() const { return is_live_; }
2726
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002727 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002728
David Brazdil1abb4192015-02-17 18:33:36 +00002729 protected:
2730 const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
2731
2732 void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2733 inputs_.Put(index, input);
2734 }
2735
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002736 private:
David Brazdil1abb4192015-02-17 18:33:36 +00002737 GrowableArray<HUserRecord<HInstruction*> > inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002738 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002739 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002740 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00002741 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002742
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002743 DISALLOW_COPY_AND_ASSIGN(HPhi);
2744};
2745
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002746class HNullCheck : public HExpression<1> {
2747 public:
2748 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002749 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002750 SetRawInputAt(0, value);
2751 }
2752
Calin Juravle10e244f2015-01-26 18:54:32 +00002753 bool CanBeMoved() const OVERRIDE { return true; }
2754 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002755 UNUSED(other);
2756 return true;
2757 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002758
Calin Juravle10e244f2015-01-26 18:54:32 +00002759 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002760
Calin Juravle10e244f2015-01-26 18:54:32 +00002761 bool CanThrow() const OVERRIDE { return true; }
2762
2763 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01002764
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002765 uint32_t GetDexPc() const { return dex_pc_; }
2766
2767 DECLARE_INSTRUCTION(NullCheck);
2768
2769 private:
2770 const uint32_t dex_pc_;
2771
2772 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
2773};
2774
2775class FieldInfo : public ValueObject {
2776 public:
Calin Juravle52c48962014-12-16 17:02:57 +00002777 FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
2778 : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002779
2780 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002781 Primitive::Type GetFieldType() const { return field_type_; }
Calin Juravle52c48962014-12-16 17:02:57 +00002782 bool IsVolatile() const { return is_volatile_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002783
2784 private:
2785 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01002786 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00002787 const bool is_volatile_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002788};
2789
2790class HInstanceFieldGet : public HExpression<1> {
2791 public:
2792 HInstanceFieldGet(HInstruction* value,
2793 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002794 MemberOffset field_offset,
2795 bool is_volatile)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002796 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002797 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002798 SetRawInputAt(0, value);
2799 }
2800
Calin Juravle10c9cbe2014-12-19 10:50:19 +00002801 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002802
2803 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2804 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
2805 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002806 }
2807
Calin Juravle77520bc2015-01-12 18:45:46 +00002808 bool CanDoImplicitNullCheck() const OVERRIDE {
2809 return GetFieldOffset().Uint32Value() < kPageSize;
2810 }
2811
2812 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002813 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
2814 }
2815
Calin Juravle52c48962014-12-16 17:02:57 +00002816 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002817 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002818 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002819 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002820
2821 DECLARE_INSTRUCTION(InstanceFieldGet);
2822
2823 private:
2824 const FieldInfo field_info_;
2825
2826 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
2827};
2828
2829class HInstanceFieldSet : public HTemplateInstruction<2> {
2830 public:
2831 HInstanceFieldSet(HInstruction* object,
2832 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01002833 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002834 MemberOffset field_offset,
2835 bool is_volatile)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002836 : HTemplateInstruction(SideEffects::ChangesSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002837 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002838 SetRawInputAt(0, object);
2839 SetRawInputAt(1, value);
2840 }
2841
Calin Juravle77520bc2015-01-12 18:45:46 +00002842 bool CanDoImplicitNullCheck() const OVERRIDE {
2843 return GetFieldOffset().Uint32Value() < kPageSize;
2844 }
2845
Calin Juravle52c48962014-12-16 17:02:57 +00002846 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002847 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002848 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002849 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002850 HInstruction* GetValue() const { return InputAt(1); }
2851
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002852 DECLARE_INSTRUCTION(InstanceFieldSet);
2853
2854 private:
2855 const FieldInfo field_info_;
2856
2857 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
2858};
2859
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002860class HArrayGet : public HExpression<2> {
2861 public:
2862 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002863 : HExpression(type, SideEffects::DependsOnSomething()) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002864 SetRawInputAt(0, array);
2865 SetRawInputAt(1, index);
2866 }
2867
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002868 bool CanBeMoved() const OVERRIDE { return true; }
2869 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002870 UNUSED(other);
2871 return true;
2872 }
Calin Juravle77520bc2015-01-12 18:45:46 +00002873 bool CanDoImplicitNullCheck() const OVERRIDE {
2874 // TODO: We can be smarter here.
2875 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
2876 // which generates the implicit null check. There are cases when these can be removed
2877 // to produce better code. If we ever add optimizations to do so we should allow an
2878 // implicit check here (as long as the address falls in the first page).
2879 return false;
2880 }
2881
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002882 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002883
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002884 HInstruction* GetArray() const { return InputAt(0); }
2885 HInstruction* GetIndex() const { return InputAt(1); }
2886
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002887 DECLARE_INSTRUCTION(ArrayGet);
2888
2889 private:
2890 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
2891};
2892
2893class HArraySet : public HTemplateInstruction<3> {
2894 public:
2895 HArraySet(HInstruction* array,
2896 HInstruction* index,
2897 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002898 Primitive::Type expected_component_type,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002899 uint32_t dex_pc)
2900 : HTemplateInstruction(SideEffects::ChangesSomething()),
2901 dex_pc_(dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002902 expected_component_type_(expected_component_type),
2903 needs_type_check_(value->GetType() == Primitive::kPrimNot) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002904 SetRawInputAt(0, array);
2905 SetRawInputAt(1, index);
2906 SetRawInputAt(2, value);
2907 }
2908
Calin Juravle77520bc2015-01-12 18:45:46 +00002909 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002910 // We currently always call a runtime method to catch array store
2911 // exceptions.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002912 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002913 }
2914
Calin Juravle77520bc2015-01-12 18:45:46 +00002915 bool CanDoImplicitNullCheck() const OVERRIDE {
2916 // TODO: Same as for ArrayGet.
2917 return false;
2918 }
2919
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002920 void ClearNeedsTypeCheck() {
2921 needs_type_check_ = false;
2922 }
2923
2924 bool NeedsTypeCheck() const { return needs_type_check_; }
2925
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002926 uint32_t GetDexPc() const { return dex_pc_; }
2927
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002928 HInstruction* GetArray() const { return InputAt(0); }
2929 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002930 HInstruction* GetValue() const { return InputAt(2); }
2931
2932 Primitive::Type GetComponentType() const {
2933 // The Dex format does not type floating point index operations. Since the
2934 // `expected_component_type_` is set during building and can therefore not
2935 // be correct, we also check what is the value type. If it is a floating
2936 // point type, we must use that type.
2937 Primitive::Type value_type = GetValue()->GetType();
2938 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
2939 ? value_type
2940 : expected_component_type_;
2941 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002942
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002943 DECLARE_INSTRUCTION(ArraySet);
2944
2945 private:
2946 const uint32_t dex_pc_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002947 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002948 bool needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002949
2950 DISALLOW_COPY_AND_ASSIGN(HArraySet);
2951};
2952
2953class HArrayLength : public HExpression<1> {
2954 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002955 explicit HArrayLength(HInstruction* array)
2956 : HExpression(Primitive::kPrimInt, SideEffects::None()) {
2957 // Note that arrays do not change length, so the instruction does not
2958 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002959 SetRawInputAt(0, array);
2960 }
2961
Calin Juravle77520bc2015-01-12 18:45:46 +00002962 bool CanBeMoved() const OVERRIDE { return true; }
2963 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002964 UNUSED(other);
2965 return true;
2966 }
Calin Juravle77520bc2015-01-12 18:45:46 +00002967 bool CanDoImplicitNullCheck() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002968
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002969 DECLARE_INSTRUCTION(ArrayLength);
2970
2971 private:
2972 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
2973};
2974
2975class HBoundsCheck : public HExpression<2> {
2976 public:
2977 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002978 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002979 DCHECK(index->GetType() == Primitive::kPrimInt);
2980 SetRawInputAt(0, index);
2981 SetRawInputAt(1, length);
2982 }
2983
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002984 bool CanBeMoved() const OVERRIDE { return true; }
2985 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002986 UNUSED(other);
2987 return true;
2988 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002989
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002990 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002991
Alexandre Rames2ed20af2015-03-06 13:55:35 +00002992 bool CanThrow() const OVERRIDE { return true; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01002993
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002994 uint32_t GetDexPc() const { return dex_pc_; }
2995
2996 DECLARE_INSTRUCTION(BoundsCheck);
2997
2998 private:
2999 const uint32_t dex_pc_;
3000
3001 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
3002};
3003
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003004/**
3005 * Some DEX instructions are folded into multiple HInstructions that need
3006 * to stay live until the last HInstruction. This class
3007 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00003008 * HInstruction stays live. `index` represents the stack location index of the
3009 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003010 */
3011class HTemporary : public HTemplateInstruction<0> {
3012 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003013 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003014
3015 size_t GetIndex() const { return index_; }
3016
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00003017 Primitive::Type GetType() const OVERRIDE {
3018 // The previous instruction is the one that will be stored in the temporary location.
3019 DCHECK(GetPrevious() != nullptr);
3020 return GetPrevious()->GetType();
3021 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00003022
Nicolas Geoffraye5038322014-07-04 09:41:32 +01003023 DECLARE_INSTRUCTION(Temporary);
3024
3025 private:
3026 const size_t index_;
3027
3028 DISALLOW_COPY_AND_ASSIGN(HTemporary);
3029};
3030
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003031class HSuspendCheck : public HTemplateInstruction<0> {
3032 public:
3033 explicit HSuspendCheck(uint32_t dex_pc)
Nicolas Geoffray9ebc72c2014-09-25 16:33:42 +01003034 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003035
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003036 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00003037 return true;
3038 }
3039
3040 uint32_t GetDexPc() const { return dex_pc_; }
3041
3042 DECLARE_INSTRUCTION(SuspendCheck);
3043
3044 private:
3045 const uint32_t dex_pc_;
3046
3047 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
3048};
3049
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003050/**
3051 * Instruction to load a Class object.
3052 */
3053class HLoadClass : public HExpression<0> {
3054 public:
3055 HLoadClass(uint16_t type_index,
3056 bool is_referrers_class,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003057 uint32_t dex_pc)
3058 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3059 type_index_(type_index),
3060 is_referrers_class_(is_referrers_class),
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003061 dex_pc_(dex_pc),
Calin Juravleb1498f62015-02-16 13:13:29 +00003062 generate_clinit_check_(false),
3063 loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003064
3065 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003066
3067 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3068 return other->AsLoadClass()->type_index_ == type_index_;
3069 }
3070
3071 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
3072
3073 uint32_t GetDexPc() const { return dex_pc_; }
3074 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003075 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003076
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003077 bool NeedsEnvironment() const OVERRIDE {
3078 // Will call runtime and load the class if the class is not loaded yet.
3079 // TODO: finer grain decision.
3080 return !is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003081 }
3082
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003083 bool MustGenerateClinitCheck() const {
3084 return generate_clinit_check_;
3085 }
3086
3087 void SetMustGenerateClinitCheck() {
3088 generate_clinit_check_ = true;
3089 }
3090
3091 bool CanCallRuntime() const {
3092 return MustGenerateClinitCheck() || !is_referrers_class_;
3093 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003094
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003095 bool CanThrow() const OVERRIDE {
3096 // May call runtime and and therefore can throw.
3097 // TODO: finer grain decision.
3098 return !is_referrers_class_;
3099 }
3100
Calin Juravleacf735c2015-02-12 15:25:22 +00003101 ReferenceTypeInfo GetLoadedClassRTI() {
3102 return loaded_class_rti_;
3103 }
3104
3105 void SetLoadedClassRTI(ReferenceTypeInfo rti) {
3106 // Make sure we only set exact types (the loaded class should never be merged).
3107 DCHECK(rti.IsExact());
3108 loaded_class_rti_ = rti;
3109 }
3110
3111 bool IsResolved() {
3112 return loaded_class_rti_.IsExact();
3113 }
3114
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003115 bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
3116
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003117 DECLARE_INSTRUCTION(LoadClass);
3118
3119 private:
3120 const uint16_t type_index_;
3121 const bool is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003122 const uint32_t dex_pc_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003123 // Whether this instruction must generate the initialization check.
3124 // Used for code generation.
3125 bool generate_clinit_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003126
Calin Juravleacf735c2015-02-12 15:25:22 +00003127 ReferenceTypeInfo loaded_class_rti_;
3128
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003129 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
3130};
3131
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003132class HLoadString : public HExpression<0> {
3133 public:
3134 HLoadString(uint32_t string_index, uint32_t dex_pc)
3135 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3136 string_index_(string_index),
3137 dex_pc_(dex_pc) {}
3138
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003139 bool CanBeMoved() const OVERRIDE { return true; }
3140
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003141 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3142 return other->AsLoadString()->string_index_ == string_index_;
3143 }
3144
3145 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
3146
3147 uint32_t GetDexPc() const { return dex_pc_; }
3148 uint32_t GetStringIndex() const { return string_index_; }
3149
3150 // TODO: Can we deopt or debug when we resolve a string?
3151 bool NeedsEnvironment() const OVERRIDE { return false; }
Nicolas Geoffray9437b782015-03-25 10:08:51 +00003152 bool NeedsDexCache() const OVERRIDE { return true; }
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00003153
3154 DECLARE_INSTRUCTION(LoadString);
3155
3156 private:
3157 const uint32_t string_index_;
3158 const uint32_t dex_pc_;
3159
3160 DISALLOW_COPY_AND_ASSIGN(HLoadString);
3161};
3162
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00003163// TODO: Pass this check to HInvokeStaticOrDirect nodes.
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003164/**
3165 * Performs an initialization check on its Class object input.
3166 */
3167class HClinitCheck : public HExpression<1> {
3168 public:
3169 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
Nicolas Geoffraya0466e12015-03-27 15:00:40 +00003170 : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()),
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003171 dex_pc_(dex_pc) {
3172 SetRawInputAt(0, constant);
3173 }
3174
Nicolas Geoffray424f6762014-11-03 14:51:25 +00003175 bool CanBeMoved() const OVERRIDE { return true; }
3176 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3177 UNUSED(other);
3178 return true;
3179 }
3180
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003181 bool NeedsEnvironment() const OVERRIDE {
3182 // May call runtime to initialize the class.
3183 return true;
3184 }
3185
3186 uint32_t GetDexPc() const { return dex_pc_; }
3187
3188 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
3189
3190 DECLARE_INSTRUCTION(ClinitCheck);
3191
3192 private:
3193 const uint32_t dex_pc_;
3194
3195 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
3196};
3197
3198class HStaticFieldGet : public HExpression<1> {
3199 public:
3200 HStaticFieldGet(HInstruction* cls,
3201 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003202 MemberOffset field_offset,
3203 bool is_volatile)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003204 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00003205 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003206 SetRawInputAt(0, cls);
3207 }
3208
Calin Juravle52c48962014-12-16 17:02:57 +00003209
Calin Juravle10c9cbe2014-12-19 10:50:19 +00003210 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003211
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003212 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00003213 HStaticFieldGet* other_get = other->AsStaticFieldGet();
3214 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003215 }
3216
3217 size_t ComputeHashCode() const OVERRIDE {
3218 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3219 }
3220
Calin Juravle52c48962014-12-16 17:02:57 +00003221 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003222 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3223 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003224 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003225
3226 DECLARE_INSTRUCTION(StaticFieldGet);
3227
3228 private:
3229 const FieldInfo field_info_;
3230
3231 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
3232};
3233
3234class HStaticFieldSet : public HTemplateInstruction<2> {
3235 public:
3236 HStaticFieldSet(HInstruction* cls,
3237 HInstruction* value,
3238 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00003239 MemberOffset field_offset,
3240 bool is_volatile)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003241 : HTemplateInstruction(SideEffects::ChangesSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00003242 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003243 SetRawInputAt(0, cls);
3244 SetRawInputAt(1, value);
3245 }
3246
Calin Juravle52c48962014-12-16 17:02:57 +00003247 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003248 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
3249 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00003250 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003251
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00003252 HInstruction* GetValue() const { return InputAt(1); }
3253
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01003254 DECLARE_INSTRUCTION(StaticFieldSet);
3255
3256 private:
3257 const FieldInfo field_info_;
3258
3259 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
3260};
3261
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003262// Implement the move-exception DEX instruction.
3263class HLoadException : public HExpression<0> {
3264 public:
3265 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
3266
3267 DECLARE_INSTRUCTION(LoadException);
3268
3269 private:
3270 DISALLOW_COPY_AND_ASSIGN(HLoadException);
3271};
3272
3273class HThrow : public HTemplateInstruction<1> {
3274 public:
3275 HThrow(HInstruction* exception, uint32_t dex_pc)
3276 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
3277 SetRawInputAt(0, exception);
3278 }
3279
3280 bool IsControlFlow() const OVERRIDE { return true; }
3281
3282 bool NeedsEnvironment() const OVERRIDE { return true; }
3283
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003284 bool CanThrow() const OVERRIDE { return true; }
3285
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003286 uint32_t GetDexPc() const { return dex_pc_; }
3287
3288 DECLARE_INSTRUCTION(Throw);
3289
3290 private:
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003291 const uint32_t dex_pc_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00003292
3293 DISALLOW_COPY_AND_ASSIGN(HThrow);
3294};
3295
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003296class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003297 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003298 HInstanceOf(HInstruction* object,
3299 HLoadClass* constant,
3300 bool class_is_final,
3301 uint32_t dex_pc)
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003302 : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
3303 class_is_final_(class_is_final),
3304 dex_pc_(dex_pc) {
3305 SetRawInputAt(0, object);
3306 SetRawInputAt(1, constant);
3307 }
3308
3309 bool CanBeMoved() const OVERRIDE { return true; }
3310
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003311 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003312 return true;
3313 }
3314
3315 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003316 return false;
3317 }
3318
3319 uint32_t GetDexPc() const { return dex_pc_; }
3320
3321 bool IsClassFinal() const { return class_is_final_; }
3322
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003323 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003324
3325 private:
3326 const bool class_is_final_;
3327 const uint32_t dex_pc_;
3328
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003329 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
3330};
3331
Calin Juravleb1498f62015-02-16 13:13:29 +00003332class HBoundType : public HExpression<1> {
3333 public:
3334 HBoundType(HInstruction* input, ReferenceTypeInfo bound_type)
3335 : HExpression(Primitive::kPrimNot, SideEffects::None()),
3336 bound_type_(bound_type) {
Calin Juravle61d544b2015-02-23 16:46:57 +00003337 DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
Calin Juravleb1498f62015-02-16 13:13:29 +00003338 SetRawInputAt(0, input);
3339 }
3340
3341 const ReferenceTypeInfo& GetBoundType() const { return bound_type_; }
3342
3343 bool CanBeNull() const OVERRIDE {
3344 // `null instanceof ClassX` always return false so we can't be null.
3345 return false;
3346 }
3347
3348 DECLARE_INSTRUCTION(BoundType);
3349
3350 private:
3351 // Encodes the most upper class that this instruction can have. In other words
3352 // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()).
3353 // It is used to bound the type in cases like `if (x instanceof ClassX) {}`
3354 const ReferenceTypeInfo bound_type_;
3355
3356 DISALLOW_COPY_AND_ASSIGN(HBoundType);
3357};
3358
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00003359class HCheckCast : public HTemplateInstruction<2> {
3360 public:
3361 HCheckCast(HInstruction* object,
3362 HLoadClass* constant,
3363 bool class_is_final,
3364 uint32_t dex_pc)
3365 : HTemplateInstruction(SideEffects::None()),
3366 class_is_final_(class_is_final),
3367 dex_pc_(dex_pc) {
3368 SetRawInputAt(0, object);
3369 SetRawInputAt(1, constant);
3370 }
3371
3372 bool CanBeMoved() const OVERRIDE { return true; }
3373
3374 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3375 return true;
3376 }
3377
3378 bool NeedsEnvironment() const OVERRIDE {
3379 // Instruction may throw a CheckCastError.
3380 return true;
3381 }
3382
3383 bool CanThrow() const OVERRIDE { return true; }
3384
3385 uint32_t GetDexPc() const { return dex_pc_; }
3386
3387 bool IsClassFinal() const { return class_is_final_; }
3388
3389 DECLARE_INSTRUCTION(CheckCast);
3390
3391 private:
3392 const bool class_is_final_;
3393 const uint32_t dex_pc_;
3394
3395 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00003396};
3397
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003398class HMonitorOperation : public HTemplateInstruction<1> {
3399 public:
3400 enum OperationKind {
3401 kEnter,
3402 kExit,
3403 };
3404
3405 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
3406 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
3407 SetRawInputAt(0, object);
3408 }
3409
3410 // Instruction may throw a Java exception, so we need an environment.
3411 bool NeedsEnvironment() const OVERRIDE { return true; }
3412 bool CanThrow() const OVERRIDE { return true; }
3413
3414 uint32_t GetDexPc() const { return dex_pc_; }
3415
3416 bool IsEnter() const { return kind_ == kEnter; }
3417
3418 DECLARE_INSTRUCTION(MonitorOperation);
3419
Calin Juravle52c48962014-12-16 17:02:57 +00003420 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00003421 const OperationKind kind_;
3422 const uint32_t dex_pc_;
3423
3424 private:
3425 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
3426};
3427
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003428class MoveOperands : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003429 public:
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003430 MoveOperands(Location source, Location destination, HInstruction* instruction)
3431 : source_(source), destination_(destination), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003432
3433 Location GetSource() const { return source_; }
3434 Location GetDestination() const { return destination_; }
3435
3436 void SetSource(Location value) { source_ = value; }
3437 void SetDestination(Location value) { destination_ = value; }
3438
3439 // The parallel move resolver marks moves as "in-progress" by clearing the
3440 // destination (but not the source).
3441 Location MarkPending() {
3442 DCHECK(!IsPending());
3443 Location dest = destination_;
3444 destination_ = Location::NoLocation();
3445 return dest;
3446 }
3447
3448 void ClearPending(Location dest) {
3449 DCHECK(IsPending());
3450 destination_ = dest;
3451 }
3452
3453 bool IsPending() const {
3454 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3455 return destination_.IsInvalid() && !source_.IsInvalid();
3456 }
3457
3458 // True if this blocks a move from the given location.
3459 bool Blocks(Location loc) const {
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003460 return !IsEliminated() && (source_.Contains(loc) || loc.Contains(source_));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003461 }
3462
3463 // A move is redundant if it's been eliminated, if its source and
3464 // destination are the same, or if its destination is unneeded.
3465 bool IsRedundant() const {
3466 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
3467 }
3468
3469 // We clear both operands to indicate move that's been eliminated.
3470 void Eliminate() {
3471 source_ = destination_ = Location::NoLocation();
3472 }
3473
3474 bool IsEliminated() const {
3475 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3476 return source_.IsInvalid();
3477 }
3478
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003479 HInstruction* GetInstruction() const { return instruction_; }
3480
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003481 private:
3482 Location source_;
3483 Location destination_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003484 // The instruction this move is assocatied with. Null when this move is
3485 // for moving an input in the expected locations of user (including a phi user).
3486 // This is only used in debug mode, to ensure we do not connect interval siblings
3487 // in the same parallel move.
3488 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003489};
3490
3491static constexpr size_t kDefaultNumberOfMoves = 4;
3492
3493class HParallelMove : public HTemplateInstruction<0> {
3494 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003495 explicit HParallelMove(ArenaAllocator* arena)
3496 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003497
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003498 void AddMove(Location source, Location destination, HInstruction* instruction) {
3499 DCHECK(source.IsValid());
3500 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003501 if (kIsDebugBuild) {
3502 if (instruction != nullptr) {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00003503 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Nicolas Geoffray234d69d2015-03-09 10:28:50 +00003504 if (moves_.Get(i).GetInstruction() == instruction) {
3505 // Special case the situation where the move is for the spill slot
3506 // of the instruction.
3507 if ((GetPrevious() == instruction)
3508 || ((GetPrevious() == nullptr)
3509 && instruction->IsPhi()
3510 && instruction->GetBlock() == GetBlock())) {
3511 DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind())
3512 << "Doing parallel moves for the same instruction.";
3513 } else {
3514 DCHECK(false) << "Doing parallel moves for the same instruction.";
3515 }
3516 }
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00003517 }
3518 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003519 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
3520 DCHECK(!destination.Equals(moves_.Get(i).GetDestination()))
3521 << "Same destination for two moves in a parallel move.";
3522 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003523 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003524 moves_.Add(MoveOperands(source, destination, instruction));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003525 }
3526
3527 MoveOperands* MoveOperandsAt(size_t index) const {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003528 return moves_.GetRawStorage() + index;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003529 }
3530
3531 size_t NumMoves() const { return moves_.Size(); }
3532
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003533 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003534
3535 private:
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003536 GrowableArray<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003537
3538 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
3539};
3540
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003541class HGraphVisitor : public ValueObject {
3542 public:
Dave Allison20dfc792014-06-16 20:44:29 -07003543 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
3544 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003545
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003546 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003547 virtual void VisitBasicBlock(HBasicBlock* block);
3548
Roland Levillain633021e2014-10-01 14:12:25 +01003549 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003550 void VisitInsertionOrder();
3551
Roland Levillain633021e2014-10-01 14:12:25 +01003552 // Visit the graph following dominator tree reverse post-order.
3553 void VisitReversePostOrder();
3554
Nicolas Geoffray787c3072014-03-17 10:20:19 +00003555 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00003556
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003557 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003558#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003559 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
3560
3561 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3562
3563#undef DECLARE_VISIT_INSTRUCTION
3564
3565 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07003566 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003567
3568 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
3569};
3570
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003571class HGraphDelegateVisitor : public HGraphVisitor {
3572 public:
3573 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
3574 virtual ~HGraphDelegateVisitor() {}
3575
3576 // Visit functions that delegate to to super class.
3577#define DECLARE_VISIT_INSTRUCTION(name, super) \
Alexandre Rames2ed20af2015-03-06 13:55:35 +00003578 void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003579
3580 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3581
3582#undef DECLARE_VISIT_INSTRUCTION
3583
3584 private:
3585 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
3586};
3587
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003588class HInsertionOrderIterator : public ValueObject {
3589 public:
3590 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
3591
3592 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
3593 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
3594 void Advance() { ++index_; }
3595
3596 private:
3597 const HGraph& graph_;
3598 size_t index_;
3599
3600 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
3601};
3602
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003603class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003604 public:
David Brazdil10f56cb2015-03-24 18:49:14 +00003605 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
3606 // Check that reverse post order of the graph has been built.
3607 DCHECK(!graph.GetReversePostOrder().IsEmpty());
3608 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003609
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003610 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
3611 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003612 void Advance() { ++index_; }
3613
3614 private:
3615 const HGraph& graph_;
3616 size_t index_;
3617
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003618 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003619};
3620
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003621class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003622 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003623 explicit HPostOrderIterator(const HGraph& graph)
David Brazdil10f56cb2015-03-24 18:49:14 +00003624 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {
3625 // Check that reverse post order of the graph has been built.
3626 DCHECK(!graph.GetReversePostOrder().IsEmpty());
3627 }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003628
3629 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003630 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003631 void Advance() { --index_; }
3632
3633 private:
3634 const HGraph& graph_;
3635 size_t index_;
3636
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003637 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003638};
3639
Nicolas Geoffray0d9f17d2015-04-15 14:17:44 +01003640class HLinearPostOrderIterator : public ValueObject {
3641 public:
3642 explicit HLinearPostOrderIterator(const HGraph& graph)
3643 : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {}
3644
3645 bool Done() const { return index_ == 0; }
3646
3647 HBasicBlock* Current() const { return order_.Get(index_ -1); }
3648
3649 void Advance() {
3650 --index_;
3651 DCHECK_GE(index_, 0U);
3652 }
3653
3654 private:
3655 const GrowableArray<HBasicBlock*>& order_;
3656 size_t index_;
3657
3658 DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
3659};
3660
3661class HLinearOrderIterator : public ValueObject {
3662 public:
3663 explicit HLinearOrderIterator(const HGraph& graph)
3664 : order_(graph.GetLinearOrder()), index_(0) {}
3665
3666 bool Done() const { return index_ == order_.Size(); }
3667 HBasicBlock* Current() const { return order_.Get(index_); }
3668 void Advance() { ++index_; }
3669
3670 private:
3671 const GrowableArray<HBasicBlock*>& order_;
3672 size_t index_;
3673
3674 DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
3675};
3676
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003677// Iterator over the blocks that art part of the loop. Includes blocks part
3678// of an inner loop. The order in which the blocks are iterated is on their
3679// block id.
3680class HBlocksInLoopIterator : public ValueObject {
3681 public:
3682 explicit HBlocksInLoopIterator(const HLoopInformation& info)
3683 : blocks_in_loop_(info.GetBlocks()),
3684 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
3685 index_(0) {
3686 if (!blocks_in_loop_.IsBitSet(index_)) {
3687 Advance();
3688 }
3689 }
3690
3691 bool Done() const { return index_ == blocks_.Size(); }
3692 HBasicBlock* Current() const { return blocks_.Get(index_); }
3693 void Advance() {
3694 ++index_;
3695 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
3696 if (blocks_in_loop_.IsBitSet(index_)) {
3697 break;
3698 }
3699 }
3700 }
3701
3702 private:
3703 const BitVector& blocks_in_loop_;
3704 const GrowableArray<HBasicBlock*>& blocks_;
3705 size_t index_;
3706
3707 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
3708};
3709
Alexandre Ramesb2fd7bc2015-03-11 16:48:16 +00003710inline int64_t Int64FromConstant(HConstant* constant) {
3711 DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
3712 return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
3713 : constant->AsLongConstant()->GetValue();
3714}
3715
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003716} // namespace art
3717
3718#endif // ART_COMPILER_OPTIMIZING_NODES_H_