blob: 689aab08b3252f9d4e63998e0ad41bf8070ece01 [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 Geoffray4e3d23a2014-05-22 18:32:45 +010020#include "locations.h"
Nicolas Geoffraye5038322014-07-04 09:41:32 +010021#include "offsets.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000022#include "utils/allocation.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000023#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000024#include "utils/growable_array.h"
25
26namespace art {
27
28class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010029class HEnvironment;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000030class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000031class HIntConstant;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000032class HGraphVisitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010033class HPhi;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +010034class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000035class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000036
37static const int kDefaultNumberOfBlocks = 8;
38static const int kDefaultNumberOfSuccessors = 2;
39static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000040static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000041
Dave Allison20dfc792014-06-16 20:44:29 -070042enum IfCondition {
43 kCondEQ,
44 kCondNE,
45 kCondLT,
46 kCondLE,
47 kCondGT,
48 kCondGE,
49};
50
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010051class HInstructionList {
52 public:
53 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
54
55 void AddInstruction(HInstruction* instruction);
56 void RemoveInstruction(HInstruction* instruction);
57
58 private:
59 HInstruction* first_instruction_;
60 HInstruction* last_instruction_;
61
62 friend class HBasicBlock;
63 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +010064 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010065
66 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
67};
68
Nicolas Geoffray818f2102014-02-18 16:43:35 +000069// Control-flow graph of a method. Contains a list of basic blocks.
70class HGraph : public ArenaObject {
71 public:
72 explicit HGraph(ArenaAllocator* arena)
73 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000074 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010075 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010076 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010077 number_of_vregs_(0),
78 number_of_in_vregs_(0),
Nicolas Geoffraye5038322014-07-04 09:41:32 +010079 number_of_temporaries_(0),
Dave Allison20dfc792014-06-16 20:44:29 -070080 current_instruction_id_(0) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +000081
Nicolas Geoffray787c3072014-03-17 10:20:19 +000082 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +010083 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000084
Nicolas Geoffray787c3072014-03-17 10:20:19 +000085 HBasicBlock* GetEntryBlock() const { return entry_block_; }
86 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000087
Nicolas Geoffray787c3072014-03-17 10:20:19 +000088 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
89 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000090
Nicolas Geoffray818f2102014-02-18 16:43:35 +000091 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010092
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000093 void BuildDominatorTree();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010094 void TransformToSSA();
95 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000096
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010097 // Find all natural loops in this graph. Aborts computation and returns false
Nicolas Geoffrayf635e632014-05-14 09:43:38 +010098 // if one loop is not natural, that is the header does not dominate the back
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010099 // edge.
100 bool FindNaturalLoops() const;
101
102 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
103 void SimplifyLoop(HBasicBlock* header);
104
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000105 int GetNextInstructionId() {
106 return current_instruction_id_++;
107 }
108
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100109 uint16_t GetMaximumNumberOfOutVRegs() const {
110 return maximum_number_of_out_vregs_;
111 }
112
113 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
114 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
115 }
116
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100117 void UpdateNumberOfTemporaries(size_t count) {
118 number_of_temporaries_ = std::max(count, number_of_temporaries_);
119 }
120
121 size_t GetNumberOfTemporaries() const {
122 return number_of_temporaries_;
123 }
124
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100125 void SetNumberOfVRegs(uint16_t number_of_vregs) {
126 number_of_vregs_ = number_of_vregs;
127 }
128
129 uint16_t GetNumberOfVRegs() const {
130 return number_of_vregs_;
131 }
132
133 void SetNumberOfInVRegs(uint16_t value) {
134 number_of_in_vregs_ = value;
135 }
136
137 uint16_t GetNumberOfInVRegs() const {
138 return number_of_in_vregs_;
139 }
140
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100141 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
142 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100143 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100144
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000145 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000146 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
147 void VisitBlockForDominatorTree(HBasicBlock* block,
148 HBasicBlock* predecessor,
149 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100150 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000151 void VisitBlockForBackEdges(HBasicBlock* block,
152 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100153 ArenaBitVector* visiting);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000154 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
155
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000156 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000157
158 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000159 GrowableArray<HBasicBlock*> blocks_;
160
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100161 // List of blocks to perform a reverse post order tree traversal.
162 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000163
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000164 HBasicBlock* entry_block_;
165 HBasicBlock* exit_block_;
166
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100167 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100168 uint16_t maximum_number_of_out_vregs_;
169
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100170 // The number of virtual registers in this method. Contains the parameters.
171 uint16_t number_of_vregs_;
172
173 // The number of virtual registers used by parameters of this method.
174 uint16_t number_of_in_vregs_;
175
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100176 // The number of temporaries that will be needed for the baseline compiler.
177 size_t number_of_temporaries_;
178
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000179 // The current id to assign to a newly added instruction. See HInstruction.id_.
180 int current_instruction_id_;
181
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000182 DISALLOW_COPY_AND_ASSIGN(HGraph);
183};
184
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000185class HLoopInformation : public ArenaObject {
186 public:
187 HLoopInformation(HBasicBlock* header, HGraph* graph)
188 : header_(header),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100189 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
190 blocks_(graph->GetArena(), graph->GetBlocks().Size(), false) {}
191
192 HBasicBlock* GetHeader() const {
193 return header_;
194 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000195
196 void AddBackEdge(HBasicBlock* back_edge) {
197 back_edges_.Add(back_edge);
198 }
199
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100200 void RemoveBackEdge(HBasicBlock* back_edge) {
201 back_edges_.Delete(back_edge);
202 }
203
204 bool IsBackEdge(HBasicBlock* block) {
205 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
206 if (back_edges_.Get(i) == block) return true;
207 }
208 return false;
209 }
210
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000211 int NumberOfBackEdges() const {
212 return back_edges_.Size();
213 }
214
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100215 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100216
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100217 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
218 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100219 }
220
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100221 void ClearBackEdges() {
222 back_edges_.Reset();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100223 }
224
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100225 // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
226 // that is the header dominates the back edge.
227 bool Populate();
228
229 // Returns whether this loop information contains `block`.
230 // Note that this loop information *must* be populated before entering this function.
231 bool Contains(const HBasicBlock& block) const;
232
233 // Returns whether this loop information is an inner loop of `other`.
234 // Note that `other` *must* be populated before entering this function.
235 bool IsIn(const HLoopInformation& other) const;
236
237 const ArenaBitVector& GetBlocks() const { return blocks_; }
238
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000239 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100240 // Internal recursive implementation of `Populate`.
241 void PopulateRecursive(HBasicBlock* block);
242
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000243 HBasicBlock* header_;
244 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100245 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000246
247 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
248};
249
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100250static constexpr size_t kNoLifetime = -1;
251
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000252// A block in a method. Contains the list of instructions represented
253// as a double linked list. Each block knows its predecessors and
254// successors.
255class HBasicBlock : public ArenaObject {
256 public:
257 explicit HBasicBlock(HGraph* graph)
258 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000259 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
260 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000261 loop_information_(nullptr),
262 dominator_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100263 block_id_(-1),
264 lifetime_start_(kNoLifetime),
265 lifetime_end_(kNoLifetime) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000266
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100267 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
268 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000269 }
270
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100271 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
272 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000273 }
274
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000275 void AddBackEdge(HBasicBlock* back_edge) {
276 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000277 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000278 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100279 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000280 loop_information_->AddBackEdge(back_edge);
281 }
282
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000283 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000284
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000285 int GetBlockId() const { return block_id_; }
286 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000287
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000288 HBasicBlock* GetDominator() const { return dominator_; }
289 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000290
291 int NumberOfBackEdges() const {
292 return loop_information_ == nullptr
293 ? 0
294 : loop_information_->NumberOfBackEdges();
295 }
296
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100297 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
298 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100299 const HInstructionList& GetInstructions() const { return instructions_; }
300 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100301 HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000302
303 void AddSuccessor(HBasicBlock* block) {
304 successors_.Add(block);
305 block->predecessors_.Add(this);
306 }
307
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100308 void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
309 size_t successor_index = GetSuccessorIndexOf(existing);
310 DCHECK_NE(successor_index, static_cast<size_t>(-1));
311 existing->RemovePredecessor(this);
312 new_block->predecessors_.Add(this);
313 successors_.Put(successor_index, new_block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000314 }
315
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100316 void RemovePredecessor(HBasicBlock* block) {
317 predecessors_.Delete(block);
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100318 }
319
320 void ClearAllPredecessors() {
321 predecessors_.Reset();
322 }
323
324 void AddPredecessor(HBasicBlock* block) {
325 predecessors_.Add(block);
326 block->successors_.Add(this);
327 }
328
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100329 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
330 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
331 if (predecessors_.Get(i) == predecessor) {
332 return i;
333 }
334 }
335 return -1;
336 }
337
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100338 size_t GetSuccessorIndexOf(HBasicBlock* successor) {
339 for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
340 if (successors_.Get(i) == successor) {
341 return i;
342 }
343 }
344 return -1;
345 }
346
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000347 void AddInstruction(HInstruction* instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100348 void RemoveInstruction(HInstruction* instruction);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100349 void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100350 void AddPhi(HPhi* phi);
351 void RemovePhi(HPhi* phi);
352
353 bool IsLoopHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100354 return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100355 }
356
357 HLoopInformation* GetLoopInformation() const {
358 return loop_information_;
359 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000360
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100361 // Set the loop_information_ on this block. This method overrides the current
362 // loop_information if it is an outer loop of the passed loop information.
363 void SetInLoop(HLoopInformation* info) {
364 if (IsLoopHeader()) {
365 // Nothing to do. This just means `info` is an outer loop.
366 } else if (loop_information_ == nullptr) {
367 loop_information_ = info;
368 } else if (loop_information_->Contains(*info->GetHeader())) {
369 // Block is currently part of an outer loop. Make it part of this inner loop.
370 // Note that a non loop header having a loop information means this loop information
371 // has already been populated
372 loop_information_ = info;
373 } else {
374 // Block is part of an inner loop. Do not update the loop information.
375 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
376 // at this point, because this method is being called while populating `info`.
377 }
378 }
379
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100380 bool IsInLoop() const { return loop_information_ != nullptr; }
381
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100382 // Returns wheter this block dominates the blocked passed as parameter.
383 bool Dominates(HBasicBlock* block) const;
384
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100385 size_t GetLifetimeStart() const { return lifetime_start_; }
386 size_t GetLifetimeEnd() const { return lifetime_end_; }
387
388 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
389 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
390
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000391 private:
392 HGraph* const graph_;
393 GrowableArray<HBasicBlock*> predecessors_;
394 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100395 HInstructionList instructions_;
396 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000397 HLoopInformation* loop_information_;
398 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000399 int block_id_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100400 size_t lifetime_start_;
401 size_t lifetime_end_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000402
403 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
404};
405
406#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000407 M(Add) \
Dave Allison20dfc792014-06-16 20:44:29 -0700408 M(Condition) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000409 M(Equal) \
Dave Allison20dfc792014-06-16 20:44:29 -0700410 M(NotEqual) \
411 M(LessThan) \
412 M(LessThanOrEqual) \
413 M(GreaterThan) \
414 M(GreaterThanOrEqual) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000415 M(Exit) \
416 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000417 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000418 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000419 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000420 M(LoadLocal) \
421 M(Local) \
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100422 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100423 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100424 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100425 M(ParameterValue) \
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100426 M(ParallelMove) \
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100427 M(Phi) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000428 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000429 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000430 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100431 M(Sub) \
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100432 M(Compare) \
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100433 M(InstanceFieldGet) \
434 M(InstanceFieldSet) \
435 M(NullCheck) \
436 M(Temporary) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000437
Dave Allison20dfc792014-06-16 20:44:29 -0700438
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000439#define FORWARD_DECLARATION(type) class H##type;
440FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
441#undef FORWARD_DECLARATION
442
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000443#define DECLARE_INSTRUCTION(type) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000444 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000445 virtual H##type* As##type() { return this; } \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100446 virtual void Accept(HGraphVisitor* visitor) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000447
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100448template <typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000449class HUseListNode : public ArenaObject {
450 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100451 HUseListNode(T* user, size_t index, HUseListNode* tail)
Dave Allison20dfc792014-06-16 20:44:29 -0700452 : user_(user), index_(index), tail_(tail) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000453
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000454 HUseListNode* GetTail() const { return tail_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100455 T* GetUser() const { return user_; }
456 size_t GetIndex() const { return index_; }
457
458 void SetTail(HUseListNode<T>* node) { tail_ = node; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000459
460 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100461 T* const user_;
462 const size_t index_;
463 HUseListNode<T>* tail_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000464
465 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
466};
467
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000468class HInstruction : public ArenaObject {
469 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000470 HInstruction()
471 : previous_(nullptr),
472 next_(nullptr),
473 block_(nullptr),
474 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100475 ssa_index_(-1),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000476 uses_(nullptr),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100477 env_uses_(nullptr),
478 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100479 locations_(nullptr),
480 live_interval_(nullptr),
481 lifetime_position_(kNoLifetime) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000482
Dave Allison20dfc792014-06-16 20:44:29 -0700483 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000484
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000485 HInstruction* GetNext() const { return next_; }
486 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000487
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000488 HBasicBlock* GetBlock() const { return block_; }
489 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100490 bool IsInBlock() const { return block_ != nullptr; }
491 bool IsInLoop() const { return block_->IsInLoop(); }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000492
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100493 virtual size_t InputCount() const = 0;
494 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000495
496 virtual void Accept(HGraphVisitor* visitor) = 0;
497 virtual const char* DebugName() const = 0;
498
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100499 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100500 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100501
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100502 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100503 virtual bool IsControlFlow() const { return false; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100504
505 void AddUseAt(HInstruction* user, size_t index) {
506 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000507 }
508
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100509 void AddEnvUseAt(HEnvironment* user, size_t index) {
510 env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
511 user, index, env_uses_);
512 }
513
514 void RemoveUser(HInstruction* user, size_t index);
515
516 HUseListNode<HInstruction>* GetUses() const { return uses_; }
517 HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000518
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100519 bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +0100520 bool HasEnvironmentUses() const { return env_uses_ != nullptr; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000521
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100522 size_t NumberOfUses() const {
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100523 // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100524 size_t result = 0;
525 HUseListNode<HInstruction>* current = uses_;
526 while (current != nullptr) {
527 current = current->GetTail();
528 ++result;
529 }
530 return result;
531 }
532
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000533 int GetId() const { return id_; }
534 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000535
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100536 int GetSsaIndex() const { return ssa_index_; }
537 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
538 bool HasSsaIndex() const { return ssa_index_ != -1; }
539
540 bool HasEnvironment() const { return environment_ != nullptr; }
541 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100542 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
543
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000544 LocationSummary* GetLocations() const { return locations_; }
545 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000546
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100547 void ReplaceWith(HInstruction* instruction);
548
Dave Allison20dfc792014-06-16 20:44:29 -0700549 bool HasOnlyOneUse() const {
550 return uses_ != nullptr && uses_->GetTail() == nullptr;
551 }
552
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000553#define INSTRUCTION_TYPE_CHECK(type) \
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100554 bool Is##type() { return (As##type() != nullptr); } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000555 virtual H##type* As##type() { return nullptr; }
556
557 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
558#undef INSTRUCTION_TYPE_CHECK
559
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100560 size_t GetLifetimePosition() const { return lifetime_position_; }
561 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
562 LiveInterval* GetLiveInterval() const { return live_interval_; }
563 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
564 bool HasLiveInterval() const { return live_interval_ != nullptr; }
565
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000566 private:
567 HInstruction* previous_;
568 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000569 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000570
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000571 // An instruction gets an id when it is added to the graph.
572 // It reflects creation order. A negative id means the instruction
573 // has not beed added to the graph.
574 int id_;
575
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100576 // When doing liveness analysis, instructions that have uses get an SSA index.
577 int ssa_index_;
578
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100579 // List of instructions that have this instruction as input.
580 HUseListNode<HInstruction>* uses_;
581
582 // List of environments that contain this instruction.
583 HUseListNode<HEnvironment>* env_uses_;
584
585 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000586
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000587 // Set by the code generator.
588 LocationSummary* locations_;
589
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100590 // Set by the liveness analysis.
591 LiveInterval* live_interval_;
592
593 // Set by the liveness analysis, this is the position in a linear
594 // order of blocks where this instruction's live interval start.
595 size_t lifetime_position_;
596
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000597 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100598 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000599
600 DISALLOW_COPY_AND_ASSIGN(HInstruction);
601};
602
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100603template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000604class HUseIterator : public ValueObject {
605 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100606 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000607
608 bool Done() const { return current_ == nullptr; }
609
610 void Advance() {
611 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000612 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000613 }
614
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100615 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000616 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100617 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000618 }
619
620 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100621 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000622
623 friend class HValue;
624};
625
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100626// A HEnvironment object contains the values of virtual registers at a given location.
627class HEnvironment : public ArenaObject {
628 public:
629 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
630 vregs_.SetSize(number_of_vregs);
631 for (size_t i = 0; i < number_of_vregs; i++) {
632 vregs_.Put(i, nullptr);
633 }
634 }
635
636 void Populate(const GrowableArray<HInstruction*>& env) {
637 for (size_t i = 0; i < env.Size(); i++) {
638 HInstruction* instruction = env.Get(i);
639 vregs_.Put(i, instruction);
640 if (instruction != nullptr) {
641 instruction->AddEnvUseAt(this, i);
642 }
643 }
644 }
645
646 void SetRawEnvAt(size_t index, HInstruction* instruction) {
647 vregs_.Put(index, instruction);
648 }
649
650 GrowableArray<HInstruction*>* GetVRegs() {
651 return &vregs_;
652 }
653
654 private:
655 GrowableArray<HInstruction*> vregs_;
656
657 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
658};
659
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000660class HInputIterator : public ValueObject {
661 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700662 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000663
664 bool Done() const { return index_ == instruction_->InputCount(); }
665 HInstruction* Current() const { return instruction_->InputAt(index_); }
666 void Advance() { index_++; }
667
668 private:
669 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100670 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000671
672 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
673};
674
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000675class HInstructionIterator : public ValueObject {
676 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100677 explicit HInstructionIterator(const HInstructionList& instructions)
678 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000679 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000680 }
681
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000682 bool Done() const { return instruction_ == nullptr; }
683 HInstruction* Current() const { return instruction_; }
684 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000685 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000686 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000687 }
688
689 private:
690 HInstruction* instruction_;
691 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100692
693 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000694};
695
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100696class HBackwardInstructionIterator : public ValueObject {
697 public:
698 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
699 : instruction_(instructions.last_instruction_) {
700 next_ = Done() ? nullptr : instruction_->GetPrevious();
701 }
702
703 bool Done() const { return instruction_ == nullptr; }
704 HInstruction* Current() const { return instruction_; }
705 void Advance() {
706 instruction_ = next_;
707 next_ = Done() ? nullptr : instruction_->GetPrevious();
708 }
709
710 private:
711 HInstruction* instruction_;
712 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100713
714 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100715};
716
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000717// An embedded container with N elements of type T. Used (with partial
718// specialization for N=0) because embedded arrays cannot have size 0.
719template<typename T, intptr_t N>
720class EmbeddedArray {
721 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700722 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000723
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000724 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000725
726 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000727 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000728 return elements_[i];
729 }
730
731 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000732 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000733 return elements_[i];
734 }
735
736 const T& At(intptr_t i) const {
737 return (*this)[i];
738 }
739
740 void SetAt(intptr_t i, const T& val) {
741 (*this)[i] = val;
742 }
743
744 private:
745 T elements_[N];
746};
747
748template<typename T>
749class EmbeddedArray<T, 0> {
750 public:
751 intptr_t length() const { return 0; }
752 const T& operator[](intptr_t i) const {
753 LOG(FATAL) << "Unreachable";
754 static T sentinel = 0;
755 return sentinel;
756 }
757 T& operator[](intptr_t i) {
758 LOG(FATAL) << "Unreachable";
759 static T sentinel = 0;
760 return sentinel;
761 }
762};
763
764template<intptr_t N>
765class HTemplateInstruction: public HInstruction {
766 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700767 HTemplateInstruction<N>() : inputs_() {}
768 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000769
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100770 virtual size_t InputCount() const { return N; }
771 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000772
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000773 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100774 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000775 inputs_[i] = instruction;
776 }
777
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000778 private:
779 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100780
781 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000782};
783
Dave Allison20dfc792014-06-16 20:44:29 -0700784template<intptr_t N>
785class HExpression: public HTemplateInstruction<N> {
786 public:
787 explicit HExpression<N>(Primitive::Type type) : type_(type) {}
788 virtual ~HExpression() {}
789
790 virtual Primitive::Type GetType() const { return type_; }
791
792 private:
793 const Primitive::Type type_;
794};
795
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000796// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
797// instruction that branches to the exit block.
798class HReturnVoid : public HTemplateInstruction<0> {
799 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100800 HReturnVoid() {}
801
802 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000803
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100804 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000805
806 private:
807 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
808};
809
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000810// Represents dex's RETURN opcodes. A HReturn is a control flow
811// instruction that branches to the exit block.
812class HReturn : public HTemplateInstruction<1> {
813 public:
814 explicit HReturn(HInstruction* value) {
815 SetRawInputAt(0, value);
816 }
817
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100818 virtual bool IsControlFlow() const { return true; }
819
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100820 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000821
822 private:
823 DISALLOW_COPY_AND_ASSIGN(HReturn);
824};
825
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000826// The exit instruction is the only instruction of the exit block.
827// Instructions aborting the method (HTrow and HReturn) must branch to the
828// exit block.
829class HExit : public HTemplateInstruction<0> {
830 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100831 HExit() {}
832
833 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000834
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100835 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000836
837 private:
838 DISALLOW_COPY_AND_ASSIGN(HExit);
839};
840
841// Jumps from one block to another.
842class HGoto : public HTemplateInstruction<0> {
843 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100844 HGoto() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000845
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000846 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100847 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000848 }
849
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100850 virtual bool IsControlFlow() const { return true; }
851
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100852 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000853
854 private:
855 DISALLOW_COPY_AND_ASSIGN(HGoto);
856};
857
Dave Allison20dfc792014-06-16 20:44:29 -0700858
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000859// Conditional branch. A block ending with an HIf instruction must have
860// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000861class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000862 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000863 explicit HIf(HInstruction* input) {
864 SetRawInputAt(0, input);
865 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000866
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000867 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100868 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000869 }
870
871 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100872 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000873 }
874
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100875 virtual bool IsControlFlow() const { return true; }
876
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100877 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000878
Dave Allison20dfc792014-06-16 20:44:29 -0700879 virtual bool IsIfInstruction() const { return true; }
880
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000881 private:
882 DISALLOW_COPY_AND_ASSIGN(HIf);
883};
884
Dave Allison20dfc792014-06-16 20:44:29 -0700885class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000886 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000887 HBinaryOperation(Primitive::Type result_type,
888 HInstruction* left,
Dave Allison20dfc792014-06-16 20:44:29 -0700889 HInstruction* right) : HExpression(result_type) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000890 SetRawInputAt(0, left);
891 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000892 }
893
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000894 HInstruction* GetLeft() const { return InputAt(0); }
895 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -0700896 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000897
898 virtual bool IsCommutative() { return false; }
899
900 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000901 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
902};
903
Dave Allison20dfc792014-06-16 20:44:29 -0700904class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000905 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700906 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000907 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
908
909 virtual bool IsCommutative() { return true; }
Dave Allison20dfc792014-06-16 20:44:29 -0700910 bool NeedsMaterialization() const;
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000911
Dave Allison20dfc792014-06-16 20:44:29 -0700912 DECLARE_INSTRUCTION(Condition);
913
914 virtual IfCondition GetCondition() const = 0;
915
916 private:
917 DISALLOW_COPY_AND_ASSIGN(HCondition);
918};
919
920// Instruction to check if two inputs are equal to each other.
921class HEqual : public HCondition {
922 public:
923 HEqual(HInstruction* first, HInstruction* second)
924 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100925
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100926 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000927
Dave Allison20dfc792014-06-16 20:44:29 -0700928 virtual IfCondition GetCondition() const {
929 return kCondEQ;
930 }
931
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000932 private:
933 DISALLOW_COPY_AND_ASSIGN(HEqual);
934};
935
Dave Allison20dfc792014-06-16 20:44:29 -0700936class HNotEqual : public HCondition {
937 public:
938 HNotEqual(HInstruction* first, HInstruction* second)
939 : HCondition(first, second) {}
940
941 DECLARE_INSTRUCTION(NotEqual);
942
943 virtual IfCondition GetCondition() const {
944 return kCondNE;
945 }
946
947 private:
948 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
949};
950
951class HLessThan : public HCondition {
952 public:
953 HLessThan(HInstruction* first, HInstruction* second)
954 : HCondition(first, second) {}
955
956 DECLARE_INSTRUCTION(LessThan);
957
958 virtual IfCondition GetCondition() const {
959 return kCondLT;
960 }
961
962 private:
963 DISALLOW_COPY_AND_ASSIGN(HLessThan);
964};
965
966class HLessThanOrEqual : public HCondition {
967 public:
968 HLessThanOrEqual(HInstruction* first, HInstruction* second)
969 : HCondition(first, second) {}
970
971 DECLARE_INSTRUCTION(LessThanOrEqual);
972
973 virtual IfCondition GetCondition() const {
974 return kCondLE;
975 }
976
977 private:
978 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
979};
980
981class HGreaterThan : public HCondition {
982 public:
983 HGreaterThan(HInstruction* first, HInstruction* second)
984 : HCondition(first, second) {}
985
986 DECLARE_INSTRUCTION(GreaterThan);
987
988 virtual IfCondition GetCondition() const {
989 return kCondGT;
990 }
991
992 private:
993 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
994};
995
996class HGreaterThanOrEqual : public HCondition {
997 public:
998 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
999 : HCondition(first, second) {}
1000
1001 DECLARE_INSTRUCTION(GreaterThanOrEqual);
1002
1003 virtual IfCondition GetCondition() const {
1004 return kCondGE;
1005 }
1006
1007 private:
1008 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
1009};
1010
1011
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001012// Instruction to check how two inputs compare to each other.
1013// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
1014class HCompare : public HBinaryOperation {
1015 public:
1016 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second)
1017 : HBinaryOperation(Primitive::kPrimInt, first, second) {
1018 DCHECK_EQ(type, first->GetType());
1019 DCHECK_EQ(type, second->GetType());
1020 }
1021
1022 DECLARE_INSTRUCTION(Compare);
1023
1024 private:
1025 DISALLOW_COPY_AND_ASSIGN(HCompare);
1026};
1027
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001028// A local in the graph. Corresponds to a Dex register.
1029class HLocal : public HTemplateInstruction<0> {
1030 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001031 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001032
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001033 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001034
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001035 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001036
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001037 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001038 // The Dex register number.
1039 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001040
1041 DISALLOW_COPY_AND_ASSIGN(HLocal);
1042};
1043
1044// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07001045class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001046 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001047 explicit HLoadLocal(HLocal* local, Primitive::Type type) : HExpression(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001048 SetRawInputAt(0, local);
1049 }
1050
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001051 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1052
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001053 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001054
1055 private:
1056 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
1057};
1058
1059// Store a value in a given local. This instruction has two inputs: the value
1060// and the local.
1061class HStoreLocal : public HTemplateInstruction<2> {
1062 public:
1063 HStoreLocal(HLocal* local, HInstruction* value) {
1064 SetRawInputAt(0, local);
1065 SetRawInputAt(1, value);
1066 }
1067
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001068 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1069
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001070 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001071
1072 private:
1073 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
1074};
1075
1076// Constants of the type int. Those can be from Dex instructions, or
1077// synthesized (for example with the if-eqz instruction).
Dave Allison20dfc792014-06-16 20:44:29 -07001078class HIntConstant : public HExpression<0> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001079 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001080 explicit HIntConstant(int32_t value) : HExpression(Primitive::kPrimInt), value_(value) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001081
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001082 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001083
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001084 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001085
1086 private:
1087 const int32_t value_;
1088
1089 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
1090};
1091
Dave Allison20dfc792014-06-16 20:44:29 -07001092class HLongConstant : public HExpression<0> {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001093 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001094 explicit HLongConstant(int64_t value) : HExpression(Primitive::kPrimLong), value_(value) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001095
1096 int64_t GetValue() const { return value_; }
1097
1098 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
1099
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001100 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001101
1102 private:
1103 const int64_t value_;
1104
1105 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
1106};
1107
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001108class HInvoke : public HInstruction {
1109 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001110 HInvoke(ArenaAllocator* arena,
1111 uint32_t number_of_arguments,
1112 Primitive::Type return_type,
1113 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001114 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001115 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001116 dex_pc_(dex_pc) {
1117 inputs_.SetSize(number_of_arguments);
1118 }
1119
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001120 virtual size_t InputCount() const { return inputs_.Size(); }
1121 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1122
1123 // Runtime needs to walk the stack, so Dex -> Dex calls need to
1124 // know their environment.
1125 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001126
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001127 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001128 SetRawInputAt(index, argument);
1129 }
1130
1131 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1132 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001133 }
1134
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001135 virtual Primitive::Type GetType() const { return return_type_; }
1136
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001137 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001138
1139 protected:
1140 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001141 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001142 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001143
1144 private:
1145 DISALLOW_COPY_AND_ASSIGN(HInvoke);
1146};
1147
1148class HInvokeStatic : public HInvoke {
1149 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001150 HInvokeStatic(ArenaAllocator* arena,
1151 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001152 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001153 uint32_t dex_pc,
1154 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001155 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
1156 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001157
1158 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
1159
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001160 DECLARE_INSTRUCTION(InvokeStatic);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001161
1162 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001163 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001164
1165 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
1166};
1167
Dave Allison20dfc792014-06-16 20:44:29 -07001168class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001169 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001170 HNewInstance(uint32_t dex_pc, uint16_t type_index) : HExpression(Primitive::kPrimNot),
1171 dex_pc_(dex_pc), type_index_(type_index) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001172
1173 uint32_t GetDexPc() const { return dex_pc_; }
1174 uint16_t GetTypeIndex() const { return type_index_; }
1175
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001176 // Calls runtime so needs an environment.
1177 virtual bool NeedsEnvironment() const { return true; }
1178
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001179 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001180
1181 private:
1182 const uint32_t dex_pc_;
1183 const uint16_t type_index_;
1184
1185 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
1186};
1187
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001188class HAdd : public HBinaryOperation {
1189 public:
1190 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1191 : HBinaryOperation(result_type, left, right) {}
1192
1193 virtual bool IsCommutative() { return true; }
1194
1195 DECLARE_INSTRUCTION(Add);
1196
1197 private:
1198 DISALLOW_COPY_AND_ASSIGN(HAdd);
1199};
1200
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001201class HSub : public HBinaryOperation {
1202 public:
1203 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1204 : HBinaryOperation(result_type, left, right) {}
1205
1206 virtual bool IsCommutative() { return false; }
1207
1208 DECLARE_INSTRUCTION(Sub);
1209
1210 private:
1211 DISALLOW_COPY_AND_ASSIGN(HSub);
1212};
1213
1214// The value of a parameter in this method. Its location depends on
1215// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07001216class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001217 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001218 HParameterValue(uint8_t index, Primitive::Type parameter_type)
Dave Allison20dfc792014-06-16 20:44:29 -07001219 : HExpression(parameter_type), index_(index) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001220
1221 uint8_t GetIndex() const { return index_; }
1222
1223 DECLARE_INSTRUCTION(ParameterValue);
1224
1225 private:
1226 // The index of this parameter in the parameters list. Must be less
1227 // than HGraph::number_of_in_vregs_;
1228 const uint8_t index_;
1229
1230 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1231};
1232
Dave Allison20dfc792014-06-16 20:44:29 -07001233class HNot : public HExpression<1> {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001234 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001235 explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean) {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001236 SetRawInputAt(0, input);
1237 }
1238
1239 DECLARE_INSTRUCTION(Not);
1240
1241 private:
1242 DISALLOW_COPY_AND_ASSIGN(HNot);
1243};
1244
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001245class HPhi : public HInstruction {
1246 public:
1247 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
1248 : inputs_(arena, number_of_inputs),
1249 reg_number_(reg_number),
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001250 type_(type),
1251 is_live_(false) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001252 inputs_.SetSize(number_of_inputs);
1253 }
1254
1255 virtual size_t InputCount() const { return inputs_.Size(); }
1256 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1257
1258 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1259 inputs_.Put(index, input);
1260 }
1261
1262 void AddInput(HInstruction* input);
1263
1264 virtual Primitive::Type GetType() const { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001265 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001266
1267 uint32_t GetRegNumber() const { return reg_number_; }
1268
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001269 void SetDead() { is_live_ = false; }
1270 void SetLive() { is_live_ = true; }
1271 bool IsDead() const { return !is_live_; }
1272 bool IsLive() const { return is_live_; }
1273
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001274 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001275
1276 protected:
1277 GrowableArray<HInstruction*> inputs_;
1278 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001279 Primitive::Type type_;
Nicolas Geoffray7dc206a2014-07-11 09:49:49 +01001280 bool is_live_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001281
1282 private:
1283 DISALLOW_COPY_AND_ASSIGN(HPhi);
1284};
1285
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001286class HNullCheck : public HExpression<1> {
1287 public:
1288 HNullCheck(HInstruction* value, uint32_t dex_pc)
1289 : HExpression(value->GetType()), dex_pc_(dex_pc) {
1290 SetRawInputAt(0, value);
1291 }
1292
1293 virtual bool NeedsEnvironment() const { return true; }
1294
1295 uint32_t GetDexPc() const { return dex_pc_; }
1296
1297 DECLARE_INSTRUCTION(NullCheck);
1298
1299 private:
1300 const uint32_t dex_pc_;
1301
1302 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
1303};
1304
1305class FieldInfo : public ValueObject {
1306 public:
1307 explicit FieldInfo(MemberOffset field_offset)
1308 : field_offset_(field_offset) {}
1309
1310 MemberOffset GetFieldOffset() const { return field_offset_; }
1311
1312 private:
1313 const MemberOffset field_offset_;
1314};
1315
1316class HInstanceFieldGet : public HExpression<1> {
1317 public:
1318 HInstanceFieldGet(HInstruction* value,
1319 Primitive::Type field_type,
1320 MemberOffset field_offset)
1321 : HExpression(field_type), field_info_(field_offset) {
1322 SetRawInputAt(0, value);
1323 }
1324
1325 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
1326
1327 DECLARE_INSTRUCTION(InstanceFieldGet);
1328
1329 private:
1330 const FieldInfo field_info_;
1331
1332 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
1333};
1334
1335class HInstanceFieldSet : public HTemplateInstruction<2> {
1336 public:
1337 HInstanceFieldSet(HInstruction* object,
1338 HInstruction* value,
1339 MemberOffset field_offset)
1340 : field_info_(field_offset) {
1341 SetRawInputAt(0, object);
1342 SetRawInputAt(1, value);
1343 }
1344
1345 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
1346
1347 DECLARE_INSTRUCTION(InstanceFieldSet);
1348
1349 private:
1350 const FieldInfo field_info_;
1351
1352 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
1353};
1354
1355/**
1356 * Some DEX instructions are folded into multiple HInstructions that need
1357 * to stay live until the last HInstruction. This class
1358 * is used as a marker for the baseline compiler to ensure its preceding
1359 * HInstruction stays live. `index` is the temporary number that is used
1360 * for knowing the stack offset where to store the instruction.
1361 */
1362class HTemporary : public HTemplateInstruction<0> {
1363 public:
1364 explicit HTemporary(size_t index) : index_(index) {}
1365
1366 size_t GetIndex() const { return index_; }
1367
1368 DECLARE_INSTRUCTION(Temporary);
1369
1370 private:
1371 const size_t index_;
1372
1373 DISALLOW_COPY_AND_ASSIGN(HTemporary);
1374};
1375
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001376class MoveOperands : public ArenaObject {
1377 public:
1378 MoveOperands(Location source, Location destination)
1379 : source_(source), destination_(destination) {}
1380
1381 Location GetSource() const { return source_; }
1382 Location GetDestination() const { return destination_; }
1383
1384 void SetSource(Location value) { source_ = value; }
1385 void SetDestination(Location value) { destination_ = value; }
1386
1387 // The parallel move resolver marks moves as "in-progress" by clearing the
1388 // destination (but not the source).
1389 Location MarkPending() {
1390 DCHECK(!IsPending());
1391 Location dest = destination_;
1392 destination_ = Location::NoLocation();
1393 return dest;
1394 }
1395
1396 void ClearPending(Location dest) {
1397 DCHECK(IsPending());
1398 destination_ = dest;
1399 }
1400
1401 bool IsPending() const {
1402 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
1403 return destination_.IsInvalid() && !source_.IsInvalid();
1404 }
1405
1406 // True if this blocks a move from the given location.
1407 bool Blocks(Location loc) const {
1408 return !IsEliminated() && source_.Equals(loc);
1409 }
1410
1411 // A move is redundant if it's been eliminated, if its source and
1412 // destination are the same, or if its destination is unneeded.
1413 bool IsRedundant() const {
1414 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
1415 }
1416
1417 // We clear both operands to indicate move that's been eliminated.
1418 void Eliminate() {
1419 source_ = destination_ = Location::NoLocation();
1420 }
1421
1422 bool IsEliminated() const {
1423 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
1424 return source_.IsInvalid();
1425 }
1426
1427 private:
1428 Location source_;
1429 Location destination_;
1430
1431 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
1432};
1433
1434static constexpr size_t kDefaultNumberOfMoves = 4;
1435
1436class HParallelMove : public HTemplateInstruction<0> {
1437 public:
1438 explicit HParallelMove(ArenaAllocator* arena) : moves_(arena, kDefaultNumberOfMoves) {}
1439
1440 void AddMove(MoveOperands* move) {
1441 moves_.Add(move);
1442 }
1443
1444 MoveOperands* MoveOperandsAt(size_t index) const {
1445 return moves_.Get(index);
1446 }
1447
1448 size_t NumMoves() const { return moves_.Size(); }
1449
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001450 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001451
1452 private:
1453 GrowableArray<MoveOperands*> moves_;
1454
1455 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
1456};
1457
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001458class HGraphVisitor : public ValueObject {
1459 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001460 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
1461 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001462
Dave Allison20dfc792014-06-16 20:44:29 -07001463 virtual void VisitInstruction(HInstruction* instruction) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001464 virtual void VisitBasicBlock(HBasicBlock* block);
1465
1466 void VisitInsertionOrder();
1467
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001468 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001469
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001470 // Visit functions for instruction classes.
1471#define DECLARE_VISIT_INSTRUCTION(name) \
1472 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
1473
1474 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1475
1476#undef DECLARE_VISIT_INSTRUCTION
1477
1478 private:
1479 HGraph* graph_;
1480
1481 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
1482};
1483
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001484class HInsertionOrderIterator : public ValueObject {
1485 public:
1486 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1487
1488 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1489 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1490 void Advance() { ++index_; }
1491
1492 private:
1493 const HGraph& graph_;
1494 size_t index_;
1495
1496 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1497};
1498
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001499class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001500 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001501 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001502
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001503 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
1504 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001505 void Advance() { ++index_; }
1506
1507 private:
1508 const HGraph& graph_;
1509 size_t index_;
1510
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001511 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001512};
1513
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001514class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001515 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001516 explicit HPostOrderIterator(const HGraph& graph)
1517 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001518
1519 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001520 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001521 void Advance() { --index_; }
1522
1523 private:
1524 const HGraph& graph_;
1525 size_t index_;
1526
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001527 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001528};
1529
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001530} // namespace art
1531
1532#endif // ART_COMPILER_OPTIMIZING_NODES_H_