blob: 4036a8d4ba6e6224f16706e3fc4711666912d0fb [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
380 // Returns wheter this block dominates the blocked passed as parameter.
381 bool Dominates(HBasicBlock* block) const;
382
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100383 size_t GetLifetimeStart() const { return lifetime_start_; }
384 size_t GetLifetimeEnd() const { return lifetime_end_; }
385
386 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
387 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
388
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000389 private:
390 HGraph* const graph_;
391 GrowableArray<HBasicBlock*> predecessors_;
392 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100393 HInstructionList instructions_;
394 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000395 HLoopInformation* loop_information_;
396 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000397 int block_id_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100398 size_t lifetime_start_;
399 size_t lifetime_end_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000400
401 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
402};
403
404#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000405 M(Add) \
Dave Allison20dfc792014-06-16 20:44:29 -0700406 M(Condition) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000407 M(Equal) \
Dave Allison20dfc792014-06-16 20:44:29 -0700408 M(NotEqual) \
409 M(LessThan) \
410 M(LessThanOrEqual) \
411 M(GreaterThan) \
412 M(GreaterThanOrEqual) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000413 M(Exit) \
414 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000415 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000416 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000417 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000418 M(LoadLocal) \
419 M(Local) \
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100420 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100421 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100422 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100423 M(ParameterValue) \
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +0100424 M(ParallelMove) \
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100425 M(Phi) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000426 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000427 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000428 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100429 M(Sub) \
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100430 M(Compare) \
Nicolas Geoffraye5038322014-07-04 09:41:32 +0100431 M(InstanceFieldGet) \
432 M(InstanceFieldSet) \
433 M(NullCheck) \
434 M(Temporary) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000435
Dave Allison20dfc792014-06-16 20:44:29 -0700436
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000437#define FORWARD_DECLARATION(type) class H##type;
438FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
439#undef FORWARD_DECLARATION
440
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000441#define DECLARE_INSTRUCTION(type) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000442 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000443 virtual H##type* As##type() { return this; } \
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100444 virtual void Accept(HGraphVisitor* visitor) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000445
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100446template <typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000447class HUseListNode : public ArenaObject {
448 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100449 HUseListNode(T* user, size_t index, HUseListNode* tail)
Dave Allison20dfc792014-06-16 20:44:29 -0700450 : user_(user), index_(index), tail_(tail) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000451
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000452 HUseListNode* GetTail() const { return tail_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100453 T* GetUser() const { return user_; }
454 size_t GetIndex() const { return index_; }
455
456 void SetTail(HUseListNode<T>* node) { tail_ = node; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000457
458 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100459 T* const user_;
460 const size_t index_;
461 HUseListNode<T>* tail_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000462
463 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
464};
465
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000466class HInstruction : public ArenaObject {
467 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000468 HInstruction()
469 : previous_(nullptr),
470 next_(nullptr),
471 block_(nullptr),
472 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100473 ssa_index_(-1),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000474 uses_(nullptr),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100475 env_uses_(nullptr),
476 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100477 locations_(nullptr),
478 live_interval_(nullptr),
479 lifetime_position_(kNoLifetime) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000480
Dave Allison20dfc792014-06-16 20:44:29 -0700481 virtual ~HInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000482
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000483 HInstruction* GetNext() const { return next_; }
484 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000485
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000486 HBasicBlock* GetBlock() const { return block_; }
487 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000488
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100489 virtual size_t InputCount() const = 0;
490 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000491
492 virtual void Accept(HGraphVisitor* visitor) = 0;
493 virtual const char* DebugName() const = 0;
494
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100495 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100496 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100497
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100498 virtual bool NeedsEnvironment() const { return false; }
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100499 virtual bool IsControlFlow() const { return false; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100500
501 void AddUseAt(HInstruction* user, size_t index) {
502 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000503 }
504
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100505 void AddEnvUseAt(HEnvironment* user, size_t index) {
506 env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
507 user, index, env_uses_);
508 }
509
510 void RemoveUser(HInstruction* user, size_t index);
511
512 HUseListNode<HInstruction>* GetUses() const { return uses_; }
513 HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000514
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100515 bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000516
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100517 size_t NumberOfUses() const {
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100518 // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100519 size_t result = 0;
520 HUseListNode<HInstruction>* current = uses_;
521 while (current != nullptr) {
522 current = current->GetTail();
523 ++result;
524 }
525 return result;
526 }
527
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000528 int GetId() const { return id_; }
529 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000530
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100531 int GetSsaIndex() const { return ssa_index_; }
532 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
533 bool HasSsaIndex() const { return ssa_index_ != -1; }
534
535 bool HasEnvironment() const { return environment_ != nullptr; }
536 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100537 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
538
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000539 LocationSummary* GetLocations() const { return locations_; }
540 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000541
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100542 void ReplaceWith(HInstruction* instruction);
543
Dave Allison20dfc792014-06-16 20:44:29 -0700544 bool HasOnlyOneUse() const {
545 return uses_ != nullptr && uses_->GetTail() == nullptr;
546 }
547
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000548#define INSTRUCTION_TYPE_CHECK(type) \
Nicolas Geoffray86dbb9a2014-06-04 11:12:39 +0100549 bool Is##type() { return (As##type() != nullptr); } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000550 virtual H##type* As##type() { return nullptr; }
551
552 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
553#undef INSTRUCTION_TYPE_CHECK
554
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100555 size_t GetLifetimePosition() const { return lifetime_position_; }
556 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
557 LiveInterval* GetLiveInterval() const { return live_interval_; }
558 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
559 bool HasLiveInterval() const { return live_interval_ != nullptr; }
560
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000561 private:
562 HInstruction* previous_;
563 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000564 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000565
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000566 // An instruction gets an id when it is added to the graph.
567 // It reflects creation order. A negative id means the instruction
568 // has not beed added to the graph.
569 int id_;
570
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100571 // When doing liveness analysis, instructions that have uses get an SSA index.
572 int ssa_index_;
573
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100574 // List of instructions that have this instruction as input.
575 HUseListNode<HInstruction>* uses_;
576
577 // List of environments that contain this instruction.
578 HUseListNode<HEnvironment>* env_uses_;
579
580 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000581
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000582 // Set by the code generator.
583 LocationSummary* locations_;
584
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100585 // Set by the liveness analysis.
586 LiveInterval* live_interval_;
587
588 // Set by the liveness analysis, this is the position in a linear
589 // order of blocks where this instruction's live interval start.
590 size_t lifetime_position_;
591
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000592 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100593 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000594
595 DISALLOW_COPY_AND_ASSIGN(HInstruction);
596};
597
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100598template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000599class HUseIterator : public ValueObject {
600 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100601 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000602
603 bool Done() const { return current_ == nullptr; }
604
605 void Advance() {
606 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000607 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000608 }
609
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100610 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000611 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100612 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000613 }
614
615 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100616 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000617
618 friend class HValue;
619};
620
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100621// A HEnvironment object contains the values of virtual registers at a given location.
622class HEnvironment : public ArenaObject {
623 public:
624 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
625 vregs_.SetSize(number_of_vregs);
626 for (size_t i = 0; i < number_of_vregs; i++) {
627 vregs_.Put(i, nullptr);
628 }
629 }
630
631 void Populate(const GrowableArray<HInstruction*>& env) {
632 for (size_t i = 0; i < env.Size(); i++) {
633 HInstruction* instruction = env.Get(i);
634 vregs_.Put(i, instruction);
635 if (instruction != nullptr) {
636 instruction->AddEnvUseAt(this, i);
637 }
638 }
639 }
640
641 void SetRawEnvAt(size_t index, HInstruction* instruction) {
642 vregs_.Put(index, instruction);
643 }
644
645 GrowableArray<HInstruction*>* GetVRegs() {
646 return &vregs_;
647 }
648
649 private:
650 GrowableArray<HInstruction*> vregs_;
651
652 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
653};
654
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000655class HInputIterator : public ValueObject {
656 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700657 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000658
659 bool Done() const { return index_ == instruction_->InputCount(); }
660 HInstruction* Current() const { return instruction_->InputAt(index_); }
661 void Advance() { index_++; }
662
663 private:
664 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100665 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000666
667 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
668};
669
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000670class HInstructionIterator : public ValueObject {
671 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100672 explicit HInstructionIterator(const HInstructionList& instructions)
673 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000674 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000675 }
676
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000677 bool Done() const { return instruction_ == nullptr; }
678 HInstruction* Current() const { return instruction_; }
679 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000680 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000681 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000682 }
683
684 private:
685 HInstruction* instruction_;
686 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100687
688 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000689};
690
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100691class HBackwardInstructionIterator : public ValueObject {
692 public:
693 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
694 : instruction_(instructions.last_instruction_) {
695 next_ = Done() ? nullptr : instruction_->GetPrevious();
696 }
697
698 bool Done() const { return instruction_ == nullptr; }
699 HInstruction* Current() const { return instruction_; }
700 void Advance() {
701 instruction_ = next_;
702 next_ = Done() ? nullptr : instruction_->GetPrevious();
703 }
704
705 private:
706 HInstruction* instruction_;
707 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100708
709 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100710};
711
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000712// An embedded container with N elements of type T. Used (with partial
713// specialization for N=0) because embedded arrays cannot have size 0.
714template<typename T, intptr_t N>
715class EmbeddedArray {
716 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700717 EmbeddedArray() : elements_() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000718
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000719 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000720
721 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000722 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000723 return elements_[i];
724 }
725
726 T& operator[](intptr_t i) {
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 const T& At(intptr_t i) const {
732 return (*this)[i];
733 }
734
735 void SetAt(intptr_t i, const T& val) {
736 (*this)[i] = val;
737 }
738
739 private:
740 T elements_[N];
741};
742
743template<typename T>
744class EmbeddedArray<T, 0> {
745 public:
746 intptr_t length() const { return 0; }
747 const T& operator[](intptr_t i) const {
748 LOG(FATAL) << "Unreachable";
749 static T sentinel = 0;
750 return sentinel;
751 }
752 T& operator[](intptr_t i) {
753 LOG(FATAL) << "Unreachable";
754 static T sentinel = 0;
755 return sentinel;
756 }
757};
758
759template<intptr_t N>
760class HTemplateInstruction: public HInstruction {
761 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700762 HTemplateInstruction<N>() : inputs_() {}
763 virtual ~HTemplateInstruction() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000764
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100765 virtual size_t InputCount() const { return N; }
766 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000767
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000768 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100769 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000770 inputs_[i] = instruction;
771 }
772
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000773 private:
774 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100775
776 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000777};
778
Dave Allison20dfc792014-06-16 20:44:29 -0700779template<intptr_t N>
780class HExpression: public HTemplateInstruction<N> {
781 public:
782 explicit HExpression<N>(Primitive::Type type) : type_(type) {}
783 virtual ~HExpression() {}
784
785 virtual Primitive::Type GetType() const { return type_; }
786
787 private:
788 const Primitive::Type type_;
789};
790
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000791// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
792// instruction that branches to the exit block.
793class HReturnVoid : public HTemplateInstruction<0> {
794 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100795 HReturnVoid() {}
796
797 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000798
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100799 DECLARE_INSTRUCTION(ReturnVoid);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000800
801 private:
802 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
803};
804
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000805// Represents dex's RETURN opcodes. A HReturn is a control flow
806// instruction that branches to the exit block.
807class HReturn : public HTemplateInstruction<1> {
808 public:
809 explicit HReturn(HInstruction* value) {
810 SetRawInputAt(0, value);
811 }
812
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100813 virtual bool IsControlFlow() const { return true; }
814
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100815 DECLARE_INSTRUCTION(Return);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000816
817 private:
818 DISALLOW_COPY_AND_ASSIGN(HReturn);
819};
820
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000821// The exit instruction is the only instruction of the exit block.
822// Instructions aborting the method (HTrow and HReturn) must branch to the
823// exit block.
824class HExit : public HTemplateInstruction<0> {
825 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100826 HExit() {}
827
828 virtual bool IsControlFlow() const { return true; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000829
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100830 DECLARE_INSTRUCTION(Exit);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000831
832 private:
833 DISALLOW_COPY_AND_ASSIGN(HExit);
834};
835
836// Jumps from one block to another.
837class HGoto : public HTemplateInstruction<0> {
838 public:
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100839 HGoto() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000840
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000841 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100842 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000843 }
844
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100845 virtual bool IsControlFlow() const { return true; }
846
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100847 DECLARE_INSTRUCTION(Goto);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000848
849 private:
850 DISALLOW_COPY_AND_ASSIGN(HGoto);
851};
852
Dave Allison20dfc792014-06-16 20:44:29 -0700853
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000854// Conditional branch. A block ending with an HIf instruction must have
855// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000856class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000857 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000858 explicit HIf(HInstruction* input) {
859 SetRawInputAt(0, input);
860 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000861
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000862 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100863 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000864 }
865
866 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100867 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000868 }
869
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100870 virtual bool IsControlFlow() const { return true; }
871
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100872 DECLARE_INSTRUCTION(If);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000873
Dave Allison20dfc792014-06-16 20:44:29 -0700874 virtual bool IsIfInstruction() const { return true; }
875
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000876 private:
877 DISALLOW_COPY_AND_ASSIGN(HIf);
878};
879
Dave Allison20dfc792014-06-16 20:44:29 -0700880class HBinaryOperation : public HExpression<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000881 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000882 HBinaryOperation(Primitive::Type result_type,
883 HInstruction* left,
Dave Allison20dfc792014-06-16 20:44:29 -0700884 HInstruction* right) : HExpression(result_type) {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000885 SetRawInputAt(0, left);
886 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000887 }
888
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000889 HInstruction* GetLeft() const { return InputAt(0); }
890 HInstruction* GetRight() const { return InputAt(1); }
Dave Allison20dfc792014-06-16 20:44:29 -0700891 Primitive::Type GetResultType() const { return GetType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000892
893 virtual bool IsCommutative() { return false; }
894
895 private:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000896 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
897};
898
Dave Allison20dfc792014-06-16 20:44:29 -0700899class HCondition : public HBinaryOperation {
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000900 public:
Dave Allison20dfc792014-06-16 20:44:29 -0700901 HCondition(HInstruction* first, HInstruction* second)
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000902 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
903
904 virtual bool IsCommutative() { return true; }
Dave Allison20dfc792014-06-16 20:44:29 -0700905 bool NeedsMaterialization() const;
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000906
Dave Allison20dfc792014-06-16 20:44:29 -0700907 DECLARE_INSTRUCTION(Condition);
908
909 virtual IfCondition GetCondition() const = 0;
910
911 private:
912 DISALLOW_COPY_AND_ASSIGN(HCondition);
913};
914
915// Instruction to check if two inputs are equal to each other.
916class HEqual : public HCondition {
917 public:
918 HEqual(HInstruction* first, HInstruction* second)
919 : HCondition(first, second) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100920
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100921 DECLARE_INSTRUCTION(Equal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000922
Dave Allison20dfc792014-06-16 20:44:29 -0700923 virtual IfCondition GetCondition() const {
924 return kCondEQ;
925 }
926
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000927 private:
928 DISALLOW_COPY_AND_ASSIGN(HEqual);
929};
930
Dave Allison20dfc792014-06-16 20:44:29 -0700931class HNotEqual : public HCondition {
932 public:
933 HNotEqual(HInstruction* first, HInstruction* second)
934 : HCondition(first, second) {}
935
936 DECLARE_INSTRUCTION(NotEqual);
937
938 virtual IfCondition GetCondition() const {
939 return kCondNE;
940 }
941
942 private:
943 DISALLOW_COPY_AND_ASSIGN(HNotEqual);
944};
945
946class HLessThan : public HCondition {
947 public:
948 HLessThan(HInstruction* first, HInstruction* second)
949 : HCondition(first, second) {}
950
951 DECLARE_INSTRUCTION(LessThan);
952
953 virtual IfCondition GetCondition() const {
954 return kCondLT;
955 }
956
957 private:
958 DISALLOW_COPY_AND_ASSIGN(HLessThan);
959};
960
961class HLessThanOrEqual : public HCondition {
962 public:
963 HLessThanOrEqual(HInstruction* first, HInstruction* second)
964 : HCondition(first, second) {}
965
966 DECLARE_INSTRUCTION(LessThanOrEqual);
967
968 virtual IfCondition GetCondition() const {
969 return kCondLE;
970 }
971
972 private:
973 DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
974};
975
976class HGreaterThan : public HCondition {
977 public:
978 HGreaterThan(HInstruction* first, HInstruction* second)
979 : HCondition(first, second) {}
980
981 DECLARE_INSTRUCTION(GreaterThan);
982
983 virtual IfCondition GetCondition() const {
984 return kCondGT;
985 }
986
987 private:
988 DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
989};
990
991class HGreaterThanOrEqual : public HCondition {
992 public:
993 HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
994 : HCondition(first, second) {}
995
996 DECLARE_INSTRUCTION(GreaterThanOrEqual);
997
998 virtual IfCondition GetCondition() const {
999 return kCondGE;
1000 }
1001
1002 private:
1003 DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
1004};
1005
1006
Nicolas Geoffray412f10c2014-06-19 10:00:34 +01001007// Instruction to check how two inputs compare to each other.
1008// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
1009class HCompare : public HBinaryOperation {
1010 public:
1011 HCompare(Primitive::Type type, HInstruction* first, HInstruction* second)
1012 : HBinaryOperation(Primitive::kPrimInt, first, second) {
1013 DCHECK_EQ(type, first->GetType());
1014 DCHECK_EQ(type, second->GetType());
1015 }
1016
1017 DECLARE_INSTRUCTION(Compare);
1018
1019 private:
1020 DISALLOW_COPY_AND_ASSIGN(HCompare);
1021};
1022
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001023// A local in the graph. Corresponds to a Dex register.
1024class HLocal : public HTemplateInstruction<0> {
1025 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001026 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001027
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001028 DECLARE_INSTRUCTION(Local);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001029
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001030 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001031
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001032 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001033 // The Dex register number.
1034 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001035
1036 DISALLOW_COPY_AND_ASSIGN(HLocal);
1037};
1038
1039// Load a given local. The local is an input of this instruction.
Dave Allison20dfc792014-06-16 20:44:29 -07001040class HLoadLocal : public HExpression<1> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001041 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001042 explicit HLoadLocal(HLocal* local, Primitive::Type type) : HExpression(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001043 SetRawInputAt(0, local);
1044 }
1045
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001046 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1047
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001048 DECLARE_INSTRUCTION(LoadLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001049
1050 private:
1051 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
1052};
1053
1054// Store a value in a given local. This instruction has two inputs: the value
1055// and the local.
1056class HStoreLocal : public HTemplateInstruction<2> {
1057 public:
1058 HStoreLocal(HLocal* local, HInstruction* value) {
1059 SetRawInputAt(0, local);
1060 SetRawInputAt(1, value);
1061 }
1062
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001063 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1064
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001065 DECLARE_INSTRUCTION(StoreLocal);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001066
1067 private:
1068 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
1069};
1070
1071// Constants of the type int. Those can be from Dex instructions, or
1072// synthesized (for example with the if-eqz instruction).
Dave Allison20dfc792014-06-16 20:44:29 -07001073class HIntConstant : public HExpression<0> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001074 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001075 explicit HIntConstant(int32_t value) : HExpression(Primitive::kPrimInt), value_(value) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001076
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001077 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +00001078
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001079 DECLARE_INSTRUCTION(IntConstant);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +00001080
1081 private:
1082 const int32_t value_;
1083
1084 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
1085};
1086
Dave Allison20dfc792014-06-16 20:44:29 -07001087class HLongConstant : public HExpression<0> {
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001088 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001089 explicit HLongConstant(int64_t value) : HExpression(Primitive::kPrimLong), value_(value) {}
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001090
1091 int64_t GetValue() const { return value_; }
1092
1093 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
1094
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001095 DECLARE_INSTRUCTION(LongConstant);
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001096
1097 private:
1098 const int64_t value_;
1099
1100 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
1101};
1102
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001103class HInvoke : public HInstruction {
1104 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001105 HInvoke(ArenaAllocator* arena,
1106 uint32_t number_of_arguments,
1107 Primitive::Type return_type,
1108 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001109 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001110 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001111 dex_pc_(dex_pc) {
1112 inputs_.SetSize(number_of_arguments);
1113 }
1114
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001115 virtual size_t InputCount() const { return inputs_.Size(); }
1116 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1117
1118 // Runtime needs to walk the stack, so Dex -> Dex calls need to
1119 // know their environment.
1120 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001121
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001122 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001123 SetRawInputAt(index, argument);
1124 }
1125
1126 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1127 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001128 }
1129
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001130 virtual Primitive::Type GetType() const { return return_type_; }
1131
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001132 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001133
1134 protected:
1135 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001136 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001137 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001138
1139 private:
1140 DISALLOW_COPY_AND_ASSIGN(HInvoke);
1141};
1142
1143class HInvokeStatic : public HInvoke {
1144 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001145 HInvokeStatic(ArenaAllocator* arena,
1146 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001147 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001148 uint32_t dex_pc,
1149 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001150 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
1151 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001152
1153 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
1154
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001155 DECLARE_INSTRUCTION(InvokeStatic);
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001156
1157 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +01001158 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +00001159
1160 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
1161};
1162
Dave Allison20dfc792014-06-16 20:44:29 -07001163class HNewInstance : public HExpression<0> {
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001164 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001165 HNewInstance(uint32_t dex_pc, uint16_t type_index) : HExpression(Primitive::kPrimNot),
1166 dex_pc_(dex_pc), type_index_(type_index) {}
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001167
1168 uint32_t GetDexPc() const { return dex_pc_; }
1169 uint16_t GetTypeIndex() const { return type_index_; }
1170
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001171 // Calls runtime so needs an environment.
1172 virtual bool NeedsEnvironment() const { return true; }
1173
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001174 DECLARE_INSTRUCTION(NewInstance);
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001175
1176 private:
1177 const uint32_t dex_pc_;
1178 const uint16_t type_index_;
1179
1180 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
1181};
1182
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001183class HAdd : public HBinaryOperation {
1184 public:
1185 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1186 : HBinaryOperation(result_type, left, right) {}
1187
1188 virtual bool IsCommutative() { return true; }
1189
1190 DECLARE_INSTRUCTION(Add);
1191
1192 private:
1193 DISALLOW_COPY_AND_ASSIGN(HAdd);
1194};
1195
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001196class HSub : public HBinaryOperation {
1197 public:
1198 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1199 : HBinaryOperation(result_type, left, right) {}
1200
1201 virtual bool IsCommutative() { return false; }
1202
1203 DECLARE_INSTRUCTION(Sub);
1204
1205 private:
1206 DISALLOW_COPY_AND_ASSIGN(HSub);
1207};
1208
1209// The value of a parameter in this method. Its location depends on
1210// the calling convention.
Dave Allison20dfc792014-06-16 20:44:29 -07001211class HParameterValue : public HExpression<0> {
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001212 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001213 HParameterValue(uint8_t index, Primitive::Type parameter_type)
Dave Allison20dfc792014-06-16 20:44:29 -07001214 : HExpression(parameter_type), index_(index) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001215
1216 uint8_t GetIndex() const { return index_; }
1217
1218 DECLARE_INSTRUCTION(ParameterValue);
1219
1220 private:
1221 // The index of this parameter in the parameters list. Must be less
1222 // than HGraph::number_of_in_vregs_;
1223 const uint8_t index_;
1224
1225 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1226};
1227
Dave Allison20dfc792014-06-16 20:44:29 -07001228class HNot : public HExpression<1> {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001229 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001230 explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean) {
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001231 SetRawInputAt(0, input);
1232 }
1233
1234 DECLARE_INSTRUCTION(Not);
1235
1236 private:
1237 DISALLOW_COPY_AND_ASSIGN(HNot);
1238};
1239
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001240class HPhi : public HInstruction {
1241 public:
1242 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
1243 : inputs_(arena, number_of_inputs),
1244 reg_number_(reg_number),
1245 type_(type) {
1246 inputs_.SetSize(number_of_inputs);
1247 }
1248
1249 virtual size_t InputCount() const { return inputs_.Size(); }
1250 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1251
1252 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1253 inputs_.Put(index, input);
1254 }
1255
1256 void AddInput(HInstruction* input);
1257
1258 virtual Primitive::Type GetType() const { return type_; }
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001259 void SetType(Primitive::Type type) { type_ = type; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001260
1261 uint32_t GetRegNumber() const { return reg_number_; }
1262
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001263 DECLARE_INSTRUCTION(Phi);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001264
1265 protected:
1266 GrowableArray<HInstruction*> inputs_;
1267 const uint32_t reg_number_;
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001268 Primitive::Type type_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001269
1270 private:
1271 DISALLOW_COPY_AND_ASSIGN(HPhi);
1272};
1273
Nicolas Geoffraye5038322014-07-04 09:41:32 +01001274class HNullCheck : public HExpression<1> {
1275 public:
1276 HNullCheck(HInstruction* value, uint32_t dex_pc)
1277 : HExpression(value->GetType()), dex_pc_(dex_pc) {
1278 SetRawInputAt(0, value);
1279 }
1280
1281 virtual bool NeedsEnvironment() const { return true; }
1282
1283 uint32_t GetDexPc() const { return dex_pc_; }
1284
1285 DECLARE_INSTRUCTION(NullCheck);
1286
1287 private:
1288 const uint32_t dex_pc_;
1289
1290 DISALLOW_COPY_AND_ASSIGN(HNullCheck);
1291};
1292
1293class FieldInfo : public ValueObject {
1294 public:
1295 explicit FieldInfo(MemberOffset field_offset)
1296 : field_offset_(field_offset) {}
1297
1298 MemberOffset GetFieldOffset() const { return field_offset_; }
1299
1300 private:
1301 const MemberOffset field_offset_;
1302};
1303
1304class HInstanceFieldGet : public HExpression<1> {
1305 public:
1306 HInstanceFieldGet(HInstruction* value,
1307 Primitive::Type field_type,
1308 MemberOffset field_offset)
1309 : HExpression(field_type), field_info_(field_offset) {
1310 SetRawInputAt(0, value);
1311 }
1312
1313 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
1314
1315 DECLARE_INSTRUCTION(InstanceFieldGet);
1316
1317 private:
1318 const FieldInfo field_info_;
1319
1320 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
1321};
1322
1323class HInstanceFieldSet : public HTemplateInstruction<2> {
1324 public:
1325 HInstanceFieldSet(HInstruction* object,
1326 HInstruction* value,
1327 MemberOffset field_offset)
1328 : field_info_(field_offset) {
1329 SetRawInputAt(0, object);
1330 SetRawInputAt(1, value);
1331 }
1332
1333 MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
1334
1335 DECLARE_INSTRUCTION(InstanceFieldSet);
1336
1337 private:
1338 const FieldInfo field_info_;
1339
1340 DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
1341};
1342
1343/**
1344 * Some DEX instructions are folded into multiple HInstructions that need
1345 * to stay live until the last HInstruction. This class
1346 * is used as a marker for the baseline compiler to ensure its preceding
1347 * HInstruction stays live. `index` is the temporary number that is used
1348 * for knowing the stack offset where to store the instruction.
1349 */
1350class HTemporary : public HTemplateInstruction<0> {
1351 public:
1352 explicit HTemporary(size_t index) : index_(index) {}
1353
1354 size_t GetIndex() const { return index_; }
1355
1356 DECLARE_INSTRUCTION(Temporary);
1357
1358 private:
1359 const size_t index_;
1360
1361 DISALLOW_COPY_AND_ASSIGN(HTemporary);
1362};
1363
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001364class MoveOperands : public ArenaObject {
1365 public:
1366 MoveOperands(Location source, Location destination)
1367 : source_(source), destination_(destination) {}
1368
1369 Location GetSource() const { return source_; }
1370 Location GetDestination() const { return destination_; }
1371
1372 void SetSource(Location value) { source_ = value; }
1373 void SetDestination(Location value) { destination_ = value; }
1374
1375 // The parallel move resolver marks moves as "in-progress" by clearing the
1376 // destination (but not the source).
1377 Location MarkPending() {
1378 DCHECK(!IsPending());
1379 Location dest = destination_;
1380 destination_ = Location::NoLocation();
1381 return dest;
1382 }
1383
1384 void ClearPending(Location dest) {
1385 DCHECK(IsPending());
1386 destination_ = dest;
1387 }
1388
1389 bool IsPending() const {
1390 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
1391 return destination_.IsInvalid() && !source_.IsInvalid();
1392 }
1393
1394 // True if this blocks a move from the given location.
1395 bool Blocks(Location loc) const {
1396 return !IsEliminated() && source_.Equals(loc);
1397 }
1398
1399 // A move is redundant if it's been eliminated, if its source and
1400 // destination are the same, or if its destination is unneeded.
1401 bool IsRedundant() const {
1402 return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
1403 }
1404
1405 // We clear both operands to indicate move that's been eliminated.
1406 void Eliminate() {
1407 source_ = destination_ = Location::NoLocation();
1408 }
1409
1410 bool IsEliminated() const {
1411 DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
1412 return source_.IsInvalid();
1413 }
1414
1415 private:
1416 Location source_;
1417 Location destination_;
1418
1419 DISALLOW_COPY_AND_ASSIGN(MoveOperands);
1420};
1421
1422static constexpr size_t kDefaultNumberOfMoves = 4;
1423
1424class HParallelMove : public HTemplateInstruction<0> {
1425 public:
1426 explicit HParallelMove(ArenaAllocator* arena) : moves_(arena, kDefaultNumberOfMoves) {}
1427
1428 void AddMove(MoveOperands* move) {
1429 moves_.Add(move);
1430 }
1431
1432 MoveOperands* MoveOperandsAt(size_t index) const {
1433 return moves_.Get(index);
1434 }
1435
1436 size_t NumMoves() const { return moves_.Size(); }
1437
Nicolas Geoffraya7062e02014-05-22 12:50:17 +01001438 DECLARE_INSTRUCTION(ParallelMove);
Nicolas Geoffray4e3d23a2014-05-22 18:32:45 +01001439
1440 private:
1441 GrowableArray<MoveOperands*> moves_;
1442
1443 DISALLOW_COPY_AND_ASSIGN(HParallelMove);
1444};
1445
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001446class HGraphVisitor : public ValueObject {
1447 public:
Dave Allison20dfc792014-06-16 20:44:29 -07001448 explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
1449 virtual ~HGraphVisitor() {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001450
Dave Allison20dfc792014-06-16 20:44:29 -07001451 virtual void VisitInstruction(HInstruction* instruction) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001452 virtual void VisitBasicBlock(HBasicBlock* block);
1453
1454 void VisitInsertionOrder();
1455
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001456 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001457
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001458 // Visit functions for instruction classes.
1459#define DECLARE_VISIT_INSTRUCTION(name) \
1460 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
1461
1462 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1463
1464#undef DECLARE_VISIT_INSTRUCTION
1465
1466 private:
1467 HGraph* graph_;
1468
1469 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
1470};
1471
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001472class HInsertionOrderIterator : public ValueObject {
1473 public:
1474 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1475
1476 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1477 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1478 void Advance() { ++index_; }
1479
1480 private:
1481 const HGraph& graph_;
1482 size_t index_;
1483
1484 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1485};
1486
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001487class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001488 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001489 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001490
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001491 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
1492 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001493 void Advance() { ++index_; }
1494
1495 private:
1496 const HGraph& graph_;
1497 size_t index_;
1498
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001499 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001500};
1501
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001502class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001503 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001504 explicit HPostOrderIterator(const HGraph& graph)
1505 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001506
1507 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001508 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001509 void Advance() { --index_; }
1510
1511 private:
1512 const HGraph& graph_;
1513 size_t index_;
1514
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001515 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001516};
1517
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001518} // namespace art
1519
1520#endif // ART_COMPILER_OPTIMIZING_NODES_H_