blob: 081c2bd08a63bb7a3b0831a863583446211e3a4d [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
20#include "utils/allocation.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000021#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000022#include "utils/growable_array.h"
23
24namespace art {
25
26class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010027class HEnvironment;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000028class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000029class HIntConstant;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000030class HGraphVisitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010031class HPhi;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000032class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000033
34static const int kDefaultNumberOfBlocks = 8;
35static const int kDefaultNumberOfSuccessors = 2;
36static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000037static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000038
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010039class HInstructionList {
40 public:
41 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
42
43 void AddInstruction(HInstruction* instruction);
44 void RemoveInstruction(HInstruction* instruction);
45
46 private:
47 HInstruction* first_instruction_;
48 HInstruction* last_instruction_;
49
50 friend class HBasicBlock;
51 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +010052 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010053
54 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
55};
56
Nicolas Geoffray818f2102014-02-18 16:43:35 +000057// Control-flow graph of a method. Contains a list of basic blocks.
58class HGraph : public ArenaObject {
59 public:
60 explicit HGraph(ArenaAllocator* arena)
61 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010063 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010064 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010065 number_of_vregs_(0),
66 number_of_in_vregs_(0),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000067 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000068
Nicolas Geoffray787c3072014-03-17 10:20:19 +000069 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +010070 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000071
Nicolas Geoffray787c3072014-03-17 10:20:19 +000072 HBasicBlock* GetEntryBlock() const { return entry_block_; }
73 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000074
Nicolas Geoffray787c3072014-03-17 10:20:19 +000075 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
76 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000077
Nicolas Geoffray818f2102014-02-18 16:43:35 +000078 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010079
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000080 void BuildDominatorTree();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010081 void TransformToSSA();
82 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000083
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010084 // Find all natural loops in this graph. Aborts computation and returns false
85 // if one loop is not natural, that is the header does not dominated the back
86 // edge.
87 bool FindNaturalLoops() const;
88
89 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
90 void SimplifyLoop(HBasicBlock* header);
91
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000092 int GetNextInstructionId() {
93 return current_instruction_id_++;
94 }
95
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010096 uint16_t GetMaximumNumberOfOutVRegs() const {
97 return maximum_number_of_out_vregs_;
98 }
99
100 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
101 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
102 }
103
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100104 void SetNumberOfVRegs(uint16_t number_of_vregs) {
105 number_of_vregs_ = number_of_vregs;
106 }
107
108 uint16_t GetNumberOfVRegs() const {
109 return number_of_vregs_;
110 }
111
112 void SetNumberOfInVRegs(uint16_t value) {
113 number_of_in_vregs_ = value;
114 }
115
116 uint16_t GetNumberOfInVRegs() const {
117 return number_of_in_vregs_;
118 }
119
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100120 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
121 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100122 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100123
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000124 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
126 void VisitBlockForDominatorTree(HBasicBlock* block,
127 HBasicBlock* predecessor,
128 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100129 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000130 void VisitBlockForBackEdges(HBasicBlock* block,
131 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100132 ArenaBitVector* visiting);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000133 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
134
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000135 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000136
137 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000138 GrowableArray<HBasicBlock*> blocks_;
139
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100140 // List of blocks to perform a reverse post order tree traversal.
141 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000142
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000143 HBasicBlock* entry_block_;
144 HBasicBlock* exit_block_;
145
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100146 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100147 uint16_t maximum_number_of_out_vregs_;
148
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100149 // The number of virtual registers in this method. Contains the parameters.
150 uint16_t number_of_vregs_;
151
152 // The number of virtual registers used by parameters of this method.
153 uint16_t number_of_in_vregs_;
154
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000155 // The current id to assign to a newly added instruction. See HInstruction.id_.
156 int current_instruction_id_;
157
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000158 DISALLOW_COPY_AND_ASSIGN(HGraph);
159};
160
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000161class HLoopInformation : public ArenaObject {
162 public:
163 HLoopInformation(HBasicBlock* header, HGraph* graph)
164 : header_(header),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100165 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
166 blocks_(graph->GetArena(), graph->GetBlocks().Size(), false) {}
167
168 HBasicBlock* GetHeader() const {
169 return header_;
170 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000171
172 void AddBackEdge(HBasicBlock* back_edge) {
173 back_edges_.Add(back_edge);
174 }
175
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100176 void RemoveBackEdge(HBasicBlock* back_edge) {
177 back_edges_.Delete(back_edge);
178 }
179
180 bool IsBackEdge(HBasicBlock* block) {
181 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
182 if (back_edges_.Get(i) == block) return true;
183 }
184 return false;
185 }
186
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000187 int NumberOfBackEdges() const {
188 return back_edges_.Size();
189 }
190
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100191 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100192
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100193 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
194 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100195 }
196
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100197 void ClearBackEdges() {
198 back_edges_.Reset();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100199 }
200
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100201 // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
202 // that is the header dominates the back edge.
203 bool Populate();
204
205 // Returns whether this loop information contains `block`.
206 // Note that this loop information *must* be populated before entering this function.
207 bool Contains(const HBasicBlock& block) const;
208
209 // Returns whether this loop information is an inner loop of `other`.
210 // Note that `other` *must* be populated before entering this function.
211 bool IsIn(const HLoopInformation& other) const;
212
213 const ArenaBitVector& GetBlocks() const { return blocks_; }
214
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000215 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100216 // Internal recursive implementation of `Populate`.
217 void PopulateRecursive(HBasicBlock* block);
218
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000219 HBasicBlock* header_;
220 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100221 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000222
223 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
224};
225
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000226// A block in a method. Contains the list of instructions represented
227// as a double linked list. Each block knows its predecessors and
228// successors.
229class HBasicBlock : public ArenaObject {
230 public:
231 explicit HBasicBlock(HGraph* graph)
232 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000233 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
234 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000235 loop_information_(nullptr),
236 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000237 block_id_(-1) { }
238
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100239 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
240 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000241 }
242
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100243 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
244 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000245 }
246
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000247 void AddBackEdge(HBasicBlock* back_edge) {
248 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000249 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000250 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100251 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000252 loop_information_->AddBackEdge(back_edge);
253 }
254
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000255 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000256
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000257 int GetBlockId() const { return block_id_; }
258 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000259
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000260 HBasicBlock* GetDominator() const { return dominator_; }
261 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000262
263 int NumberOfBackEdges() const {
264 return loop_information_ == nullptr
265 ? 0
266 : loop_information_->NumberOfBackEdges();
267 }
268
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100269 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
270 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
271 HInstructionList const* GetInstructions() const { return &instructions_; }
272 HInstructionList const* GetPhis() const { return &phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000273
274 void AddSuccessor(HBasicBlock* block) {
275 successors_.Add(block);
276 block->predecessors_.Add(this);
277 }
278
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100279 void RemovePredecessor(HBasicBlock* block, bool remove_in_successor = true) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000280 predecessors_.Delete(block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100281 if (remove_in_successor) {
282 block->successors_.Delete(this);
283 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000284 }
285
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100286 void RemoveSuccessor(HBasicBlock* block, bool remove_in_predecessor = true) {
287 successors_.Delete(block);
288 if (remove_in_predecessor) {
289 block->predecessors_.Delete(this);
290 }
291 }
292
293 void ClearAllPredecessors() {
294 predecessors_.Reset();
295 }
296
297 void AddPredecessor(HBasicBlock* block) {
298 predecessors_.Add(block);
299 block->successors_.Add(this);
300 }
301
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000302 void AddInstruction(HInstruction* instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100303 void RemoveInstruction(HInstruction* instruction);
304 void AddPhi(HPhi* phi);
305 void RemovePhi(HPhi* phi);
306
307 bool IsLoopHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100308 return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100309 }
310
311 HLoopInformation* GetLoopInformation() const {
312 return loop_information_;
313 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000314
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100315 // Set the loop_information_ on this block. This method overrides the current
316 // loop_information if it is an outer loop of the passed loop information.
317 void SetInLoop(HLoopInformation* info) {
318 if (IsLoopHeader()) {
319 // Nothing to do. This just means `info` is an outer loop.
320 } else if (loop_information_ == nullptr) {
321 loop_information_ = info;
322 } else if (loop_information_->Contains(*info->GetHeader())) {
323 // Block is currently part of an outer loop. Make it part of this inner loop.
324 // Note that a non loop header having a loop information means this loop information
325 // has already been populated
326 loop_information_ = info;
327 } else {
328 // Block is part of an inner loop. Do not update the loop information.
329 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
330 // at this point, because this method is being called while populating `info`.
331 }
332 }
333
334 // Returns wheter this block dominates the blocked passed as parameter.
335 bool Dominates(HBasicBlock* block) const;
336
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000337 private:
338 HGraph* const graph_;
339 GrowableArray<HBasicBlock*> predecessors_;
340 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100341 HInstructionList instructions_;
342 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000343 HLoopInformation* loop_information_;
344 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000345 int block_id_;
346
347 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
348};
349
350#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000351 M(Add) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000352 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000353 M(Exit) \
354 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000355 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000356 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000357 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000358 M(LoadLocal) \
359 M(Local) \
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100360 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100361 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100362 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100363 M(ParameterValue) \
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100364 M(Phi) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000365 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000366 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000367 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100368 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000369
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000370#define FORWARD_DECLARATION(type) class H##type;
371FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
372#undef FORWARD_DECLARATION
373
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000374#define DECLARE_INSTRUCTION(type) \
375 virtual void Accept(HGraphVisitor* visitor); \
376 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000377 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000378
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100379template <typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000380class HUseListNode : public ArenaObject {
381 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100382 HUseListNode(T* user, size_t index, HUseListNode* tail)
383 : user_(user), index_(index), tail_(tail) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000384
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000385 HUseListNode* GetTail() const { return tail_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100386 T* GetUser() const { return user_; }
387 size_t GetIndex() const { return index_; }
388
389 void SetTail(HUseListNode<T>* node) { tail_ = node; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000390
391 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100392 T* const user_;
393 const size_t index_;
394 HUseListNode<T>* tail_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000395
396 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
397};
398
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000399class HInstruction : public ArenaObject {
400 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000401 HInstruction()
402 : previous_(nullptr),
403 next_(nullptr),
404 block_(nullptr),
405 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100406 ssa_index_(-1),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000407 uses_(nullptr),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100408 env_uses_(nullptr),
409 environment_(nullptr),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000410 locations_(nullptr) { }
411
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000412 virtual ~HInstruction() { }
413
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000414 HInstruction* GetNext() const { return next_; }
415 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000416
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000417 HBasicBlock* GetBlock() const { return block_; }
418 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000419
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100420 virtual size_t InputCount() const = 0;
421 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000422
423 virtual void Accept(HGraphVisitor* visitor) = 0;
424 virtual const char* DebugName() const = 0;
425
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100426 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100427 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100428
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100429 virtual bool NeedsEnvironment() const { return false; }
430
431 void AddUseAt(HInstruction* user, size_t index) {
432 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000433 }
434
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100435 void AddEnvUseAt(HEnvironment* user, size_t index) {
436 env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
437 user, index, env_uses_);
438 }
439
440 void RemoveUser(HInstruction* user, size_t index);
441
442 HUseListNode<HInstruction>* GetUses() const { return uses_; }
443 HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000444
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100445 bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000446
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000447 int GetId() const { return id_; }
448 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000449
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100450 int GetSsaIndex() const { return ssa_index_; }
451 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
452 bool HasSsaIndex() const { return ssa_index_ != -1; }
453
454 bool HasEnvironment() const { return environment_ != nullptr; }
455 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100456 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
457
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000458 LocationSummary* GetLocations() const { return locations_; }
459 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000460
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100461 void ReplaceWith(HInstruction* instruction);
462
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000463#define INSTRUCTION_TYPE_CHECK(type) \
464 virtual H##type* As##type() { return nullptr; }
465
466 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
467#undef INSTRUCTION_TYPE_CHECK
468
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000469 private:
470 HInstruction* previous_;
471 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000472 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000473
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000474 // An instruction gets an id when it is added to the graph.
475 // It reflects creation order. A negative id means the instruction
476 // has not beed added to the graph.
477 int id_;
478
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100479 // When doing liveness analysis, instructions that have uses get an SSA index.
480 int ssa_index_;
481
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100482 // List of instructions that have this instruction as input.
483 HUseListNode<HInstruction>* uses_;
484
485 // List of environments that contain this instruction.
486 HUseListNode<HEnvironment>* env_uses_;
487
488 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000489
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000490 // Set by the code generator.
491 LocationSummary* locations_;
492
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000493 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100494 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000495
496 DISALLOW_COPY_AND_ASSIGN(HInstruction);
497};
498
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100499template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000500class HUseIterator : public ValueObject {
501 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100502 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000503
504 bool Done() const { return current_ == nullptr; }
505
506 void Advance() {
507 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000508 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000509 }
510
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100511 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000512 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100513 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000514 }
515
516 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100517 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000518
519 friend class HValue;
520};
521
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100522// A HEnvironment object contains the values of virtual registers at a given location.
523class HEnvironment : public ArenaObject {
524 public:
525 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
526 vregs_.SetSize(number_of_vregs);
527 for (size_t i = 0; i < number_of_vregs; i++) {
528 vregs_.Put(i, nullptr);
529 }
530 }
531
532 void Populate(const GrowableArray<HInstruction*>& env) {
533 for (size_t i = 0; i < env.Size(); i++) {
534 HInstruction* instruction = env.Get(i);
535 vregs_.Put(i, instruction);
536 if (instruction != nullptr) {
537 instruction->AddEnvUseAt(this, i);
538 }
539 }
540 }
541
542 void SetRawEnvAt(size_t index, HInstruction* instruction) {
543 vregs_.Put(index, instruction);
544 }
545
546 GrowableArray<HInstruction*>* GetVRegs() {
547 return &vregs_;
548 }
549
550 private:
551 GrowableArray<HInstruction*> vregs_;
552
553 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
554};
555
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000556class HInputIterator : public ValueObject {
557 public:
558 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
559
560 bool Done() const { return index_ == instruction_->InputCount(); }
561 HInstruction* Current() const { return instruction_->InputAt(index_); }
562 void Advance() { index_++; }
563
564 private:
565 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100566 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000567
568 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
569};
570
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000571class HInstructionIterator : public ValueObject {
572 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100573 explicit HInstructionIterator(const HInstructionList& instructions)
574 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000575 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000576 }
577
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000578 bool Done() const { return instruction_ == nullptr; }
579 HInstruction* Current() const { return instruction_; }
580 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000581 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000582 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000583 }
584
585 private:
586 HInstruction* instruction_;
587 HInstruction* next_;
588};
589
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100590class HBackwardInstructionIterator : public ValueObject {
591 public:
592 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
593 : instruction_(instructions.last_instruction_) {
594 next_ = Done() ? nullptr : instruction_->GetPrevious();
595 }
596
597 bool Done() const { return instruction_ == nullptr; }
598 HInstruction* Current() const { return instruction_; }
599 void Advance() {
600 instruction_ = next_;
601 next_ = Done() ? nullptr : instruction_->GetPrevious();
602 }
603
604 private:
605 HInstruction* instruction_;
606 HInstruction* next_;
607};
608
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000609// An embedded container with N elements of type T. Used (with partial
610// specialization for N=0) because embedded arrays cannot have size 0.
611template<typename T, intptr_t N>
612class EmbeddedArray {
613 public:
614 EmbeddedArray() : elements_() { }
615
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000616 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000617
618 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000619 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000620 return elements_[i];
621 }
622
623 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000624 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000625 return elements_[i];
626 }
627
628 const T& At(intptr_t i) const {
629 return (*this)[i];
630 }
631
632 void SetAt(intptr_t i, const T& val) {
633 (*this)[i] = val;
634 }
635
636 private:
637 T elements_[N];
638};
639
640template<typename T>
641class EmbeddedArray<T, 0> {
642 public:
643 intptr_t length() const { return 0; }
644 const T& operator[](intptr_t i) const {
645 LOG(FATAL) << "Unreachable";
646 static T sentinel = 0;
647 return sentinel;
648 }
649 T& operator[](intptr_t i) {
650 LOG(FATAL) << "Unreachable";
651 static T sentinel = 0;
652 return sentinel;
653 }
654};
655
656template<intptr_t N>
657class HTemplateInstruction: public HInstruction {
658 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000659 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000660 virtual ~HTemplateInstruction() { }
661
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100662 virtual size_t InputCount() const { return N; }
663 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000664
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000665 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100666 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000667 inputs_[i] = instruction;
668 }
669
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000670 private:
671 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100672
673 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000674};
675
676// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
677// instruction that branches to the exit block.
678class HReturnVoid : public HTemplateInstruction<0> {
679 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000680 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000681
682 DECLARE_INSTRUCTION(ReturnVoid)
683
684 private:
685 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
686};
687
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000688// Represents dex's RETURN opcodes. A HReturn is a control flow
689// instruction that branches to the exit block.
690class HReturn : public HTemplateInstruction<1> {
691 public:
692 explicit HReturn(HInstruction* value) {
693 SetRawInputAt(0, value);
694 }
695
696 DECLARE_INSTRUCTION(Return)
697
698 private:
699 DISALLOW_COPY_AND_ASSIGN(HReturn);
700};
701
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000702// The exit instruction is the only instruction of the exit block.
703// Instructions aborting the method (HTrow and HReturn) must branch to the
704// exit block.
705class HExit : public HTemplateInstruction<0> {
706 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000707 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000708
709 DECLARE_INSTRUCTION(Exit)
710
711 private:
712 DISALLOW_COPY_AND_ASSIGN(HExit);
713};
714
715// Jumps from one block to another.
716class HGoto : public HTemplateInstruction<0> {
717 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000718 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000719
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000720 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100721 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000722 }
723
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000724 DECLARE_INSTRUCTION(Goto)
725
726 private:
727 DISALLOW_COPY_AND_ASSIGN(HGoto);
728};
729
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000730// Conditional branch. A block ending with an HIf instruction must have
731// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000732class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000733 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000734 explicit HIf(HInstruction* input) {
735 SetRawInputAt(0, input);
736 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000737
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000738 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100739 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000740 }
741
742 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100743 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000744 }
745
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000746 DECLARE_INSTRUCTION(If)
747
748 private:
749 DISALLOW_COPY_AND_ASSIGN(HIf);
750};
751
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000752class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000753 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000754 HBinaryOperation(Primitive::Type result_type,
755 HInstruction* left,
756 HInstruction* right) : result_type_(result_type) {
757 SetRawInputAt(0, left);
758 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000759 }
760
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000761 HInstruction* GetLeft() const { return InputAt(0); }
762 HInstruction* GetRight() const { return InputAt(1); }
763 Primitive::Type GetResultType() const { return result_type_; }
764
765 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100766 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000767
768 private:
769 const Primitive::Type result_type_;
770
771 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
772};
773
774
775// Instruction to check if two inputs are equal to each other.
776class HEqual : public HBinaryOperation {
777 public:
778 HEqual(HInstruction* first, HInstruction* second)
779 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
780
781 virtual bool IsCommutative() { return true; }
782
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100783 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
784
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000785 DECLARE_INSTRUCTION(Equal)
786
787 private:
788 DISALLOW_COPY_AND_ASSIGN(HEqual);
789};
790
791// A local in the graph. Corresponds to a Dex register.
792class HLocal : public HTemplateInstruction<0> {
793 public:
794 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
795
796 DECLARE_INSTRUCTION(Local)
797
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000798 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000799
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000800 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000801 // The Dex register number.
802 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000803
804 DISALLOW_COPY_AND_ASSIGN(HLocal);
805};
806
807// Load a given local. The local is an input of this instruction.
808class HLoadLocal : public HTemplateInstruction<1> {
809 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100810 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000811 SetRawInputAt(0, local);
812 }
813
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100814 virtual Primitive::Type GetType() const { return type_; }
815
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000816 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
817
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000818 DECLARE_INSTRUCTION(LoadLocal)
819
820 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100821 const Primitive::Type type_;
822
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000823 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
824};
825
826// Store a value in a given local. This instruction has two inputs: the value
827// and the local.
828class HStoreLocal : public HTemplateInstruction<2> {
829 public:
830 HStoreLocal(HLocal* local, HInstruction* value) {
831 SetRawInputAt(0, local);
832 SetRawInputAt(1, value);
833 }
834
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000835 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
836
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000837 DECLARE_INSTRUCTION(StoreLocal)
838
839 private:
840 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
841};
842
843// Constants of the type int. Those can be from Dex instructions, or
844// synthesized (for example with the if-eqz instruction).
845class HIntConstant : public HTemplateInstruction<0> {
846 public:
847 explicit HIntConstant(int32_t value) : value_(value) { }
848
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000849 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100850 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000851
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000852 DECLARE_INSTRUCTION(IntConstant)
853
854 private:
855 const int32_t value_;
856
857 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
858};
859
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100860class HLongConstant : public HTemplateInstruction<0> {
861 public:
862 explicit HLongConstant(int64_t value) : value_(value) { }
863
864 int64_t GetValue() const { return value_; }
865
866 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
867
868 DECLARE_INSTRUCTION(LongConstant)
869
870 private:
871 const int64_t value_;
872
873 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
874};
875
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000876class HInvoke : public HInstruction {
877 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100878 HInvoke(ArenaAllocator* arena,
879 uint32_t number_of_arguments,
880 Primitive::Type return_type,
881 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000882 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100883 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000884 dex_pc_(dex_pc) {
885 inputs_.SetSize(number_of_arguments);
886 }
887
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100888 virtual size_t InputCount() const { return inputs_.Size(); }
889 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
890
891 // Runtime needs to walk the stack, so Dex -> Dex calls need to
892 // know their environment.
893 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000894
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100895 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100896 SetRawInputAt(index, argument);
897 }
898
899 virtual void SetRawInputAt(size_t index, HInstruction* input) {
900 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100901 }
902
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100903 virtual Primitive::Type GetType() const { return return_type_; }
904
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100905 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000906
907 protected:
908 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100909 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100910 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000911
912 private:
913 DISALLOW_COPY_AND_ASSIGN(HInvoke);
914};
915
916class HInvokeStatic : public HInvoke {
917 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100918 HInvokeStatic(ArenaAllocator* arena,
919 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100920 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100921 uint32_t dex_pc,
922 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100923 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
924 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000925
926 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
927
928 DECLARE_INSTRUCTION(InvokeStatic)
929
930 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100931 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000932
933 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
934};
935
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100936class HNewInstance : public HTemplateInstruction<0> {
937 public:
938 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
939
940 uint32_t GetDexPc() const { return dex_pc_; }
941 uint16_t GetTypeIndex() const { return type_index_; }
942
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100943 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
944
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100945 // Calls runtime so needs an environment.
946 virtual bool NeedsEnvironment() const { return true; }
947
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100948 DECLARE_INSTRUCTION(NewInstance)
949
950 private:
951 const uint32_t dex_pc_;
952 const uint16_t type_index_;
953
954 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
955};
956
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000957class HAdd : public HBinaryOperation {
958 public:
959 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
960 : HBinaryOperation(result_type, left, right) {}
961
962 virtual bool IsCommutative() { return true; }
963
964 DECLARE_INSTRUCTION(Add);
965
966 private:
967 DISALLOW_COPY_AND_ASSIGN(HAdd);
968};
969
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100970class HSub : public HBinaryOperation {
971 public:
972 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
973 : HBinaryOperation(result_type, left, right) {}
974
975 virtual bool IsCommutative() { return false; }
976
977 DECLARE_INSTRUCTION(Sub);
978
979 private:
980 DISALLOW_COPY_AND_ASSIGN(HSub);
981};
982
983// The value of a parameter in this method. Its location depends on
984// the calling convention.
985class HParameterValue : public HTemplateInstruction<0> {
986 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100987 HParameterValue(uint8_t index, Primitive::Type parameter_type)
988 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100989
990 uint8_t GetIndex() const { return index_; }
991
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100992 virtual Primitive::Type GetType() const { return parameter_type_; }
993
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100994 DECLARE_INSTRUCTION(ParameterValue);
995
996 private:
997 // The index of this parameter in the parameters list. Must be less
998 // than HGraph::number_of_in_vregs_;
999 const uint8_t index_;
1000
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001001 const Primitive::Type parameter_type_;
1002
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001003 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1004};
1005
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001006class HNot : public HTemplateInstruction<1> {
1007 public:
1008 explicit HNot(HInstruction* input) {
1009 SetRawInputAt(0, input);
1010 }
1011
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001012 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
1013
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001014 DECLARE_INSTRUCTION(Not);
1015
1016 private:
1017 DISALLOW_COPY_AND_ASSIGN(HNot);
1018};
1019
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001020class HPhi : public HInstruction {
1021 public:
1022 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
1023 : inputs_(arena, number_of_inputs),
1024 reg_number_(reg_number),
1025 type_(type) {
1026 inputs_.SetSize(number_of_inputs);
1027 }
1028
1029 virtual size_t InputCount() const { return inputs_.Size(); }
1030 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1031
1032 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1033 inputs_.Put(index, input);
1034 }
1035
1036 void AddInput(HInstruction* input);
1037
1038 virtual Primitive::Type GetType() const { return type_; }
1039
1040 uint32_t GetRegNumber() const { return reg_number_; }
1041
1042 DECLARE_INSTRUCTION(Phi)
1043
1044 protected:
1045 GrowableArray<HInstruction*> inputs_;
1046 const uint32_t reg_number_;
1047 const Primitive::Type type_;
1048
1049 private:
1050 DISALLOW_COPY_AND_ASSIGN(HPhi);
1051};
1052
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001053class HGraphVisitor : public ValueObject {
1054 public:
1055 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
1056 virtual ~HGraphVisitor() { }
1057
1058 virtual void VisitInstruction(HInstruction* instruction) { }
1059 virtual void VisitBasicBlock(HBasicBlock* block);
1060
1061 void VisitInsertionOrder();
1062
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001063 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001064
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001065 // Visit functions for instruction classes.
1066#define DECLARE_VISIT_INSTRUCTION(name) \
1067 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
1068
1069 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1070
1071#undef DECLARE_VISIT_INSTRUCTION
1072
1073 private:
1074 HGraph* graph_;
1075
1076 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
1077};
1078
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001079class HInsertionOrderIterator : public ValueObject {
1080 public:
1081 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1082
1083 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1084 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1085 void Advance() { ++index_; }
1086
1087 private:
1088 const HGraph& graph_;
1089 size_t index_;
1090
1091 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1092};
1093
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001094class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001095 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001096 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001097
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001098 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
1099 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001100 void Advance() { ++index_; }
1101
1102 private:
1103 const HGraph& graph_;
1104 size_t index_;
1105
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001106 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001107};
1108
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001109class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001110 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001111 explicit HPostOrderIterator(const HGraph& graph)
1112 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001113
1114 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001115 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001116 void Advance() { --index_; }
1117
1118 private:
1119 const HGraph& graph_;
1120 size_t index_;
1121
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001122 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001123};
1124
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001125} // namespace art
1126
1127#endif // ART_COMPILER_OPTIMIZING_NODES_H_