blob: cebde3bb5c4830978c203a6dfe2f813efbff87b9 [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
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +000020#include "entrypoints/quick/quick_entrypoints_enum.h"
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000021#include "invoke_type.h"
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +010022#include "locations.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010023#include "offsets.h"
Ian Rogerse63db272014-07-15 15:36:11 -070024#include "primitive.h"
Ian Rogers0279ebb2014-10-08 17:27:48 -070025#include "utils/arena_object.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000026#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000027#include "utils/growable_array.h"
28
29namespace art {
30
31class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010032class HEnvironment;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000033class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000034class HIntConstant;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000035class HInvoke;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000036class HGraphVisitor;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +000037class HNullConstant;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010038class HPhi;
Nicolas Geoffray3c049742014-09-24 18:10:46 +010039class HSuspendCheck;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010040class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000041class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000042
43static const int kDefaultNumberOfBlocks = 8;
44static const int kDefaultNumberOfSuccessors = 2;
45static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010046static const int kDefaultNumberOfDominatedBlocks = 1;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000047static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000048
Calin Juravle9aec02f2014-11-18 23:06:35 +000049static constexpr uint32_t kMaxIntShiftValue = 0x1f;
50static constexpr uint64_t kMaxLongShiftValue = 0x3f;
51
Dave Allison20dfc792014-06-16 20:44:29 -070052enum IfCondition {
53 kCondEQ,
54 kCondNE,
55 kCondLT,
56 kCondLE,
57 kCondGT,
58 kCondGE,
59};
60
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010061class HInstructionList {
62 public:
63 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
64
65 void AddInstruction(HInstruction* instruction);
66 void RemoveInstruction(HInstruction* instruction);
67
Roland Levillain6b469232014-09-25 10:10:38 +010068 // Return true if this list contains `instruction`.
69 bool Contains(HInstruction* instruction) const;
70
Roland Levillainccc07a92014-09-16 14:48:16 +010071 // Return true if `instruction1` is found before `instruction2` in
72 // this instruction list and false otherwise. Abort if none
73 // of these instructions is found.
74 bool FoundBefore(const HInstruction* instruction1,
75 const HInstruction* instruction2) const;
76
Nicolas Geoffray276d9da2015-02-02 18:24:11 +000077 bool IsEmpty() const { return first_instruction_ == nullptr; }
78 void Clear() { first_instruction_ = last_instruction_ = nullptr; }
79
80 // Update the block of all instructions to be `block`.
81 void SetBlockOfInstructions(HBasicBlock* block) const;
82
83 void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
84 void Add(const HInstructionList& instruction_list);
85
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010086 private:
87 HInstruction* first_instruction_;
88 HInstruction* last_instruction_;
89
90 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000091 friend class HGraph;
92 friend class HInstruction;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010093 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +010094 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010095
96 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
97};
98
Nicolas Geoffray818f2102014-02-18 16:43:35 +000099// Control-flow graph of a method. Contains a list of basic blocks.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700100class HGraph : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000101 public:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000102 HGraph(ArenaAllocator* arena, int start_instruction_id = 0)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000103 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000104 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100105 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700106 entry_block_(nullptr),
107 exit_block_(nullptr),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100108 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100109 number_of_vregs_(0),
110 number_of_in_vregs_(0),
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000111 temporaries_vreg_slots_(0),
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000112 current_instruction_id_(start_instruction_id) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000113
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000114 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100115 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Roland Levillain93445682014-10-06 19:24:02 +0100116 HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000117
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000118 HBasicBlock* GetEntryBlock() const { return entry_block_; }
119 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000120
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000121 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
122 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000123
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000124 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100125
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000126 // Try building the SSA form of this graph, with dominance computation and loop
127 // recognition. Returns whether it was successful in doing all these steps.
128 bool TryBuildingSsa() {
129 BuildDominatorTree();
130 TransformToSsa();
131 return AnalyzeNaturalLoops();
132 }
133
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000134 void BuildDominatorTree();
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000135 void TransformToSsa();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100136 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000137
Nicolas Geoffrayf5370122014-12-02 11:51:19 +0000138 // Analyze all natural loops in this graph. Returns false if one
139 // loop is not natural, that is the header does not dominate the
140 // back edge.
141 bool AnalyzeNaturalLoops() const;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100142
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000143 // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
144 void InlineInto(HGraph* outer_graph, HInvoke* invoke);
145
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100146 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
147 void SimplifyLoop(HBasicBlock* header);
148
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000149 int32_t GetNextInstructionId() {
150 DCHECK_NE(current_instruction_id_, INT32_MAX);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000151 return current_instruction_id_++;
152 }
153
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000154 int32_t GetCurrentInstructionId() const {
155 return current_instruction_id_;
156 }
157
158 void SetCurrentInstructionId(int32_t id) {
159 current_instruction_id_ = id;
160 }
161
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100162 uint16_t GetMaximumNumberOfOutVRegs() const {
163 return maximum_number_of_out_vregs_;
164 }
165
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000166 void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
167 maximum_number_of_out_vregs_ = new_value;
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100168 }
169
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000170 void UpdateTemporariesVRegSlots(size_t slots) {
171 temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100172 }
173
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000174 size_t GetTemporariesVRegSlots() const {
175 return temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100176 }
177
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100178 void SetNumberOfVRegs(uint16_t number_of_vregs) {
179 number_of_vregs_ = number_of_vregs;
180 }
181
182 uint16_t GetNumberOfVRegs() const {
183 return number_of_vregs_;
184 }
185
186 void SetNumberOfInVRegs(uint16_t value) {
187 number_of_in_vregs_ = value;
188 }
189
Nicolas Geoffrayab032bc2014-07-15 12:55:21 +0100190 uint16_t GetNumberOfLocalVRegs() const {
191 return number_of_vregs_ - number_of_in_vregs_;
192 }
193
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100194 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
195 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100196 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100197
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000198 HNullConstant* GetNullConstant();
199
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000200 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000201 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
202 void VisitBlockForDominatorTree(HBasicBlock* block,
203 HBasicBlock* predecessor,
204 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100205 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000206 void VisitBlockForBackEdges(HBasicBlock* block,
207 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100208 ArenaBitVector* visiting);
Roland Levillainfc600dc2014-12-02 17:16:31 +0000209 void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000210 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
Jean Christophe Beyler53d9da82014-12-04 13:28:25 -0800211 void RemoveBlock(HBasicBlock* block) const;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000212
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000213 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000214
215 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000216 GrowableArray<HBasicBlock*> blocks_;
217
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100218 // List of blocks to perform a reverse post order tree traversal.
219 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000220
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000221 HBasicBlock* entry_block_;
222 HBasicBlock* exit_block_;
223
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100224 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100225 uint16_t maximum_number_of_out_vregs_;
226
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100227 // The number of virtual registers in this method. Contains the parameters.
228 uint16_t number_of_vregs_;
229
230 // The number of virtual registers used by parameters of this method.
231 uint16_t number_of_in_vregs_;
232
Calin Juravlef97f9fb2014-11-11 15:38:19 +0000233 // Number of vreg size slots that the temporaries use (used in baseline compiler).
234 size_t temporaries_vreg_slots_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100235
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000236 // The current id to assign to a newly added instruction. See HInstruction.id_.
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000237 int32_t current_instruction_id_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000238
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000239 // Cached null constant that might be created when building SSA form.
240 HNullConstant* cached_null_constant_;
241
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000242 ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000243 DISALLOW_COPY_AND_ASSIGN(HGraph);
244};
245
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700246class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000247 public:
248 HLoopInformation(HBasicBlock* header, HGraph* graph)
249 : header_(header),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100250 suspend_check_(nullptr),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100251 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
Nicolas Geoffrayb09aacb2014-09-17 18:21:53 +0100252 // Make bit vector growable, as the number of blocks may change.
253 blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100254
255 HBasicBlock* GetHeader() const {
256 return header_;
257 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000258
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000259 void SetHeader(HBasicBlock* block) {
260 header_ = block;
261 }
262
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100263 HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
264 void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
265 bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
266
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000267 void AddBackEdge(HBasicBlock* back_edge) {
268 back_edges_.Add(back_edge);
269 }
270
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100271 void RemoveBackEdge(HBasicBlock* back_edge) {
272 back_edges_.Delete(back_edge);
273 }
274
275 bool IsBackEdge(HBasicBlock* block) {
276 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
277 if (back_edges_.Get(i) == block) return true;
278 }
279 return false;
280 }
281
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000282 size_t NumberOfBackEdges() const {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000283 return back_edges_.Size();
284 }
285
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100286 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100287
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100288 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
289 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100290 }
291
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100292 void ClearBackEdges() {
293 back_edges_.Reset();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100294 }
295
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100296 // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
297 // that is the header dominates the back edge.
298 bool Populate();
299
300 // Returns whether this loop information contains `block`.
301 // Note that this loop information *must* be populated before entering this function.
302 bool Contains(const HBasicBlock& block) const;
303
304 // Returns whether this loop information is an inner loop of `other`.
305 // Note that `other` *must* be populated before entering this function.
306 bool IsIn(const HLoopInformation& other) const;
307
308 const ArenaBitVector& GetBlocks() const { return blocks_; }
309
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000310 void Add(HBasicBlock* block);
311
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000312 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100313 // Internal recursive implementation of `Populate`.
314 void PopulateRecursive(HBasicBlock* block);
315
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000316 HBasicBlock* header_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100317 HSuspendCheck* suspend_check_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000318 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100319 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000320
321 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
322};
323
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100324static constexpr size_t kNoLifetime = -1;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100325static constexpr uint32_t kNoDexPc = -1;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100326
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000327// A block in a method. Contains the list of instructions represented
328// as a double linked list. Each block knows its predecessors and
329// successors.
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100330
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700331class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000332 public:
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100333 explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000334 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000335 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
336 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000337 loop_information_(nullptr),
338 dominator_(nullptr),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100339 dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100340 block_id_(-1),
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100341 dex_pc_(dex_pc),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100342 lifetime_start_(kNoLifetime),
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000343 lifetime_end_(kNoLifetime),
344 is_catch_block_(false) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000345
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100346 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
347 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000348 }
349
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100350 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
351 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000352 }
353
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100354 const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
355 return dominated_blocks_;
356 }
357
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100358 bool IsEntryBlock() const {
359 return graph_->GetEntryBlock() == this;
360 }
361
362 bool IsExitBlock() const {
363 return graph_->GetExitBlock() == this;
364 }
365
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000366 void AddBackEdge(HBasicBlock* back_edge) {
367 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000368 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000369 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100370 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000371 loop_information_->AddBackEdge(back_edge);
372 }
373
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000374 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000375 void SetGraph(HGraph* graph) { graph_ = graph; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000376
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000377 int GetBlockId() const { return block_id_; }
378 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000379
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000380 HBasicBlock* GetDominator() const { return dominator_; }
381 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100382 void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000383 void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
384 for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
385 if (dominated_blocks_.Get(i) == existing) {
386 dominated_blocks_.Put(i, new_block);
387 return;
388 }
389 }
390 LOG(FATAL) << "Unreachable";
391 UNREACHABLE();
392 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000393
394 int NumberOfBackEdges() const {
395 return loop_information_ == nullptr
396 ? 0
397 : loop_information_->NumberOfBackEdges();
398 }
399
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100400 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
401 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100402 const HInstructionList& GetInstructions() const { return instructions_; }
403 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100404 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000405
406 void AddSuccessor(HBasicBlock* block) {
407 successors_.Add(block);
408 block->predecessors_.Add(this);
409 }
410
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100411 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
412 size_t successor_index = GetSuccessorIndexOf(existing);
413 DCHECK_NE(successor_index, static_cast<size_t>(-1));
414 existing->RemovePredecessor(this);
415 new_block->predecessors_.Add(this);
416 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000417 }
418
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000419 void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
420 size_t predecessor_index = GetPredecessorIndexOf(existing);
421 DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
422 existing->RemoveSuccessor(this);
423 new_block->successors_.Add(this);
424 predecessors_.Put(predecessor_index, new_block);
425 }
426
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100427 void RemovePredecessor(HBasicBlock* block) {
428 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100429 }
430
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000431 void RemoveSuccessor(HBasicBlock* block) {
432 successors_.Delete(block);
433 }
434
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100435 void ClearAllPredecessors() {
436 predecessors_.Reset();
437 }
438
439 void AddPredecessor(HBasicBlock* block) {
440 predecessors_.Add(block);
441 block->successors_.Add(this);
442 }
443
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100444 void SwapPredecessors() {
Nicolas Geoffrayc83d4412014-09-18 16:46:20 +0100445 DCHECK_EQ(predecessors_.Size(), 2u);
Nicolas Geoffray604c6e42014-09-17 12:08:44 +0100446 HBasicBlock* temp = predecessors_.Get(0);
447 predecessors_.Put(0, predecessors_.Get(1));
448 predecessors_.Put(1, temp);
449 }
450
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100451 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
452 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
453 if (predecessors_.Get(i) == predecessor) {
454 return i;
455 }
456 }
457 return -1;
458 }
459
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100460 size_t GetSuccessorIndexOf(HBasicBlock* successor) {
461 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
462 if (successors_.Get(i) == successor) {
463 return i;
464 }
465 }
466 return -1;
467 }
468
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000469 // Split the block into two blocks just after `cursor`. Returns the newly
470 // created block. Note that this method just updates raw block information,
471 // like predecessors, successors, dominators, and instruction list. It does not
472 // update the graph, reverse post order, loop information, nor make sure the
473 // blocks are consistent (for example ending with a control flow instruction).
474 HBasicBlock* SplitAfter(HInstruction* cursor);
475
476 // Merge `other` at the end of `this`. Successors and dominated blocks of
477 // `other` are changed to be successors and dominated blocks of `this`. Note
478 // that this method does not update the graph, reverse post order, loop
479 // information, nor make sure the blocks are consistent (for example ending
480 // with a control flow instruction).
481 void MergeWith(HBasicBlock* other);
482
483 // Replace `this` with `other`. Predecessors, successors, and dominated blocks
484 // of `this` are moved to `other`.
485 // Note that this method does not update the graph, reverse post order, loop
486 // information, nor make sure the blocks are consistent (for example ending
487 void ReplaceWith(HBasicBlock* other);
488
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000489 void AddInstruction(HInstruction* instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100490 void RemoveInstruction(HInstruction* instruction);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100491 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Roland Levillainccc07a92014-09-16 14:48:16 +0100492 // Replace instruction `initial` with `replacement` within this block.
493 void ReplaceAndRemoveInstructionWith(HInstruction* initial,
494 HInstruction* replacement);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100495 void AddPhi(HPhi* phi);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100496 void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100497 void RemovePhi(HPhi* phi);
498
499 bool IsLoopHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100500 return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100501 }
502
Roland Levillain6b879dd2014-09-22 17:13:44 +0100503 bool IsLoopPreHeaderFirstPredecessor() const {
504 DCHECK(IsLoopHeader());
505 DCHECK(!GetPredecessors().IsEmpty());
506 return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
507 }
508
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100509 HLoopInformation* GetLoopInformation() const {
510 return loop_information_;
511 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000512
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000513 // Set the loop_information_ on this block. Overrides the current
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100514 // loop_information if it is an outer loop of the passed loop information.
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000515 // Note that this method is called while creating the loop information.
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100516 void SetInLoop(HLoopInformation* info) {
517 if (IsLoopHeader()) {
518 // Nothing to do. This just means `info` is an outer loop.
519 } else if (loop_information_ == nullptr) {
520 loop_information_ = info;
521 } else if (loop_information_->Contains(*info->GetHeader())) {
522 // Block is currently part of an outer loop. Make it part of this inner loop.
523 // Note that a non loop header having a loop information means this loop information
524 // has already been populated
525 loop_information_ = info;
526 } else {
527 // Block is part of an inner loop. Do not update the loop information.
528 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
529 // at this point, because this method is being called while populating `info`.
530 }
531 }
532
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000533 // Raw update of the loop information.
534 void SetLoopInformation(HLoopInformation* info) {
535 loop_information_ = info;
536 }
537
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100538 bool IsInLoop() const { return loop_information_ != nullptr; }
539
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100540 // Returns wheter this block dominates the blocked passed as parameter.
541 bool Dominates(HBasicBlock* block) const;
542
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100543 size_t GetLifetimeStart() const { return lifetime_start_; }
544 size_t GetLifetimeEnd() const { return lifetime_end_; }
545
546 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
547 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
548
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100549 uint32_t GetDexPc() const { return dex_pc_; }
550
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000551 bool IsCatchBlock() const { return is_catch_block_; }
552 void SetIsCatchBlock() { is_catch_block_ = true; }
553
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000554 private:
Nicolas Geoffray276d9da2015-02-02 18:24:11 +0000555 HGraph* graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000556 GrowableArray<HBasicBlock*> predecessors_;
557 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100558 HInstructionList instructions_;
559 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000560 HLoopInformation* loop_information_;
561 HBasicBlock* dominator_;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100562 GrowableArray<HBasicBlock*> dominated_blocks_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000563 int block_id_;
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100564 // The dex program counter of the first instruction of this block.
565 const uint32_t dex_pc_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100566 size_t lifetime_start_;
567 size_t lifetime_end_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000568 bool is_catch_block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000569
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000570 friend class HGraph;
571 friend class HInstruction;
572
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000573 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
574};
575
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100576#define FOR_EACH_CONCRETE_INSTRUCTION(M) \
577 M(Add, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000578 M(And, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000579 M(ArrayGet, Instruction) \
580 M(ArrayLength, Instruction) \
581 M(ArraySet, Instruction) \
582 M(BoundsCheck, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000583 M(CheckCast, Instruction) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100584 M(ClinitCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000585 M(Compare, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100586 M(Condition, BinaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000587 M(Div, BinaryOperation) \
Calin Juravled0d48522014-11-04 16:40:20 +0000588 M(DivZeroCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000589 M(DoubleConstant, Constant) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100590 M(Equal, Condition) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000591 M(Exit, Instruction) \
592 M(FloatConstant, Constant) \
593 M(Goto, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100594 M(GreaterThan, Condition) \
595 M(GreaterThanOrEqual, Condition) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100596 M(If, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000597 M(InstanceFieldGet, Instruction) \
598 M(InstanceFieldSet, Instruction) \
Nicolas Geoffray57a88d42014-11-10 15:09:21 +0000599 M(InstanceOf, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100600 M(IntConstant, Constant) \
Nicolas Geoffray52839d12014-11-07 17:47:25 +0000601 M(InvokeInterface, Invoke) \
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000602 M(InvokeStaticOrDirect, Invoke) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100603 M(InvokeVirtual, Invoke) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000604 M(LessThan, Condition) \
605 M(LessThanOrEqual, Condition) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000606 M(LoadClass, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000607 M(LoadException, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100608 M(LoadLocal, Instruction) \
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +0000609 M(LoadString, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100610 M(Local, Instruction) \
611 M(LongConstant, Constant) \
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +0000612 M(MonitorOperation, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000613 M(Mul, BinaryOperation) \
614 M(Neg, UnaryOperation) \
615 M(NewArray, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100616 M(NewInstance, Instruction) \
Roland Levillain1cc5f2512014-10-22 18:06:21 +0100617 M(Not, UnaryOperation) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000618 M(NotEqual, Condition) \
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000619 M(NullConstant, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000620 M(NullCheck, Instruction) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000621 M(Or, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100622 M(ParallelMove, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000623 M(ParameterValue, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100624 M(Phi, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000625 M(Rem, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100626 M(Return, Instruction) \
627 M(ReturnVoid, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000628 M(Shl, BinaryOperation) \
629 M(Shr, BinaryOperation) \
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +0100630 M(StaticFieldGet, Instruction) \
631 M(StaticFieldSet, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100632 M(StoreLocal, Instruction) \
633 M(Sub, BinaryOperation) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100634 M(SuspendCheck, Instruction) \
Calin Juravle7c4954d2014-10-28 16:57:40 +0000635 M(Temporary, Instruction) \
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +0000636 M(Throw, Instruction) \
Roland Levillaindff1f282014-11-05 14:15:05 +0000637 M(TypeConversion, Instruction) \
Calin Juravle9aec02f2014-11-18 23:06:35 +0000638 M(UShr, BinaryOperation) \
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000639 M(Xor, BinaryOperation) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000640
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100641#define FOR_EACH_INSTRUCTION(M) \
642 FOR_EACH_CONCRETE_INSTRUCTION(M) \
643 M(Constant, Instruction) \
Roland Levillain88cb1752014-10-20 16:36:47 +0100644 M(UnaryOperation, Instruction) \
Calin Juravle34bacdf2014-10-07 20:23:36 +0100645 M(BinaryOperation, Instruction) \
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100646 M(Invoke, Instruction)
Dave Allison20dfc792014-06-16 20:44:29 -0700647
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100648#define FORWARD_DECLARATION(type, super) class H##type;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000649FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
650#undef FORWARD_DECLARATION
651
Roland Levillainccc07a92014-09-16 14:48:16 +0100652#define DECLARE_INSTRUCTION(type) \
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100653 virtual InstructionKind GetKind() const { return k##type; } \
Roland Levillainccc07a92014-09-16 14:48:16 +0100654 virtual const char* DebugName() const { return #type; } \
655 virtual const H##type* As##type() const OVERRIDE { return this; } \
656 virtual H##type* As##type() OVERRIDE { return this; } \
657 virtual bool InstructionTypeEquals(HInstruction* other) const { \
658 return other->Is##type(); \
659 } \
660 virtual void Accept(HGraphVisitor* visitor)
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000661
David Brazdiled596192015-01-23 10:39:45 +0000662template <typename T> class HUseList;
663
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100664template <typename T>
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700665class HUseListNode : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000666 public:
David Brazdiled596192015-01-23 10:39:45 +0000667 HUseListNode* GetPrevious() const { return prev_; }
668 HUseListNode* GetNext() const { return next_; }
669 T GetUser() const { return user_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100670 size_t GetIndex() const { return index_; }
671
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000672 private:
David Brazdiled596192015-01-23 10:39:45 +0000673 HUseListNode(T user, size_t index)
674 : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
675
676 T const user_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100677 const size_t index_;
David Brazdiled596192015-01-23 10:39:45 +0000678 HUseListNode<T>* prev_;
679 HUseListNode<T>* next_;
680
681 friend class HUseList<T>;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000682
683 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
684};
685
David Brazdiled596192015-01-23 10:39:45 +0000686template <typename T>
687class HUseList : public ValueObject {
688 public:
689 HUseList() : first_(nullptr) {}
690
691 void Clear() {
692 first_ = nullptr;
693 }
694
695 // Adds a new entry at the beginning of the use list and returns
696 // the newly created node.
697 HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
David Brazdilea55b932015-01-27 17:12:29 +0000698 HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
David Brazdiled596192015-01-23 10:39:45 +0000699 if (IsEmpty()) {
700 first_ = new_node;
701 } else {
702 first_->prev_ = new_node;
703 new_node->next_ = first_;
704 first_ = new_node;
705 }
706 return new_node;
707 }
708
709 HUseListNode<T>* GetFirst() const {
710 return first_;
711 }
712
713 void Remove(HUseListNode<T>* node) {
714 if (node->prev_ != nullptr) {
715 node->prev_->next_ = node->next_;
716 }
717 if (node->next_ != nullptr) {
718 node->next_->prev_ = node->prev_;
719 }
720 if (node == first_) {
721 first_ = node->next_;
722 }
723 }
724
725 bool IsEmpty() const {
726 return first_ == nullptr;
727 }
728
729 bool HasOnlyOneUse() const {
730 return first_ != nullptr && first_->next_ == nullptr;
731 }
732
733 private:
734 HUseListNode<T>* first_;
735};
736
737template<typename T>
738class HUseIterator : public ValueObject {
739 public:
740 explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
741
742 bool Done() const { return current_ == nullptr; }
743
744 void Advance() {
745 DCHECK(!Done());
746 current_ = current_->GetNext();
747 }
748
749 HUseListNode<T>* Current() const {
750 DCHECK(!Done());
751 return current_;
752 }
753
754 private:
755 HUseListNode<T>* current_;
756
757 friend class HValue;
758};
759
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100760// Represents the side effects an instruction may have.
761class SideEffects : public ValueObject {
762 public:
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100763 SideEffects() : flags_(0) {}
764
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100765 static SideEffects None() {
766 return SideEffects(0);
767 }
768
769 static SideEffects All() {
770 return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
771 }
772
773 static SideEffects ChangesSomething() {
774 return SideEffects((1 << kFlagChangesCount) - 1);
775 }
776
777 static SideEffects DependsOnSomething() {
778 int count = kFlagDependsOnCount - kFlagChangesCount;
779 return SideEffects(((1 << count) - 1) << kFlagChangesCount);
780 }
781
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100782 SideEffects Union(SideEffects other) const {
783 return SideEffects(flags_ | other.flags_);
784 }
785
Roland Levillain72bceff2014-09-15 18:29:00 +0100786 bool HasSideEffects() const {
787 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
788 return (flags_ & all_bits_set) != 0;
789 }
790
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100791 bool HasAllSideEffects() const {
792 size_t all_bits_set = (1 << kFlagChangesCount) - 1;
793 return all_bits_set == (flags_ & all_bits_set);
794 }
795
796 bool DependsOn(SideEffects other) const {
797 size_t depends_flags = other.ComputeDependsFlags();
798 return (flags_ & depends_flags) != 0;
799 }
800
801 bool HasDependencies() const {
802 int count = kFlagDependsOnCount - kFlagChangesCount;
803 size_t all_bits_set = (1 << count) - 1;
804 return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
805 }
806
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100807 private:
808 static constexpr int kFlagChangesSomething = 0;
809 static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
810
811 static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
812 static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
813
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100814 explicit SideEffects(size_t flags) : flags_(flags) {}
815
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100816 size_t ComputeDependsFlags() const {
817 return flags_ << kFlagChangesCount;
818 }
819
820 size_t flags_;
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100821};
822
David Brazdiled596192015-01-23 10:39:45 +0000823// A HEnvironment object contains the values of virtual registers at a given location.
824class HEnvironment : public ArenaObject<kArenaAllocMisc> {
825 public:
826 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs)
827 : vregs_(arena, number_of_vregs) {
828 vregs_.SetSize(number_of_vregs);
829 for (size_t i = 0; i < number_of_vregs; i++) {
830 vregs_.Put(i, VRegInfo(nullptr, nullptr));
831 }
832 }
833
834 void CopyFrom(HEnvironment* env);
835
836 void SetRawEnvAt(size_t index, HInstruction* instruction) {
837 vregs_.Put(index, VRegInfo(instruction, nullptr));
838 }
839
840 // Record instructions' use entries of this environment for constant-time removal.
841 void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
842 DCHECK(env_use->GetUser() == this);
843 size_t index = env_use->GetIndex();
844 VRegInfo info = vregs_.Get(index);
845 DCHECK(info.vreg_ != nullptr);
846 DCHECK(info.node_ == nullptr);
847 vregs_.Put(index, VRegInfo(info.vreg_, env_use));
848 }
849
850 HInstruction* GetInstructionAt(size_t index) const {
851 return vregs_.Get(index).vreg_;
852 }
853
854 HUseListNode<HEnvironment*>* GetInstructionEnvUseAt(size_t index) const {
855 return vregs_.Get(index).node_;
856 }
857
858 size_t Size() const { return vregs_.Size(); }
859
860 private:
861 struct VRegInfo {
862 HInstruction* vreg_;
863 HUseListNode<HEnvironment*>* node_;
864
865 VRegInfo(HInstruction* instruction, HUseListNode<HEnvironment*>* env_use)
866 : vreg_(instruction), node_(env_use) {}
867 };
868
869 GrowableArray<VRegInfo> vregs_;
870
871 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
872};
873
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700874class HInstruction : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000875 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100876 explicit HInstruction(SideEffects side_effects)
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000877 : previous_(nullptr),
878 next_(nullptr),
879 block_(nullptr),
880 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100881 ssa_index_(-1),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100882 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100883 locations_(nullptr),
884 live_interval_(nullptr),
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100885 lifetime_position_(kNoLifetime),
886 side_effects_(side_effects) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000887
Dave Allison20dfc792014-06-16 20:44:29 -0700888 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000889
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100890#define DECLARE_KIND(type, super) k##type,
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100891 enum InstructionKind {
892 FOR_EACH_INSTRUCTION(DECLARE_KIND)
893 };
894#undef DECLARE_KIND
895
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000896 HInstruction* GetNext() const { return next_; }
897 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000898
Calin Juravle77520bc2015-01-12 18:45:46 +0000899 HInstruction* GetNextDisregardingMoves() const;
900 HInstruction* GetPreviousDisregardingMoves() const;
901
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000902 HBasicBlock* GetBlock() const { return block_; }
903 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100904 bool IsInBlock() const { return block_ != nullptr; }
905 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffray3ac17fc2014-08-06 23:02:54 +0100906 bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000907
Roland Levillain6b879dd2014-09-22 17:13:44 +0100908 virtual size_t InputCount() const = 0;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100909 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000910
911 virtual void Accept(HGraphVisitor* visitor) = 0;
912 virtual const char* DebugName() const = 0;
913
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100914 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100915 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100916
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100917 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100918 virtual bool IsControlFlow() const { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +0100919 virtual bool CanThrow() const { return false; }
Roland Levillain72bceff2014-09-15 18:29:00 +0100920 bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100921
Calin Juravle10e244f2015-01-26 18:54:32 +0000922 // Does not apply for all instructions, but having this at top level greatly
923 // simplifies the null check elimination.
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000924 virtual bool CanBeNull() const {
925 DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
926 return true;
927 }
Calin Juravle10e244f2015-01-26 18:54:32 +0000928
Calin Juravle77520bc2015-01-12 18:45:46 +0000929 virtual bool CanDoImplicitNullCheck() const { return false; }
930
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100931 void AddUseAt(HInstruction* user, size_t index) {
David Brazdiled596192015-01-23 10:39:45 +0000932 uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000933 }
934
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100935 void AddEnvUseAt(HEnvironment* user, size_t index) {
Nicolas Geoffray724c9632014-09-22 12:27:27 +0100936 DCHECK(user != nullptr);
David Brazdiled596192015-01-23 10:39:45 +0000937 HUseListNode<HEnvironment*>* env_use =
938 env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
939 user->RecordEnvUse(env_use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100940 }
941
942 void RemoveUser(HInstruction* user, size_t index);
David Brazdiled596192015-01-23 10:39:45 +0000943 void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100944
David Brazdilea55b932015-01-27 17:12:29 +0000945 const HUseList<HInstruction*>& GetUses() { return uses_; }
946 const HUseList<HEnvironment*>& GetEnvUses() { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000947
David Brazdiled596192015-01-23 10:39:45 +0000948 bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
949 bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000950
Roland Levillain6c82d402014-10-13 16:10:27 +0100951 // Does this instruction strictly dominate `other_instruction`?
952 // Returns false if this instruction and `other_instruction` are the same.
953 // Aborts if this instruction and `other_instruction` are both phis.
954 bool StrictlyDominates(HInstruction* other_instruction) const;
Roland Levillainccc07a92014-09-16 14:48:16 +0100955
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000956 int GetId() const { return id_; }
957 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000958
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100959 int GetSsaIndex() const { return ssa_index_; }
960 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
961 bool HasSsaIndex() const { return ssa_index_ != -1; }
962
963 bool HasEnvironment() const { return environment_ != nullptr; }
964 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100965 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
966
Nicolas Geoffray39468442014-09-02 15:17:15 +0100967 // Returns the number of entries in the environment. Typically, that is the
968 // number of dex registers in a method. It could be more in case of inlining.
969 size_t EnvironmentSize() const;
970
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000971 LocationSummary* GetLocations() const { return locations_; }
972 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000973
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100974 void ReplaceWith(HInstruction* instruction);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100975 void ReplaceInput(HInstruction* replacement, size_t index);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100976
Nicolas Geoffray82091da2015-01-26 10:02:45 +0000977 // Move `this` instruction before `cursor`.
978 void MoveBefore(HInstruction* cursor);
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000979
Nicolas Geoffray360231a2014-10-08 21:07:48 +0100980#define INSTRUCTION_TYPE_CHECK(type, super) \
Roland Levillainccc07a92014-09-16 14:48:16 +0100981 bool Is##type() const { return (As##type() != nullptr); } \
982 virtual const H##type* As##type() const { return nullptr; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000983 virtual H##type* As##type() { return nullptr; }
984
985 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
986#undef INSTRUCTION_TYPE_CHECK
987
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100988 // Returns whether the instruction can be moved within the graph.
989 virtual bool CanBeMoved() const { return false; }
990
991 // Returns whether the two instructions are of the same kind.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700992 virtual bool InstructionTypeEquals(HInstruction* other) const {
993 UNUSED(other);
994 return false;
995 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +0100996
997 // Returns whether any data encoded in the two instructions is equal.
998 // This method does not look at the inputs. Both instructions must be
999 // of the same type, otherwise the method has undefined behavior.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001000 virtual bool InstructionDataEquals(HInstruction* other) const {
1001 UNUSED(other);
1002 return false;
1003 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001004
1005 // Returns whether two instructions are equal, that is:
Calin Juravleddb7df22014-11-25 20:56:51 +00001006 // 1) They have the same type and contain the same data (InstructionDataEquals).
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001007 // 2) Their inputs are identical.
1008 bool Equals(HInstruction* other) const;
1009
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001010 virtual InstructionKind GetKind() const = 0;
1011
1012 virtual size_t ComputeHashCode() const {
1013 size_t result = GetKind();
1014 for (size_t i = 0, e = InputCount(); i < e; ++i) {
1015 result = (result * 31) + InputAt(i)->GetId();
1016 }
1017 return result;
1018 }
1019
1020 SideEffects GetSideEffects() const { return side_effects_; }
1021
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001022 size_t GetLifetimePosition() const { return lifetime_position_; }
1023 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
1024 LiveInterval* GetLiveInterval() const { return live_interval_; }
1025 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
1026 bool HasLiveInterval() const { return live_interval_ != nullptr; }
1027
Nicolas Geoffrayc0572a42015-02-06 14:35:25 +00001028 bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1029
1030 // Returns whether the code generation of the instruction will require to have access
1031 // to the current method. Such instructions are:
1032 // (1): Instructions that require an environment, as calling the runtime requires
1033 // to walk the stack and have the current method stored at a specific stack address.
1034 // (2): Object literals like classes and strings, that are loaded from the dex cache
1035 // fields of the current method.
1036 bool NeedsCurrentMethod() const {
1037 return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1038 }
1039
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001040 private:
1041 HInstruction* previous_;
1042 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001043 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001044
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001045 // An instruction gets an id when it is added to the graph.
1046 // It reflects creation order. A negative id means the instruction
Nicolas Geoffray39468442014-09-02 15:17:15 +01001047 // has not been added to the graph.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001048 int id_;
1049
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001050 // When doing liveness analysis, instructions that have uses get an SSA index.
1051 int ssa_index_;
1052
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001053 // List of instructions that have this instruction as input.
David Brazdiled596192015-01-23 10:39:45 +00001054 HUseList<HInstruction*> uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001055
1056 // List of environments that contain this instruction.
David Brazdiled596192015-01-23 10:39:45 +00001057 HUseList<HEnvironment*> env_uses_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001058
Nicolas Geoffray39468442014-09-02 15:17:15 +01001059 // The environment associated with this instruction. Not null if the instruction
1060 // might jump out of the method.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001061 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001062
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001063 // Set by the code generator.
1064 LocationSummary* locations_;
1065
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001066 // Set by the liveness analysis.
1067 LiveInterval* live_interval_;
1068
1069 // Set by the liveness analysis, this is the position in a linear
1070 // order of blocks where this instruction's live interval start.
1071 size_t lifetime_position_;
1072
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001073 const SideEffects side_effects_;
1074
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001075 friend class HBasicBlock;
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001076 friend class HGraph;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001077 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001078
1079 DISALLOW_COPY_AND_ASSIGN(HInstruction);
1080};
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001081std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001082
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001083class HInputIterator : public ValueObject {
1084 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001085 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001086
1087 bool Done() const { return index_ == instruction_->InputCount(); }
1088 HInstruction* Current() const { return instruction_->InputAt(index_); }
1089 void Advance() { index_++; }
1090
1091 private:
1092 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001093 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001094
1095 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1096};
1097
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001098class HInstructionIterator : public ValueObject {
1099 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001100 explicit HInstructionIterator(const HInstructionList& instructions)
1101 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001102 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001103 }
1104
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001105 bool Done() const { return instruction_ == nullptr; }
1106 HInstruction* Current() const { return instruction_; }
1107 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001108 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001109 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001110 }
1111
1112 private:
1113 HInstruction* instruction_;
1114 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001115
1116 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001117};
1118
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001119class HBackwardInstructionIterator : public ValueObject {
1120 public:
1121 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1122 : instruction_(instructions.last_instruction_) {
1123 next_ = Done() ? nullptr : instruction_->GetPrevious();
1124 }
1125
1126 bool Done() const { return instruction_ == nullptr; }
1127 HInstruction* Current() const { return instruction_; }
1128 void Advance() {
1129 instruction_ = next_;
1130 next_ = Done() ? nullptr : instruction_->GetPrevious();
1131 }
1132
1133 private:
1134 HInstruction* instruction_;
1135 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +01001136
1137 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001138};
1139
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001140// An embedded container with N elements of type T. Used (with partial
1141// specialization for N=0) because embedded arrays cannot have size 0.
1142template<typename T, intptr_t N>
1143class EmbeddedArray {
1144 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001145 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001146
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001147 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001148
1149 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001150 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001151 return elements_[i];
1152 }
1153
1154 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001155 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001156 return elements_[i];
1157 }
1158
1159 const T& At(intptr_t i) const {
1160 return (*this)[i];
1161 }
1162
1163 void SetAt(intptr_t i, const T& val) {
1164 (*this)[i] = val;
1165 }
1166
1167 private:
1168 T elements_[N];
1169};
1170
1171template<typename T>
1172class EmbeddedArray<T, 0> {
1173 public:
1174 intptr_t length() const { return 0; }
1175 const T& operator[](intptr_t i) const {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001176 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001177 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001178 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001179 }
1180 T& operator[](intptr_t i) {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001181 UNUSED(i);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001182 LOG(FATAL) << "Unreachable";
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001183 UNREACHABLE();
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001184 }
1185};
1186
1187template<intptr_t N>
1188class HTemplateInstruction: public HInstruction {
1189 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001190 HTemplateInstruction<N>(SideEffects side_effects)
1191 : HInstruction(side_effects), inputs_() {}
Dave Allison20dfc792014-06-16 20:44:29 -07001192 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001193
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001194 virtual size_t InputCount() const { return N; }
1195 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001196
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001197 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001198 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001199 inputs_[i] = instruction;
1200 }
1201
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001202 private:
1203 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001204
1205 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001206};
1207
Dave Allison20dfc792014-06-16 20:44:29 -07001208template<intptr_t N>
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001209class HExpression : public HTemplateInstruction<N> {
Dave Allison20dfc792014-06-16 20:44:29 -07001210 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001211 HExpression<N>(Primitive::Type type, SideEffects side_effects)
1212 : HTemplateInstruction<N>(side_effects), type_(type) {}
Dave Allison20dfc792014-06-16 20:44:29 -07001213 virtual ~HExpression() {}
1214
1215 virtual Primitive::Type GetType() const { return type_; }
1216
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001217 protected:
1218 Primitive::Type type_;
Dave Allison20dfc792014-06-16 20:44:29 -07001219};
1220
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001221// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1222// instruction that branches to the exit block.
1223class HReturnVoid : public HTemplateInstruction<0> {
1224 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001225 HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001226
1227 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001228
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001229 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001230
1231 private:
1232 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1233};
1234
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001235// Represents dex's RETURN opcodes. A HReturn is a control flow
1236// instruction that branches to the exit block.
1237class HReturn : public HTemplateInstruction<1> {
1238 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001239 explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001240 SetRawInputAt(0, value);
1241 }
1242
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001243 virtual bool IsControlFlow() const { return true; }
1244
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001245 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001246
1247 private:
1248 DISALLOW_COPY_AND_ASSIGN(HReturn);
1249};
1250
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001251// The exit instruction is the only instruction of the exit block.
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001252// Instructions aborting the method (HThrow and HReturn) must branch to the
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001253// exit block.
1254class HExit : public HTemplateInstruction<0> {
1255 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001256 HExit() : HTemplateInstruction(SideEffects::None()) {}
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +01001257
1258 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001259
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001260 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001261
1262 private:
1263 DISALLOW_COPY_AND_ASSIGN(HExit);
1264};
1265
1266// Jumps from one block to another.
1267class HGoto : public HTemplateInstruction<0> {
1268 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001269 HGoto() : HTemplateInstruction(SideEffects::None()) {}
1270
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001271 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001272
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001273 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001274 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001275 }
1276
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001277 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001278
1279 private:
1280 DISALLOW_COPY_AND_ASSIGN(HGoto);
1281};
1282
Dave Allison20dfc792014-06-16 20:44:29 -07001283
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001284// Conditional branch. A block ending with an HIf instruction must have
1285// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001286class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001287 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001288 explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001289 SetRawInputAt(0, input);
1290 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001291
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00001292 bool IsControlFlow() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001293
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001294 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001295 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001296 }
1297
1298 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001299 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001300 }
1301
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001302 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001303
Dave Allison20dfc792014-06-16 20:44:29 -07001304 virtual bool IsIfInstruction() const { return true; }
1305
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +00001306 private:
1307 DISALLOW_COPY_AND_ASSIGN(HIf);
1308};
1309
Roland Levillain88cb1752014-10-20 16:36:47 +01001310class HUnaryOperation : public HExpression<1> {
1311 public:
1312 HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1313 : HExpression(result_type, SideEffects::None()) {
1314 SetRawInputAt(0, input);
1315 }
1316
1317 HInstruction* GetInput() const { return InputAt(0); }
1318 Primitive::Type GetResultType() const { return GetType(); }
1319
1320 virtual bool CanBeMoved() const { return true; }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001321 virtual bool InstructionDataEquals(HInstruction* other) const {
1322 UNUSED(other);
1323 return true;
1324 }
Roland Levillain88cb1752014-10-20 16:36:47 +01001325
Roland Levillain9240d6a2014-10-20 16:47:04 +01001326 // Try to statically evaluate `operation` and return a HConstant
1327 // containing the result of this evaluation. If `operation` cannot
1328 // be evaluated as a constant, return nullptr.
1329 HConstant* TryStaticEvaluation() const;
1330
1331 // Apply this operation to `x`.
1332 virtual int32_t Evaluate(int32_t x) const = 0;
1333 virtual int64_t Evaluate(int64_t x) const = 0;
1334
Roland Levillain88cb1752014-10-20 16:36:47 +01001335 DECLARE_INSTRUCTION(UnaryOperation);
1336
1337 private:
1338 DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1339};
1340
Dave Allison20dfc792014-06-16 20:44:29 -07001341class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001342 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001343 HBinaryOperation(Primitive::Type result_type,
1344 HInstruction* left,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001345 HInstruction* right) : HExpression(result_type, SideEffects::None()) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001346 SetRawInputAt(0, left);
1347 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001348 }
1349
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001350 HInstruction* GetLeft() const { return InputAt(0); }
1351 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -07001352 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001353
1354 virtual bool IsCommutative() { return false; }
1355
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001356 virtual bool CanBeMoved() const { return true; }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07001357 virtual bool InstructionDataEquals(HInstruction* other) const {
1358 UNUSED(other);
1359 return true;
1360 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001361
Roland Levillain9240d6a2014-10-20 16:47:04 +01001362 // Try to statically evaluate `operation` and return a HConstant
Roland Levillain556c3d12014-09-18 15:25:07 +01001363 // containing the result of this evaluation. If `operation` cannot
1364 // be evaluated as a constant, return nullptr.
Roland Levillain9240d6a2014-10-20 16:47:04 +01001365 HConstant* TryStaticEvaluation() const;
Roland Levillain556c3d12014-09-18 15:25:07 +01001366
1367 // Apply this operation to `x` and `y`.
1368 virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1369 virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1370
Roland Levillainccc07a92014-09-16 14:48:16 +01001371 DECLARE_INSTRUCTION(BinaryOperation);
1372
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001373 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001374 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1375};
1376
Dave Allison20dfc792014-06-16 20:44:29 -07001377class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001378 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001379 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001380 : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1381 needs_materialization_(true) {}
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001382
1383 virtual bool IsCommutative() { return true; }
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001384
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001385 bool NeedsMaterialization() const { return needs_materialization_; }
1386 void ClearNeedsMaterialization() { needs_materialization_ = false; }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001387
Nicolas Geoffray18efde52014-09-22 15:51:11 +01001388 // For code generation purposes, returns whether this instruction is just before
1389 // `if_`, and disregard moves in between.
1390 bool IsBeforeWhenDisregardMoves(HIf* if_) const;
1391
Dave Allison20dfc792014-06-16 20:44:29 -07001392 DECLARE_INSTRUCTION(Condition);
1393
1394 virtual IfCondition GetCondition() const = 0;
1395
1396 private:
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001397 // For register allocation purposes, returns whether this instruction needs to be
1398 // materialized (that is, not just be in the processor flags).
1399 bool needs_materialization_;
1400
Dave Allison20dfc792014-06-16 20:44:29 -07001401 DISALLOW_COPY_AND_ASSIGN(HCondition);
1402};
1403
1404// Instruction to check if two inputs are equal to each other.
1405class HEqual : public HCondition {
1406 public:
1407 HEqual(HInstruction* first, HInstruction* second)
1408 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001409
Roland Levillain93445682014-10-06 19:24:02 +01001410 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1411 return x == y ? 1 : 0;
1412 }
1413 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1414 return x == y ? 1 : 0;
1415 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001416
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001417 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001418
Dave Allison20dfc792014-06-16 20:44:29 -07001419 virtual IfCondition GetCondition() const {
1420 return kCondEQ;
1421 }
1422
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001423 private:
1424 DISALLOW_COPY_AND_ASSIGN(HEqual);
1425};
1426
Dave Allison20dfc792014-06-16 20:44:29 -07001427class HNotEqual : public HCondition {
1428 public:
1429 HNotEqual(HInstruction* first, HInstruction* second)
1430 : HCondition(first, second) {}
1431
Roland Levillain93445682014-10-06 19:24:02 +01001432 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1433 return x != y ? 1 : 0;
1434 }
1435 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1436 return x != y ? 1 : 0;
1437 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001438
Dave Allison20dfc792014-06-16 20:44:29 -07001439 DECLARE_INSTRUCTION(NotEqual);
1440
1441 virtual IfCondition GetCondition() const {
1442 return kCondNE;
1443 }
1444
1445 private:
1446 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
1447};
1448
1449class HLessThan : public HCondition {
1450 public:
1451 HLessThan(HInstruction* first, HInstruction* second)
1452 : HCondition(first, second) {}
1453
Roland Levillain93445682014-10-06 19:24:02 +01001454 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1455 return x < y ? 1 : 0;
1456 }
1457 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1458 return x < y ? 1 : 0;
1459 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001460
Dave Allison20dfc792014-06-16 20:44:29 -07001461 DECLARE_INSTRUCTION(LessThan);
1462
1463 virtual IfCondition GetCondition() const {
1464 return kCondLT;
1465 }
1466
1467 private:
1468 DISALLOW_COPY_AND_ASSIGN(HLessThan);
1469};
1470
1471class HLessThanOrEqual : public HCondition {
1472 public:
1473 HLessThanOrEqual(HInstruction* first, HInstruction* second)
1474 : HCondition(first, second) {}
1475
Roland Levillain93445682014-10-06 19:24:02 +01001476 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1477 return x <= y ? 1 : 0;
1478 }
1479 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1480 return x <= y ? 1 : 0;
1481 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001482
Dave Allison20dfc792014-06-16 20:44:29 -07001483 DECLARE_INSTRUCTION(LessThanOrEqual);
1484
1485 virtual IfCondition GetCondition() const {
1486 return kCondLE;
1487 }
1488
1489 private:
1490 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
1491};
1492
1493class HGreaterThan : public HCondition {
1494 public:
1495 HGreaterThan(HInstruction* first, HInstruction* second)
1496 : HCondition(first, second) {}
1497
Roland Levillain93445682014-10-06 19:24:02 +01001498 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1499 return x > y ? 1 : 0;
1500 }
1501 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1502 return x > y ? 1 : 0;
1503 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001504
Dave Allison20dfc792014-06-16 20:44:29 -07001505 DECLARE_INSTRUCTION(GreaterThan);
1506
1507 virtual IfCondition GetCondition() const {
1508 return kCondGT;
1509 }
1510
1511 private:
1512 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
1513};
1514
1515class HGreaterThanOrEqual : public HCondition {
1516 public:
1517 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
1518 : HCondition(first, second) {}
1519
Roland Levillain93445682014-10-06 19:24:02 +01001520 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1521 return x >= y ? 1 : 0;
1522 }
1523 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1524 return x >= y ? 1 : 0;
1525 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001526
Dave Allison20dfc792014-06-16 20:44:29 -07001527 DECLARE_INSTRUCTION(GreaterThanOrEqual);
1528
1529 virtual IfCondition GetCondition() const {
1530 return kCondGE;
1531 }
1532
1533 private:
1534 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
1535};
1536
1537
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001538// Instruction to check how two inputs compare to each other.
1539// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
1540class HCompare : public HBinaryOperation {
1541 public:
Calin Juravleddb7df22014-11-25 20:56:51 +00001542 // The bias applies for floating point operations and indicates how NaN
1543 // comparisons are treated:
1544 enum Bias {
1545 kNoBias, // bias is not applicable (i.e. for long operation)
1546 kGtBias, // return 1 for NaN comparisons
1547 kLtBias, // return -1 for NaN comparisons
1548 };
1549
1550 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias)
1551 : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) {
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001552 DCHECK_EQ(type, first->GetType());
1553 DCHECK_EQ(type, second->GetType());
1554 }
1555
Calin Juravleddb7df22014-11-25 20:56:51 +00001556 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01001557 return
1558 x == y ? 0 :
1559 x > y ? 1 :
1560 -1;
1561 }
Calin Juravleddb7df22014-11-25 20:56:51 +00001562
1563 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
Roland Levillain556c3d12014-09-18 15:25:07 +01001564 return
1565 x == y ? 0 :
1566 x > y ? 1 :
1567 -1;
1568 }
1569
Calin Juravleddb7df22014-11-25 20:56:51 +00001570 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
1571 return bias_ == other->AsCompare()->bias_;
1572 }
1573
1574 bool IsGtBias() { return bias_ == kGtBias; }
1575
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001576 DECLARE_INSTRUCTION(Compare);
1577
1578 private:
Calin Juravleddb7df22014-11-25 20:56:51 +00001579 const Bias bias_;
1580
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001581 DISALLOW_COPY_AND_ASSIGN(HCompare);
1582};
1583
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001584// A local in the graph. Corresponds to a Dex register.
1585class HLocal : public HTemplateInstruction<0> {
1586 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001587 explicit HLocal(uint16_t reg_number)
1588 : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001589
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001590 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001591
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001592 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001593
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001594 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001595 // The Dex register number.
1596 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001597
1598 DISALLOW_COPY_AND_ASSIGN(HLocal);
1599};
1600
1601// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07001602class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001603 public:
Roland Levillain5799fc02014-09-25 12:15:20 +01001604 HLoadLocal(HLocal* local, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001605 : HExpression(type, SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001606 SetRawInputAt(0, local);
1607 }
1608
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001609 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1610
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001611 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001612
1613 private:
1614 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
1615};
1616
1617// Store a value in a given local. This instruction has two inputs: the value
1618// and the local.
1619class HStoreLocal : public HTemplateInstruction<2> {
1620 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001621 HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001622 SetRawInputAt(0, local);
1623 SetRawInputAt(1, value);
1624 }
1625
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001626 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1627
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001628 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001629
1630 private:
1631 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
1632};
1633
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001634class HConstant : public HExpression<0> {
1635 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001636 explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
1637
1638 virtual bool CanBeMoved() const { return true; }
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001639
1640 DECLARE_INSTRUCTION(Constant);
1641
1642 private:
1643 DISALLOW_COPY_AND_ASSIGN(HConstant);
1644};
1645
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001646class HFloatConstant : public HConstant {
1647 public:
1648 explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
1649
1650 float GetValue() const { return value_; }
1651
1652 virtual bool InstructionDataEquals(HInstruction* other) const {
1653 return bit_cast<float, int32_t>(other->AsFloatConstant()->value_) ==
1654 bit_cast<float, int32_t>(value_);
1655 }
1656
1657 virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1658
1659 DECLARE_INSTRUCTION(FloatConstant);
1660
1661 private:
1662 const float value_;
1663
1664 DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
1665};
1666
1667class HDoubleConstant : public HConstant {
1668 public:
1669 explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
1670
1671 double GetValue() const { return value_; }
1672
1673 virtual bool InstructionDataEquals(HInstruction* other) const {
1674 return bit_cast<double, int64_t>(other->AsDoubleConstant()->value_) ==
1675 bit_cast<double, int64_t>(value_);
1676 }
1677
1678 virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1679
1680 DECLARE_INSTRUCTION(DoubleConstant);
1681
1682 private:
1683 const double value_;
1684
1685 DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
1686};
1687
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +00001688class HNullConstant : public HConstant {
1689 public:
1690 HNullConstant() : HConstant(Primitive::kPrimNot) {}
1691
1692 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
1693 return true;
1694 }
1695
1696 size_t ComputeHashCode() const OVERRIDE { return 0; }
1697
1698 DECLARE_INSTRUCTION(NullConstant);
1699
1700 private:
1701 DISALLOW_COPY_AND_ASSIGN(HNullConstant);
1702};
1703
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001704// Constants of the type int. Those can be from Dex instructions, or
1705// synthesized (for example with the if-eqz instruction).
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001706class HIntConstant : public HConstant {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001707 public:
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001708 explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001709
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001710 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001711
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001712 virtual bool InstructionDataEquals(HInstruction* other) const {
1713 return other->AsIntConstant()->value_ == value_;
1714 }
1715
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001716 virtual size_t ComputeHashCode() const { return GetValue(); }
1717
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001718 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001719
1720 private:
1721 const int32_t value_;
1722
1723 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
1724};
1725
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001726class HLongConstant : public HConstant {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001727 public:
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01001728 explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001729
1730 int64_t GetValue() const { return value_; }
1731
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001732 virtual bool InstructionDataEquals(HInstruction* other) const {
1733 return other->AsLongConstant()->value_ == value_;
1734 }
1735
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01001736 virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1737
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001738 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001739
1740 private:
1741 const int64_t value_;
1742
1743 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
1744};
1745
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001746enum class Intrinsics {
1747#define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
1748#include "intrinsics_list.h"
1749 kNone,
1750 INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
1751#undef INTRINSICS_LIST
1752#undef OPTIMIZING_INTRINSICS
1753};
1754std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
1755
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001756class HInvoke : public HInstruction {
1757 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001758 virtual size_t InputCount() const { return inputs_.Size(); }
1759 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1760
1761 // Runtime needs to walk the stack, so Dex -> Dex calls need to
1762 // know their environment.
Calin Juravle77520bc2015-01-12 18:45:46 +00001763 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001764
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001765 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001766 SetRawInputAt(index, argument);
1767 }
1768
1769 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1770 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001771 }
1772
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001773 virtual Primitive::Type GetType() const { return return_type_; }
1774
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001775 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001776
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001777 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
1778
1779 Intrinsics GetIntrinsic() {
1780 return intrinsic_;
1781 }
1782
1783 void SetIntrinsic(Intrinsics intrinsic) {
1784 intrinsic_ = intrinsic;
1785 }
1786
Nicolas Geoffray360231a2014-10-08 21:07:48 +01001787 DECLARE_INSTRUCTION(Invoke);
1788
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001789 protected:
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001790 HInvoke(ArenaAllocator* arena,
1791 uint32_t number_of_arguments,
1792 Primitive::Type return_type,
1793 uint32_t dex_pc,
1794 uint32_t dex_method_index)
1795 : HInstruction(SideEffects::All()),
1796 inputs_(arena, number_of_arguments),
1797 return_type_(return_type),
1798 dex_pc_(dex_pc),
1799 dex_method_index_(dex_method_index),
1800 intrinsic_(Intrinsics::kNone) {
1801 inputs_.SetSize(number_of_arguments);
1802 }
1803
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001804 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001805 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001806 const uint32_t dex_pc_;
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001807 const uint32_t dex_method_index_;
1808 Intrinsics intrinsic_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001809
1810 private:
1811 DISALLOW_COPY_AND_ASSIGN(HInvoke);
1812};
1813
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001814class HInvokeStaticOrDirect : public HInvoke {
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001815 public:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001816 HInvokeStaticOrDirect(ArenaAllocator* arena,
1817 uint32_t number_of_arguments,
1818 Primitive::Type return_type,
1819 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001820 uint32_t dex_method_index,
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00001821 bool is_recursive,
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001822 InvokeType invoke_type)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001823 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00001824 invoke_type_(invoke_type),
1825 is_recursive_(is_recursive) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001826
Calin Juravle77520bc2015-01-12 18:45:46 +00001827 bool CanDoImplicitNullCheck() const OVERRIDE {
1828 // We access the method via the dex cache so we can't do an implicit null check.
1829 // TODO: for intrinsics we can generate implicit null checks.
1830 return false;
1831 }
1832
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001833 InvokeType GetInvokeType() const { return invoke_type_; }
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00001834 bool IsRecursive() const { return is_recursive_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001835
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001836 DECLARE_INSTRUCTION(InvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001837
1838 private:
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001839 const InvokeType invoke_type_;
Nicolas Geoffray1cf95282014-12-12 19:22:03 +00001840 const bool is_recursive_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001841
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00001842 DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001843};
1844
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001845class HInvokeVirtual : public HInvoke {
1846 public:
1847 HInvokeVirtual(ArenaAllocator* arena,
1848 uint32_t number_of_arguments,
1849 Primitive::Type return_type,
1850 uint32_t dex_pc,
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001851 uint32_t dex_method_index,
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001852 uint32_t vtable_index)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001853 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001854 vtable_index_(vtable_index) {}
1855
Calin Juravle77520bc2015-01-12 18:45:46 +00001856 bool CanDoImplicitNullCheck() const OVERRIDE {
1857 // TODO: Add implicit null checks in intrinsics.
1858 return !GetLocations()->Intrinsified();
1859 }
1860
Nicolas Geoffraye982f0b2014-08-13 02:11:24 +01001861 uint32_t GetVTableIndex() const { return vtable_index_; }
1862
1863 DECLARE_INSTRUCTION(InvokeVirtual);
1864
1865 private:
1866 const uint32_t vtable_index_;
1867
1868 DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
1869};
1870
Nicolas Geoffray52839d12014-11-07 17:47:25 +00001871class HInvokeInterface : public HInvoke {
1872 public:
1873 HInvokeInterface(ArenaAllocator* arena,
1874 uint32_t number_of_arguments,
1875 Primitive::Type return_type,
1876 uint32_t dex_pc,
1877 uint32_t dex_method_index,
1878 uint32_t imt_index)
Andreas Gampe71fb52f2014-12-29 17:43:08 -08001879 : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
Nicolas Geoffray52839d12014-11-07 17:47:25 +00001880 imt_index_(imt_index) {}
1881
Calin Juravle77520bc2015-01-12 18:45:46 +00001882 bool CanDoImplicitNullCheck() const OVERRIDE {
1883 // TODO: Add implicit null checks in intrinsics.
1884 return !GetLocations()->Intrinsified();
1885 }
1886
Nicolas Geoffray52839d12014-11-07 17:47:25 +00001887 uint32_t GetImtIndex() const { return imt_index_; }
1888 uint32_t GetDexMethodIndex() const { return dex_method_index_; }
1889
1890 DECLARE_INSTRUCTION(InvokeInterface);
1891
1892 private:
Nicolas Geoffray52839d12014-11-07 17:47:25 +00001893 const uint32_t imt_index_;
1894
1895 DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
1896};
1897
Dave Allison20dfc792014-06-16 20:44:29 -07001898class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001899 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001900 HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01001901 : HExpression(Primitive::kPrimNot, SideEffects::None()),
1902 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001903 type_index_(type_index),
1904 entrypoint_(entrypoint) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001905
1906 uint32_t GetDexPc() const { return dex_pc_; }
1907 uint16_t GetTypeIndex() const { return type_index_; }
1908
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001909 // Calls runtime so needs an environment.
Calin Juravle92a6ed22014-12-02 18:58:03 +00001910 bool NeedsEnvironment() const OVERRIDE { return true; }
1911 // It may throw when called on:
1912 // - interfaces
1913 // - abstract/innaccessible/unknown classes
1914 // TODO: optimize when possible.
1915 bool CanThrow() const OVERRIDE { return true; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001916
Calin Juravle10e244f2015-01-26 18:54:32 +00001917 bool CanBeNull() const OVERRIDE { return false; }
1918
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001919 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
1920
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001921 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001922
1923 private:
1924 const uint32_t dex_pc_;
1925 const uint16_t type_index_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001926 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001927
1928 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
1929};
1930
Roland Levillain88cb1752014-10-20 16:36:47 +01001931class HNeg : public HUnaryOperation {
1932 public:
1933 explicit HNeg(Primitive::Type result_type, HInstruction* input)
1934 : HUnaryOperation(result_type, input) {}
1935
Roland Levillain9240d6a2014-10-20 16:47:04 +01001936 virtual int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
1937 virtual int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
1938
Roland Levillain88cb1752014-10-20 16:36:47 +01001939 DECLARE_INSTRUCTION(Neg);
1940
1941 private:
1942 DISALLOW_COPY_AND_ASSIGN(HNeg);
1943};
1944
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001945class HNewArray : public HExpression<1> {
1946 public:
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001947 HNewArray(HInstruction* length,
1948 uint32_t dex_pc,
1949 uint16_t type_index,
1950 QuickEntrypointEnum entrypoint)
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001951 : HExpression(Primitive::kPrimNot, SideEffects::None()),
1952 dex_pc_(dex_pc),
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001953 type_index_(type_index),
1954 entrypoint_(entrypoint) {
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001955 SetRawInputAt(0, length);
1956 }
1957
1958 uint32_t GetDexPc() const { return dex_pc_; }
1959 uint16_t GetTypeIndex() const { return type_index_; }
1960
1961 // Calls runtime so needs an environment.
Calin Juravle10e244f2015-01-26 18:54:32 +00001962 bool NeedsEnvironment() const OVERRIDE { return true; }
1963
1964 bool CanBeNull() const OVERRIDE { return false; }
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001965
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001966 QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
1967
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001968 DECLARE_INSTRUCTION(NewArray);
1969
1970 private:
1971 const uint32_t dex_pc_;
1972 const uint16_t type_index_;
Nicolas Geoffraycb1b00a2015-01-28 14:50:01 +00001973 const QuickEntrypointEnum entrypoint_;
Nicolas Geoffraya3d05a42014-10-20 17:41:32 +01001974
1975 DISALLOW_COPY_AND_ASSIGN(HNewArray);
1976};
1977
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001978class HAdd : public HBinaryOperation {
1979 public:
1980 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1981 : HBinaryOperation(result_type, left, right) {}
1982
1983 virtual bool IsCommutative() { return true; }
1984
Roland Levillain93445682014-10-06 19:24:02 +01001985 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1986 return x + y;
1987 }
1988 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1989 return x + y;
1990 }
Roland Levillain556c3d12014-09-18 15:25:07 +01001991
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001992 DECLARE_INSTRUCTION(Add);
1993
1994 private:
1995 DISALLOW_COPY_AND_ASSIGN(HAdd);
1996};
1997
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001998class HSub : public HBinaryOperation {
1999 public:
2000 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2001 : HBinaryOperation(result_type, left, right) {}
2002
Roland Levillain93445682014-10-06 19:24:02 +01002003 virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2004 return x - y;
2005 }
2006 virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2007 return x - y;
2008 }
Roland Levillain556c3d12014-09-18 15:25:07 +01002009
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002010 DECLARE_INSTRUCTION(Sub);
2011
2012 private:
2013 DISALLOW_COPY_AND_ASSIGN(HSub);
2014};
2015
Calin Juravle34bacdf2014-10-07 20:23:36 +01002016class HMul : public HBinaryOperation {
2017 public:
2018 HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2019 : HBinaryOperation(result_type, left, right) {}
2020
2021 virtual bool IsCommutative() { return true; }
2022
2023 virtual int32_t Evaluate(int32_t x, int32_t y) const { return x * y; }
2024 virtual int64_t Evaluate(int64_t x, int64_t y) const { return x * y; }
2025
2026 DECLARE_INSTRUCTION(Mul);
2027
2028 private:
2029 DISALLOW_COPY_AND_ASSIGN(HMul);
2030};
2031
Calin Juravle7c4954d2014-10-28 16:57:40 +00002032class HDiv : public HBinaryOperation {
2033 public:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002034 HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2035 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
Calin Juravle7c4954d2014-10-28 16:57:40 +00002036
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002037 virtual int32_t Evaluate(int32_t x, int32_t y) const {
2038 // Our graph structure ensures we never have 0 for `y` during constant folding.
2039 DCHECK_NE(y, 0);
Calin Juravlebacfec32014-11-14 15:54:36 +00002040 // Special case -1 to avoid getting a SIGFPE on x86(_64).
Nicolas Geoffraycd2de0c2014-11-06 15:59:38 +00002041 return (y == -1) ? -x : x / y;
2042 }
Calin Juravlebacfec32014-11-14 15:54:36 +00002043
2044 virtual int64_t Evaluate(int64_t x, int64_t y) const {
2045 DCHECK_NE(y, 0);
2046 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2047 return (y == -1) ? -x : x / y;
2048 }
Calin Juravle7c4954d2014-10-28 16:57:40 +00002049
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002050 uint32_t GetDexPc() const { return dex_pc_; }
2051
Calin Juravle7c4954d2014-10-28 16:57:40 +00002052 DECLARE_INSTRUCTION(Div);
2053
2054 private:
Calin Juravled6fb6cf2014-11-11 19:07:44 +00002055 const uint32_t dex_pc_;
2056
Calin Juravle7c4954d2014-10-28 16:57:40 +00002057 DISALLOW_COPY_AND_ASSIGN(HDiv);
2058};
2059
Calin Juravlebacfec32014-11-14 15:54:36 +00002060class HRem : public HBinaryOperation {
2061 public:
2062 HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2063 : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2064
2065 virtual int32_t Evaluate(int32_t x, int32_t y) const {
2066 DCHECK_NE(y, 0);
2067 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2068 return (y == -1) ? 0 : x % y;
2069 }
2070
2071 virtual int64_t Evaluate(int64_t x, int64_t y) const {
2072 DCHECK_NE(y, 0);
2073 // Special case -1 to avoid getting a SIGFPE on x86(_64).
2074 return (y == -1) ? 0 : x % y;
2075 }
2076
2077 uint32_t GetDexPc() const { return dex_pc_; }
2078
2079 DECLARE_INSTRUCTION(Rem);
2080
2081 private:
2082 const uint32_t dex_pc_;
2083
2084 DISALLOW_COPY_AND_ASSIGN(HRem);
2085};
2086
Calin Juravled0d48522014-11-04 16:40:20 +00002087class HDivZeroCheck : public HExpression<1> {
2088 public:
2089 HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
2090 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2091 SetRawInputAt(0, value);
2092 }
2093
2094 bool CanBeMoved() const OVERRIDE { return true; }
2095
2096 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2097 UNUSED(other);
2098 return true;
2099 }
2100
2101 bool NeedsEnvironment() const OVERRIDE { return true; }
2102 bool CanThrow() const OVERRIDE { return true; }
2103
2104 uint32_t GetDexPc() const { return dex_pc_; }
2105
2106 DECLARE_INSTRUCTION(DivZeroCheck);
2107
2108 private:
2109 const uint32_t dex_pc_;
2110
2111 DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
2112};
2113
Calin Juravle9aec02f2014-11-18 23:06:35 +00002114class HShl : public HBinaryOperation {
2115 public:
2116 HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2117 : HBinaryOperation(result_type, left, right) {}
2118
2119 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
2120 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
2121
2122 DECLARE_INSTRUCTION(Shl);
2123
2124 private:
2125 DISALLOW_COPY_AND_ASSIGN(HShl);
2126};
2127
2128class HShr : public HBinaryOperation {
2129 public:
2130 HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2131 : HBinaryOperation(result_type, left, right) {}
2132
2133 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
2134 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
2135
2136 DECLARE_INSTRUCTION(Shr);
2137
2138 private:
2139 DISALLOW_COPY_AND_ASSIGN(HShr);
2140};
2141
2142class HUShr : public HBinaryOperation {
2143 public:
2144 HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2145 : HBinaryOperation(result_type, left, right) {}
2146
2147 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2148 uint32_t ux = static_cast<uint32_t>(x);
2149 uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
2150 return static_cast<int32_t>(ux >> uy);
2151 }
2152
2153 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2154 uint64_t ux = static_cast<uint64_t>(x);
2155 uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
2156 return static_cast<int64_t>(ux >> uy);
2157 }
2158
2159 DECLARE_INSTRUCTION(UShr);
2160
2161 private:
2162 DISALLOW_COPY_AND_ASSIGN(HUShr);
2163};
2164
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +00002165class HAnd : public HBinaryOperation {
2166 public:
2167 HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2168 : HBinaryOperation(result_type, left, right) {}
2169
2170 bool IsCommutative() OVERRIDE { return true; }
2171
2172 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
2173 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
2174
2175 DECLARE_INSTRUCTION(And);
2176
2177 private:
2178 DISALLOW_COPY_AND_ASSIGN(HAnd);
2179};
2180
2181class HOr : public HBinaryOperation {
2182 public:
2183 HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2184 : HBinaryOperation(result_type, left, right) {}
2185
2186 bool IsCommutative() OVERRIDE { return true; }
2187
2188 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
2189 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
2190
2191 DECLARE_INSTRUCTION(Or);
2192
2193 private:
2194 DISALLOW_COPY_AND_ASSIGN(HOr);
2195};
2196
2197class HXor : public HBinaryOperation {
2198 public:
2199 HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2200 : HBinaryOperation(result_type, left, right) {}
2201
2202 bool IsCommutative() OVERRIDE { return true; }
2203
2204 int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
2205 int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
2206
2207 DECLARE_INSTRUCTION(Xor);
2208
2209 private:
2210 DISALLOW_COPY_AND_ASSIGN(HXor);
2211};
2212
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002213// The value of a parameter in this method. Its location depends on
2214// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07002215class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002216 public:
Calin Juravle10e244f2015-01-26 18:54:32 +00002217 HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
2218 : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002219
2220 uint8_t GetIndex() const { return index_; }
2221
Calin Juravle10e244f2015-01-26 18:54:32 +00002222 bool CanBeNull() const OVERRIDE { return !is_this_; }
2223
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002224 DECLARE_INSTRUCTION(ParameterValue);
2225
2226 private:
2227 // The index of this parameter in the parameters list. Must be less
Calin Juravle10e244f2015-01-26 18:54:32 +00002228 // than HGraph::number_of_in_vregs_.
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002229 const uint8_t index_;
2230
Calin Juravle10e244f2015-01-26 18:54:32 +00002231 // Whether or not the parameter value corresponds to 'this' argument.
2232 const bool is_this_;
2233
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01002234 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
2235};
2236
Roland Levillain1cc5f2512014-10-22 18:06:21 +01002237class HNot : public HUnaryOperation {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002238 public:
Roland Levillain1cc5f2512014-10-22 18:06:21 +01002239 explicit HNot(Primitive::Type result_type, HInstruction* input)
2240 : HUnaryOperation(result_type, input) {}
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002241
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002242 virtual bool CanBeMoved() const { return true; }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002243 virtual bool InstructionDataEquals(HInstruction* other) const {
2244 UNUSED(other);
2245 return true;
2246 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002247
Roland Levillain1cc5f2512014-10-22 18:06:21 +01002248 virtual int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
2249 virtual int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
2250
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01002251 DECLARE_INSTRUCTION(Not);
2252
2253 private:
2254 DISALLOW_COPY_AND_ASSIGN(HNot);
2255};
2256
Roland Levillaindff1f282014-11-05 14:15:05 +00002257class HTypeConversion : public HExpression<1> {
2258 public:
2259 // Instantiate a type conversion of `input` to `result_type`.
Roland Levillain624279f2014-12-04 11:54:28 +00002260 HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
2261 : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
Roland Levillaindff1f282014-11-05 14:15:05 +00002262 SetRawInputAt(0, input);
2263 DCHECK_NE(input->GetType(), result_type);
2264 }
2265
2266 HInstruction* GetInput() const { return InputAt(0); }
2267 Primitive::Type GetInputType() const { return GetInput()->GetType(); }
2268 Primitive::Type GetResultType() const { return GetType(); }
2269
Roland Levillain624279f2014-12-04 11:54:28 +00002270 // Required by the x86 and ARM code generators when producing calls
2271 // to the runtime.
2272 uint32_t GetDexPc() const { return dex_pc_; }
2273
Roland Levillaindff1f282014-11-05 14:15:05 +00002274 bool CanBeMoved() const OVERRIDE { return true; }
Roland Levillained9b1952014-11-06 11:10:17 +00002275 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
Roland Levillaindff1f282014-11-05 14:15:05 +00002276
2277 DECLARE_INSTRUCTION(TypeConversion);
2278
2279 private:
Roland Levillain624279f2014-12-04 11:54:28 +00002280 const uint32_t dex_pc_;
2281
Roland Levillaindff1f282014-11-05 14:15:05 +00002282 DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
2283};
2284
Nicolas Geoffray276d9da2015-02-02 18:24:11 +00002285static constexpr uint32_t kNoRegNumber = -1;
2286
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002287class HPhi : public HInstruction {
2288 public:
2289 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002290 : HInstruction(SideEffects::None()),
2291 inputs_(arena, number_of_inputs),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002292 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002293 type_(type),
Calin Juravle10e244f2015-01-26 18:54:32 +00002294 is_live_(false),
2295 can_be_null_(true) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002296 inputs_.SetSize(number_of_inputs);
2297 }
2298
Calin Juravle10e244f2015-01-26 18:54:32 +00002299 size_t InputCount() const OVERRIDE { return inputs_.Size(); }
2300 HInstruction* InputAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002301
Calin Juravle10e244f2015-01-26 18:54:32 +00002302 void SetRawInputAt(size_t index, HInstruction* input) OVERRIDE {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002303 inputs_.Put(index, input);
2304 }
2305
2306 void AddInput(HInstruction* input);
2307
Calin Juravle10e244f2015-01-26 18:54:32 +00002308 Primitive::Type GetType() const OVERRIDE { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002309 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002310
Calin Juravle10e244f2015-01-26 18:54:32 +00002311 bool CanBeNull() const OVERRIDE { return can_be_null_; }
2312 void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
2313
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002314 uint32_t GetRegNumber() const { return reg_number_; }
2315
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002316 void SetDead() { is_live_ = false; }
2317 void SetLive() { is_live_ = true; }
2318 bool IsDead() const { return !is_live_; }
2319 bool IsLive() const { return is_live_; }
2320
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002321 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002322
Nicolas Geoffray96f89a22014-07-11 10:57:49 +01002323 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002324 GrowableArray<HInstruction*> inputs_;
2325 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01002326 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01002327 bool is_live_;
Calin Juravle10e244f2015-01-26 18:54:32 +00002328 bool can_be_null_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002329
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01002330 DISALLOW_COPY_AND_ASSIGN(HPhi);
2331};
2332
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002333class HNullCheck : public HExpression<1> {
2334 public:
2335 HNullCheck(HInstruction* value, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002336 : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002337 SetRawInputAt(0, value);
2338 }
2339
Calin Juravle10e244f2015-01-26 18:54:32 +00002340 bool CanBeMoved() const OVERRIDE { return true; }
2341 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002342 UNUSED(other);
2343 return true;
2344 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002345
Calin Juravle10e244f2015-01-26 18:54:32 +00002346 bool NeedsEnvironment() const OVERRIDE { return true; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002347
Calin Juravle10e244f2015-01-26 18:54:32 +00002348 bool CanThrow() const OVERRIDE { return true; }
2349
2350 bool CanBeNull() const OVERRIDE { return false; }
Roland Levillaine161a2a2014-10-03 12:45:18 +01002351
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002352 uint32_t GetDexPc() const { return dex_pc_; }
2353
2354 DECLARE_INSTRUCTION(NullCheck);
2355
2356 private:
2357 const uint32_t dex_pc_;
2358
2359 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
2360};
2361
2362class FieldInfo : public ValueObject {
2363 public:
Calin Juravle52c48962014-12-16 17:02:57 +00002364 FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
2365 : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002366
2367 MemberOffset GetFieldOffset() const { return field_offset_; }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002368 Primitive::Type GetFieldType() const { return field_type_; }
Calin Juravle52c48962014-12-16 17:02:57 +00002369 bool IsVolatile() const { return is_volatile_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002370
2371 private:
2372 const MemberOffset field_offset_;
Nicolas Geoffray39468442014-09-02 15:17:15 +01002373 const Primitive::Type field_type_;
Calin Juravle52c48962014-12-16 17:02:57 +00002374 const bool is_volatile_;
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002375};
2376
2377class HInstanceFieldGet : public HExpression<1> {
2378 public:
2379 HInstanceFieldGet(HInstruction* value,
2380 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002381 MemberOffset field_offset,
2382 bool is_volatile)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002383 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002384 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002385 SetRawInputAt(0, value);
2386 }
2387
Calin Juravle10c9cbe2014-12-19 10:50:19 +00002388 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002389
2390 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2391 HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
2392 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002393 }
2394
Calin Juravle77520bc2015-01-12 18:45:46 +00002395 bool CanDoImplicitNullCheck() const OVERRIDE {
2396 return GetFieldOffset().Uint32Value() < kPageSize;
2397 }
2398
2399 size_t ComputeHashCode() const OVERRIDE {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +01002400 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
2401 }
2402
Calin Juravle52c48962014-12-16 17:02:57 +00002403 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002404 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002405 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002406 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002407
2408 DECLARE_INSTRUCTION(InstanceFieldGet);
2409
2410 private:
2411 const FieldInfo field_info_;
2412
2413 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
2414};
2415
2416class HInstanceFieldSet : public HTemplateInstruction<2> {
2417 public:
2418 HInstanceFieldSet(HInstruction* object,
2419 HInstruction* value,
Nicolas Geoffray39468442014-09-02 15:17:15 +01002420 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002421 MemberOffset field_offset,
2422 bool is_volatile)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002423 : HTemplateInstruction(SideEffects::ChangesSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002424 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002425 SetRawInputAt(0, object);
2426 SetRawInputAt(1, value);
2427 }
2428
Calin Juravle77520bc2015-01-12 18:45:46 +00002429 bool CanDoImplicitNullCheck() const OVERRIDE {
2430 return GetFieldOffset().Uint32Value() < kPageSize;
2431 }
2432
Calin Juravle52c48962014-12-16 17:02:57 +00002433 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002434 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002435 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002436 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002437 HInstruction* GetValue() const { return InputAt(1); }
2438
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002439 DECLARE_INSTRUCTION(InstanceFieldSet);
2440
2441 private:
2442 const FieldInfo field_info_;
2443
2444 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
2445};
2446
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002447class HArrayGet : public HExpression<2> {
2448 public:
2449 HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002450 : HExpression(type, SideEffects::DependsOnSomething()) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002451 SetRawInputAt(0, array);
2452 SetRawInputAt(1, index);
2453 }
2454
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002455 bool CanBeMoved() const OVERRIDE { return true; }
2456 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002457 UNUSED(other);
2458 return true;
2459 }
Calin Juravle77520bc2015-01-12 18:45:46 +00002460 bool CanDoImplicitNullCheck() const OVERRIDE {
2461 // TODO: We can be smarter here.
2462 // Currently, the array access is always preceded by an ArrayLength or a NullCheck
2463 // which generates the implicit null check. There are cases when these can be removed
2464 // to produce better code. If we ever add optimizations to do so we should allow an
2465 // implicit check here (as long as the address falls in the first page).
2466 return false;
2467 }
2468
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002469 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002470
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002471 HInstruction* GetArray() const { return InputAt(0); }
2472 HInstruction* GetIndex() const { return InputAt(1); }
2473
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002474 DECLARE_INSTRUCTION(ArrayGet);
2475
2476 private:
2477 DISALLOW_COPY_AND_ASSIGN(HArrayGet);
2478};
2479
2480class HArraySet : public HTemplateInstruction<3> {
2481 public:
2482 HArraySet(HInstruction* array,
2483 HInstruction* index,
2484 HInstruction* value,
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002485 Primitive::Type expected_component_type,
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002486 uint32_t dex_pc)
2487 : HTemplateInstruction(SideEffects::ChangesSomething()),
2488 dex_pc_(dex_pc),
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002489 expected_component_type_(expected_component_type),
2490 needs_type_check_(value->GetType() == Primitive::kPrimNot) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002491 SetRawInputAt(0, array);
2492 SetRawInputAt(1, index);
2493 SetRawInputAt(2, value);
2494 }
2495
Calin Juravle77520bc2015-01-12 18:45:46 +00002496 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002497 // We currently always call a runtime method to catch array store
2498 // exceptions.
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002499 return needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002500 }
2501
Calin Juravle77520bc2015-01-12 18:45:46 +00002502 bool CanDoImplicitNullCheck() const OVERRIDE {
2503 // TODO: Same as for ArrayGet.
2504 return false;
2505 }
2506
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002507 void ClearNeedsTypeCheck() {
2508 needs_type_check_ = false;
2509 }
2510
2511 bool NeedsTypeCheck() const { return needs_type_check_; }
2512
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002513 uint32_t GetDexPc() const { return dex_pc_; }
2514
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002515 HInstruction* GetArray() const { return InputAt(0); }
2516 HInstruction* GetIndex() const { return InputAt(1); }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002517 HInstruction* GetValue() const { return InputAt(2); }
2518
2519 Primitive::Type GetComponentType() const {
2520 // The Dex format does not type floating point index operations. Since the
2521 // `expected_component_type_` is set during building and can therefore not
2522 // be correct, we also check what is the value type. If it is a floating
2523 // point type, we must use that type.
2524 Primitive::Type value_type = GetValue()->GetType();
2525 return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
2526 ? value_type
2527 : expected_component_type_;
2528 }
Nicolas Geoffray39468442014-09-02 15:17:15 +01002529
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002530 DECLARE_INSTRUCTION(ArraySet);
2531
2532 private:
2533 const uint32_t dex_pc_;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01002534 const Primitive::Type expected_component_type_;
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002535 bool needs_type_check_;
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002536
2537 DISALLOW_COPY_AND_ASSIGN(HArraySet);
2538};
2539
2540class HArrayLength : public HExpression<1> {
2541 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002542 explicit HArrayLength(HInstruction* array)
2543 : HExpression(Primitive::kPrimInt, SideEffects::None()) {
2544 // Note that arrays do not change length, so the instruction does not
2545 // depend on any write.
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002546 SetRawInputAt(0, array);
2547 }
2548
Calin Juravle77520bc2015-01-12 18:45:46 +00002549 bool CanBeMoved() const OVERRIDE { return true; }
2550 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002551 UNUSED(other);
2552 return true;
2553 }
Calin Juravle77520bc2015-01-12 18:45:46 +00002554 bool CanDoImplicitNullCheck() const OVERRIDE { return true; }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002555
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002556 DECLARE_INSTRUCTION(ArrayLength);
2557
2558 private:
2559 DISALLOW_COPY_AND_ASSIGN(HArrayLength);
2560};
2561
2562class HBoundsCheck : public HExpression<2> {
2563 public:
2564 HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002565 : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002566 DCHECK(index->GetType() == Primitive::kPrimInt);
2567 SetRawInputAt(0, index);
2568 SetRawInputAt(1, length);
2569 }
2570
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002571 virtual bool CanBeMoved() const { return true; }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002572 virtual bool InstructionDataEquals(HInstruction* other) const {
2573 UNUSED(other);
2574 return true;
2575 }
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002576
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002577 virtual bool NeedsEnvironment() const { return true; }
2578
Roland Levillaine161a2a2014-10-03 12:45:18 +01002579 virtual bool CanThrow() const { return true; }
2580
Nicolas Geoffray3c7bb982014-07-23 16:04:16 +01002581 uint32_t GetDexPc() const { return dex_pc_; }
2582
2583 DECLARE_INSTRUCTION(BoundsCheck);
2584
2585 private:
2586 const uint32_t dex_pc_;
2587
2588 DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
2589};
2590
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002591/**
2592 * Some DEX instructions are folded into multiple HInstructions that need
2593 * to stay live until the last HInstruction. This class
2594 * is used as a marker for the baseline compiler to ensure its preceding
Calin Juravlef97f9fb2014-11-11 15:38:19 +00002595 * HInstruction stays live. `index` represents the stack location index of the
2596 * instruction (the actual offset is computed as index * vreg_size).
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002597 */
2598class HTemporary : public HTemplateInstruction<0> {
2599 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01002600 explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002601
2602 size_t GetIndex() const { return index_; }
2603
Nicolas Geoffray421e9f92014-11-11 18:21:53 +00002604 Primitive::Type GetType() const OVERRIDE {
2605 // The previous instruction is the one that will be stored in the temporary location.
2606 DCHECK(GetPrevious() != nullptr);
2607 return GetPrevious()->GetType();
2608 }
Nicolas Geoffrayf43083d2014-11-07 10:48:10 +00002609
Nicolas Geoffraye5038322014-07-04 09:41:32 +01002610 DECLARE_INSTRUCTION(Temporary);
2611
2612 private:
2613 const size_t index_;
2614
2615 DISALLOW_COPY_AND_ASSIGN(HTemporary);
2616};
2617
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00002618class HSuspendCheck : public HTemplateInstruction<0> {
2619 public:
2620 explicit HSuspendCheck(uint32_t dex_pc)
Nicolas Geoffray9ebc72c2014-09-25 16:33:42 +01002621 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {}
Nicolas Geoffrayfbc695f2014-09-15 15:33:30 +00002622
2623 virtual bool NeedsEnvironment() const {
2624 return true;
2625 }
2626
2627 uint32_t GetDexPc() const { return dex_pc_; }
2628
2629 DECLARE_INSTRUCTION(SuspendCheck);
2630
2631 private:
2632 const uint32_t dex_pc_;
2633
2634 DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
2635};
2636
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002637/**
2638 * Instruction to load a Class object.
2639 */
2640class HLoadClass : public HExpression<0> {
2641 public:
2642 HLoadClass(uint16_t type_index,
2643 bool is_referrers_class,
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002644 uint32_t dex_pc)
2645 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2646 type_index_(type_index),
2647 is_referrers_class_(is_referrers_class),
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002648 dex_pc_(dex_pc),
2649 generate_clinit_check_(false) {}
2650
2651 bool CanBeMoved() const OVERRIDE { return true; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002652
2653 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2654 return other->AsLoadClass()->type_index_ == type_index_;
2655 }
2656
2657 size_t ComputeHashCode() const OVERRIDE { return type_index_; }
2658
2659 uint32_t GetDexPc() const { return dex_pc_; }
2660 uint16_t GetTypeIndex() const { return type_index_; }
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002661 bool IsReferrersClass() const { return is_referrers_class_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002662
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002663 bool NeedsEnvironment() const OVERRIDE {
2664 // Will call runtime and load the class if the class is not loaded yet.
2665 // TODO: finer grain decision.
2666 return !is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002667 }
2668
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002669 bool MustGenerateClinitCheck() const {
2670 return generate_clinit_check_;
2671 }
2672
2673 void SetMustGenerateClinitCheck() {
2674 generate_clinit_check_ = true;
2675 }
2676
2677 bool CanCallRuntime() const {
2678 return MustGenerateClinitCheck() || !is_referrers_class_;
2679 }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002680
Nicolas Geoffray82091da2015-01-26 10:02:45 +00002681 bool CanThrow() const OVERRIDE {
2682 // May call runtime and and therefore can throw.
2683 // TODO: finer grain decision.
2684 return !is_referrers_class_;
2685 }
2686
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002687 DECLARE_INSTRUCTION(LoadClass);
2688
2689 private:
2690 const uint16_t type_index_;
2691 const bool is_referrers_class_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002692 const uint32_t dex_pc_;
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002693 // Whether this instruction must generate the initialization check.
2694 // Used for code generation.
2695 bool generate_clinit_check_;
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002696
2697 DISALLOW_COPY_AND_ASSIGN(HLoadClass);
2698};
2699
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002700class HLoadString : public HExpression<0> {
2701 public:
2702 HLoadString(uint32_t string_index, uint32_t dex_pc)
2703 : HExpression(Primitive::kPrimNot, SideEffects::None()),
2704 string_index_(string_index),
2705 dex_pc_(dex_pc) {}
2706
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002707 bool CanBeMoved() const OVERRIDE { return true; }
2708
Nicolas Geoffrayb5f62b32014-10-30 10:58:41 +00002709 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2710 return other->AsLoadString()->string_index_ == string_index_;
2711 }
2712
2713 size_t ComputeHashCode() const OVERRIDE { return string_index_; }
2714
2715 uint32_t GetDexPc() const { return dex_pc_; }
2716 uint32_t GetStringIndex() const { return string_index_; }
2717
2718 // TODO: Can we deopt or debug when we resolve a string?
2719 bool NeedsEnvironment() const OVERRIDE { return false; }
2720
2721 DECLARE_INSTRUCTION(LoadString);
2722
2723 private:
2724 const uint32_t string_index_;
2725 const uint32_t dex_pc_;
2726
2727 DISALLOW_COPY_AND_ASSIGN(HLoadString);
2728};
2729
Nicolas Geoffraye53798a2014-12-01 10:31:54 +00002730// TODO: Pass this check to HInvokeStaticOrDirect nodes.
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002731/**
2732 * Performs an initialization check on its Class object input.
2733 */
2734class HClinitCheck : public HExpression<1> {
2735 public:
2736 explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
2737 : HExpression(Primitive::kPrimNot, SideEffects::All()),
2738 dex_pc_(dex_pc) {
2739 SetRawInputAt(0, constant);
2740 }
2741
Nicolas Geoffray424f6762014-11-03 14:51:25 +00002742 bool CanBeMoved() const OVERRIDE { return true; }
2743 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2744 UNUSED(other);
2745 return true;
2746 }
2747
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002748 bool NeedsEnvironment() const OVERRIDE {
2749 // May call runtime to initialize the class.
2750 return true;
2751 }
2752
2753 uint32_t GetDexPc() const { return dex_pc_; }
2754
2755 HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
2756
2757 DECLARE_INSTRUCTION(ClinitCheck);
2758
2759 private:
2760 const uint32_t dex_pc_;
2761
2762 DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
2763};
2764
2765class HStaticFieldGet : public HExpression<1> {
2766 public:
2767 HStaticFieldGet(HInstruction* cls,
2768 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002769 MemberOffset field_offset,
2770 bool is_volatile)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002771 : HExpression(field_type, SideEffects::DependsOnSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002772 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002773 SetRawInputAt(0, cls);
2774 }
2775
Calin Juravle52c48962014-12-16 17:02:57 +00002776
Calin Juravle10c9cbe2014-12-19 10:50:19 +00002777 bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002778
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002779 bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
Calin Juravle52c48962014-12-16 17:02:57 +00002780 HStaticFieldGet* other_get = other->AsStaticFieldGet();
2781 return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002782 }
2783
2784 size_t ComputeHashCode() const OVERRIDE {
2785 return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
2786 }
2787
Calin Juravle52c48962014-12-16 17:02:57 +00002788 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002789 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2790 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002791 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002792
2793 DECLARE_INSTRUCTION(StaticFieldGet);
2794
2795 private:
2796 const FieldInfo field_info_;
2797
2798 DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
2799};
2800
2801class HStaticFieldSet : public HTemplateInstruction<2> {
2802 public:
2803 HStaticFieldSet(HInstruction* cls,
2804 HInstruction* value,
2805 Primitive::Type field_type,
Calin Juravle52c48962014-12-16 17:02:57 +00002806 MemberOffset field_offset,
2807 bool is_volatile)
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002808 : HTemplateInstruction(SideEffects::ChangesSomething()),
Calin Juravle52c48962014-12-16 17:02:57 +00002809 field_info_(field_offset, field_type, is_volatile) {
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002810 SetRawInputAt(0, cls);
2811 SetRawInputAt(1, value);
2812 }
2813
Calin Juravle52c48962014-12-16 17:02:57 +00002814 const FieldInfo& GetFieldInfo() const { return field_info_; }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002815 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2816 Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
Calin Juravle52c48962014-12-16 17:02:57 +00002817 bool IsVolatile() const { return field_info_.IsVolatile(); }
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002818
Nicolas Geoffrayaf07bc12014-11-12 18:08:09 +00002819 HInstruction* GetValue() const { return InputAt(1); }
2820
Nicolas Geoffray19a19cf2014-10-22 16:07:05 +01002821 DECLARE_INSTRUCTION(StaticFieldSet);
2822
2823 private:
2824 const FieldInfo field_info_;
2825
2826 DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
2827};
2828
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002829// Implement the move-exception DEX instruction.
2830class HLoadException : public HExpression<0> {
2831 public:
2832 HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
2833
2834 DECLARE_INSTRUCTION(LoadException);
2835
2836 private:
2837 DISALLOW_COPY_AND_ASSIGN(HLoadException);
2838};
2839
2840class HThrow : public HTemplateInstruction<1> {
2841 public:
2842 HThrow(HInstruction* exception, uint32_t dex_pc)
2843 : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
2844 SetRawInputAt(0, exception);
2845 }
2846
2847 bool IsControlFlow() const OVERRIDE { return true; }
2848
2849 bool NeedsEnvironment() const OVERRIDE { return true; }
2850
Nicolas Geoffray82091da2015-01-26 10:02:45 +00002851 bool CanThrow() const OVERRIDE { return true; }
2852
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002853 uint32_t GetDexPc() const { return dex_pc_; }
2854
2855 DECLARE_INSTRUCTION(Throw);
2856
2857 private:
Nicolas Geoffray82091da2015-01-26 10:02:45 +00002858 const uint32_t dex_pc_;
Nicolas Geoffrayde58ab22014-11-05 12:46:03 +00002859
2860 DISALLOW_COPY_AND_ASSIGN(HThrow);
2861};
2862
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002863class HInstanceOf : public HExpression<2> {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002864 public:
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002865 HInstanceOf(HInstruction* object,
2866 HLoadClass* constant,
2867 bool class_is_final,
2868 uint32_t dex_pc)
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002869 : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
2870 class_is_final_(class_is_final),
2871 dex_pc_(dex_pc) {
2872 SetRawInputAt(0, object);
2873 SetRawInputAt(1, constant);
2874 }
2875
2876 bool CanBeMoved() const OVERRIDE { return true; }
2877
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002878 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002879 return true;
2880 }
2881
2882 bool NeedsEnvironment() const OVERRIDE {
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002883 return false;
2884 }
2885
2886 uint32_t GetDexPc() const { return dex_pc_; }
2887
2888 bool IsClassFinal() const { return class_is_final_; }
2889
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002890 DECLARE_INSTRUCTION(InstanceOf);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002891
2892 private:
2893 const bool class_is_final_;
2894 const uint32_t dex_pc_;
2895
Nicolas Geoffray57a88d42014-11-10 15:09:21 +00002896 DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
2897};
2898
2899class HCheckCast : public HTemplateInstruction<2> {
2900 public:
2901 HCheckCast(HInstruction* object,
2902 HLoadClass* constant,
2903 bool class_is_final,
2904 uint32_t dex_pc)
2905 : HTemplateInstruction(SideEffects::None()),
2906 class_is_final_(class_is_final),
2907 dex_pc_(dex_pc) {
2908 SetRawInputAt(0, object);
2909 SetRawInputAt(1, constant);
2910 }
2911
2912 bool CanBeMoved() const OVERRIDE { return true; }
2913
2914 bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2915 return true;
2916 }
2917
2918 bool NeedsEnvironment() const OVERRIDE {
2919 // Instruction may throw a CheckCastError.
2920 return true;
2921 }
2922
2923 bool CanThrow() const OVERRIDE { return true; }
2924
2925 uint32_t GetDexPc() const { return dex_pc_; }
2926
2927 bool IsClassFinal() const { return class_is_final_; }
2928
2929 DECLARE_INSTRUCTION(CheckCast);
2930
2931 private:
2932 const bool class_is_final_;
2933 const uint32_t dex_pc_;
2934
2935 DISALLOW_COPY_AND_ASSIGN(HCheckCast);
Nicolas Geoffray6f5c41f2014-11-06 08:59:20 +00002936};
2937
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002938class HMonitorOperation : public HTemplateInstruction<1> {
2939 public:
2940 enum OperationKind {
2941 kEnter,
2942 kExit,
2943 };
2944
2945 HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
2946 : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
2947 SetRawInputAt(0, object);
2948 }
2949
2950 // Instruction may throw a Java exception, so we need an environment.
2951 bool NeedsEnvironment() const OVERRIDE { return true; }
2952 bool CanThrow() const OVERRIDE { return true; }
2953
2954 uint32_t GetDexPc() const { return dex_pc_; }
2955
2956 bool IsEnter() const { return kind_ == kEnter; }
2957
2958 DECLARE_INSTRUCTION(MonitorOperation);
2959
Calin Juravle52c48962014-12-16 17:02:57 +00002960 private:
Nicolas Geoffrayb7baf5c2014-11-11 16:29:44 +00002961 const OperationKind kind_;
2962 const uint32_t dex_pc_;
2963
2964 private:
2965 DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
2966};
2967
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07002968class MoveOperands : public ArenaObject<kArenaAllocMisc> {
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01002969 public:
Nicolas Geoffray740475d2014-09-29 10:33:25 +01002970 MoveOperands(Location source, Location destination, HInstruction* instruction)
2971 : source_(source), destination_(destination), instruction_(instruction) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01002972
2973 Location GetSource() const { return source_; }
2974 Location GetDestination() const { return destination_; }
2975
2976 void SetSource(Location value) { source_ = value; }
2977 void SetDestination(Location value) { destination_ = value; }
2978
2979 // The parallel move resolver marks moves as "in-progress" by clearing the
2980 // destination (but not the source).
2981 Location MarkPending() {
2982 DCHECK(!IsPending());
2983 Location dest = destination_;
2984 destination_ = Location::NoLocation();
2985 return dest;
2986 }
2987
2988 void ClearPending(Location dest) {
2989 DCHECK(IsPending());
2990 destination_ = dest;
2991 }
2992
2993 bool IsPending() const {
2994 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
2995 return destination_.IsInvalid() && !source_.IsInvalid();
2996 }
2997
2998 // True if this blocks a move from the given location.
2999 bool Blocks(Location loc) const {
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003000 return !IsEliminated() && (source_.Contains(loc) || loc.Contains(source_));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003001 }
3002
3003 // A move is redundant if it's been eliminated, if its source and
3004 // destination are the same, or if its destination is unneeded.
3005 bool IsRedundant() const {
3006 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
3007 }
3008
3009 // We clear both operands to indicate move that's been eliminated.
3010 void Eliminate() {
3011 source_ = destination_ = Location::NoLocation();
3012 }
3013
3014 bool IsEliminated() const {
3015 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3016 return source_.IsInvalid();
3017 }
3018
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003019 HInstruction* GetInstruction() const { return instruction_; }
3020
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003021 private:
3022 Location source_;
3023 Location destination_;
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003024 // The instruction this move is assocatied with. Null when this move is
3025 // for moving an input in the expected locations of user (including a phi user).
3026 // This is only used in debug mode, to ensure we do not connect interval siblings
3027 // in the same parallel move.
3028 HInstruction* instruction_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003029};
3030
3031static constexpr size_t kDefaultNumberOfMoves = 4;
3032
3033class HParallelMove : public HTemplateInstruction<0> {
3034 public:
Nicolas Geoffray065bf772014-09-03 14:51:22 +01003035 explicit HParallelMove(ArenaAllocator* arena)
3036 : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003037
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003038 void AddMove(Location source, Location destination, HInstruction* instruction) {
3039 DCHECK(source.IsValid());
3040 DCHECK(destination.IsValid());
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003041 if (kIsDebugBuild) {
3042 if (instruction != nullptr) {
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00003043 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003044 DCHECK_NE(moves_.Get(i).GetInstruction(), instruction)
3045 << "Doing parallel moves for the same instruction.";
Nicolas Geoffraydd8f8872015-01-15 15:37:37 +00003046 }
3047 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003048 for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
3049 DCHECK(!destination.Equals(moves_.Get(i).GetDestination()))
3050 << "Same destination for two moves in a parallel move.";
3051 }
Nicolas Geoffray740475d2014-09-29 10:33:25 +01003052 }
Nicolas Geoffrayf7a0c4e2015-02-10 17:08:47 +00003053 moves_.Add(MoveOperands(source, destination, instruction));
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003054 }
3055
3056 MoveOperands* MoveOperandsAt(size_t index) const {
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003057 return moves_.GetRawStorage() + index;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003058 }
3059
3060 size_t NumMoves() const { return moves_.Size(); }
3061
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01003062 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003063
3064 private:
Nicolas Geoffray42d1f5f2015-01-16 09:14:18 +00003065 GrowableArray<MoveOperands> moves_;
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01003066
3067 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
3068};
3069
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003070class HGraphVisitor : public ValueObject {
3071 public:
Dave Allison20dfc792014-06-16 20:44:29 -07003072 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
3073 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003074
Ian Rogers6a3c1fc2014-10-31 00:33:20 -07003075 virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003076 virtual void VisitBasicBlock(HBasicBlock* block);
3077
Roland Levillain633021e2014-10-01 14:12:25 +01003078 // Visit the graph following basic block insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003079 void VisitInsertionOrder();
3080
Roland Levillain633021e2014-10-01 14:12:25 +01003081 // Visit the graph following dominator tree reverse post-order.
3082 void VisitReversePostOrder();
3083
Nicolas Geoffray787c3072014-03-17 10:20:19 +00003084 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00003085
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003086 // Visit functions for instruction classes.
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003087#define DECLARE_VISIT_INSTRUCTION(name, super) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003088 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
3089
3090 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3091
3092#undef DECLARE_VISIT_INSTRUCTION
3093
3094 private:
Ian Rogerscf7f1912014-10-22 22:06:39 -07003095 HGraph* const graph_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003096
3097 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
3098};
3099
Nicolas Geoffray360231a2014-10-08 21:07:48 +01003100class HGraphDelegateVisitor : public HGraphVisitor {
3101 public:
3102 explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
3103 virtual ~HGraphDelegateVisitor() {}
3104
3105 // Visit functions that delegate to to super class.
3106#define DECLARE_VISIT_INSTRUCTION(name, super) \
3107 virtual void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
3108
3109 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3110
3111#undef DECLARE_VISIT_INSTRUCTION
3112
3113 private:
3114 DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
3115};
3116
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003117class HInsertionOrderIterator : public ValueObject {
3118 public:
3119 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
3120
3121 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
3122 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
3123 void Advance() { ++index_; }
3124
3125 private:
3126 const HGraph& graph_;
3127 size_t index_;
3128
3129 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
3130};
3131
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003132class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003133 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003134 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003135
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003136 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
3137 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003138 void Advance() { ++index_; }
3139
3140 private:
3141 const HGraph& graph_;
3142 size_t index_;
3143
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003144 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003145};
3146
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003147class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003148 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003149 explicit HPostOrderIterator(const HGraph& graph)
3150 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003151
3152 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003153 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003154 void Advance() { --index_; }
3155
3156 private:
3157 const HGraph& graph_;
3158 size_t index_;
3159
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01003160 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01003161};
3162
Nicolas Geoffray82091da2015-01-26 10:02:45 +00003163// Iterator over the blocks that art part of the loop. Includes blocks part
3164// of an inner loop. The order in which the blocks are iterated is on their
3165// block id.
3166class HBlocksInLoopIterator : public ValueObject {
3167 public:
3168 explicit HBlocksInLoopIterator(const HLoopInformation& info)
3169 : blocks_in_loop_(info.GetBlocks()),
3170 blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
3171 index_(0) {
3172 if (!blocks_in_loop_.IsBitSet(index_)) {
3173 Advance();
3174 }
3175 }
3176
3177 bool Done() const { return index_ == blocks_.Size(); }
3178 HBasicBlock* Current() const { return blocks_.Get(index_); }
3179 void Advance() {
3180 ++index_;
3181 for (size_t e = blocks_.Size(); index_ < e; ++index_) {
3182 if (blocks_in_loop_.IsBitSet(index_)) {
3183 break;
3184 }
3185 }
3186 }
3187
3188 private:
3189 const BitVector& blocks_in_loop_;
3190 const GrowableArray<HBasicBlock*>& blocks_;
3191 size_t index_;
3192
3193 DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
3194};
3195
Nicolas Geoffray818f2102014-02-18 16:43:35 +00003196} // namespace art
3197
3198#endif // ART_COMPILER_OPTIMIZING_NODES_H_