blob: 1085c105ad7aadf7f20c1f54a6e8806b47750fc8 [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
Nicolas Geoffrayf635e632014-05-14 09:43:38 +010085 // if one loop is not natural, that is the header does not dominate the back
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010086 // 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_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100271 const HInstructionList& GetInstructions() const { return instructions_; }
272 const HInstructionList& 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 Geoffrayf635e632014-05-14 09:43:38 +0100447 size_t NumberOfUses() const {
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100448 // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100449 size_t result = 0;
450 HUseListNode<HInstruction>* current = uses_;
451 while (current != nullptr) {
452 current = current->GetTail();
453 ++result;
454 }
455 return result;
456 }
457
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000458 int GetId() const { return id_; }
459 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000460
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100461 int GetSsaIndex() const { return ssa_index_; }
462 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
463 bool HasSsaIndex() const { return ssa_index_ != -1; }
464
465 bool HasEnvironment() const { return environment_ != nullptr; }
466 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100467 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
468
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000469 LocationSummary* GetLocations() const { return locations_; }
470 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000471
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100472 void ReplaceWith(HInstruction* instruction);
473
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000474#define INSTRUCTION_TYPE_CHECK(type) \
475 virtual H##type* As##type() { return nullptr; }
476
477 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
478#undef INSTRUCTION_TYPE_CHECK
479
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000480 private:
481 HInstruction* previous_;
482 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000483 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000484
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000485 // An instruction gets an id when it is added to the graph.
486 // It reflects creation order. A negative id means the instruction
487 // has not beed added to the graph.
488 int id_;
489
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100490 // When doing liveness analysis, instructions that have uses get an SSA index.
491 int ssa_index_;
492
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100493 // List of instructions that have this instruction as input.
494 HUseListNode<HInstruction>* uses_;
495
496 // List of environments that contain this instruction.
497 HUseListNode<HEnvironment>* env_uses_;
498
499 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000500
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000501 // Set by the code generator.
502 LocationSummary* locations_;
503
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000504 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100505 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000506
507 DISALLOW_COPY_AND_ASSIGN(HInstruction);
508};
509
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100510template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000511class HUseIterator : public ValueObject {
512 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100513 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000514
515 bool Done() const { return current_ == nullptr; }
516
517 void Advance() {
518 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000519 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000520 }
521
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100522 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000523 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100524 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000525 }
526
527 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100528 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000529
530 friend class HValue;
531};
532
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100533// A HEnvironment object contains the values of virtual registers at a given location.
534class HEnvironment : public ArenaObject {
535 public:
536 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
537 vregs_.SetSize(number_of_vregs);
538 for (size_t i = 0; i < number_of_vregs; i++) {
539 vregs_.Put(i, nullptr);
540 }
541 }
542
543 void Populate(const GrowableArray<HInstruction*>& env) {
544 for (size_t i = 0; i < env.Size(); i++) {
545 HInstruction* instruction = env.Get(i);
546 vregs_.Put(i, instruction);
547 if (instruction != nullptr) {
548 instruction->AddEnvUseAt(this, i);
549 }
550 }
551 }
552
553 void SetRawEnvAt(size_t index, HInstruction* instruction) {
554 vregs_.Put(index, instruction);
555 }
556
557 GrowableArray<HInstruction*>* GetVRegs() {
558 return &vregs_;
559 }
560
561 private:
562 GrowableArray<HInstruction*> vregs_;
563
564 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
565};
566
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000567class HInputIterator : public ValueObject {
568 public:
569 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
570
571 bool Done() const { return index_ == instruction_->InputCount(); }
572 HInstruction* Current() const { return instruction_->InputAt(index_); }
573 void Advance() { index_++; }
574
575 private:
576 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100577 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000578
579 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
580};
581
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000582class HInstructionIterator : public ValueObject {
583 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100584 explicit HInstructionIterator(const HInstructionList& instructions)
585 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000586 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000587 }
588
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000589 bool Done() const { return instruction_ == nullptr; }
590 HInstruction* Current() const { return instruction_; }
591 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000592 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000593 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000594 }
595
596 private:
597 HInstruction* instruction_;
598 HInstruction* next_;
599};
600
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100601class HBackwardInstructionIterator : public ValueObject {
602 public:
603 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
604 : instruction_(instructions.last_instruction_) {
605 next_ = Done() ? nullptr : instruction_->GetPrevious();
606 }
607
608 bool Done() const { return instruction_ == nullptr; }
609 HInstruction* Current() const { return instruction_; }
610 void Advance() {
611 instruction_ = next_;
612 next_ = Done() ? nullptr : instruction_->GetPrevious();
613 }
614
615 private:
616 HInstruction* instruction_;
617 HInstruction* next_;
618};
619
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000620// An embedded container with N elements of type T. Used (with partial
621// specialization for N=0) because embedded arrays cannot have size 0.
622template<typename T, intptr_t N>
623class EmbeddedArray {
624 public:
625 EmbeddedArray() : elements_() { }
626
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000627 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000628
629 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000630 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000631 return elements_[i];
632 }
633
634 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000635 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000636 return elements_[i];
637 }
638
639 const T& At(intptr_t i) const {
640 return (*this)[i];
641 }
642
643 void SetAt(intptr_t i, const T& val) {
644 (*this)[i] = val;
645 }
646
647 private:
648 T elements_[N];
649};
650
651template<typename T>
652class EmbeddedArray<T, 0> {
653 public:
654 intptr_t length() const { return 0; }
655 const T& operator[](intptr_t i) const {
656 LOG(FATAL) << "Unreachable";
657 static T sentinel = 0;
658 return sentinel;
659 }
660 T& operator[](intptr_t i) {
661 LOG(FATAL) << "Unreachable";
662 static T sentinel = 0;
663 return sentinel;
664 }
665};
666
667template<intptr_t N>
668class HTemplateInstruction: public HInstruction {
669 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000670 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000671 virtual ~HTemplateInstruction() { }
672
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100673 virtual size_t InputCount() const { return N; }
674 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000675
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000676 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100677 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000678 inputs_[i] = instruction;
679 }
680
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000681 private:
682 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100683
684 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000685};
686
687// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
688// instruction that branches to the exit block.
689class HReturnVoid : public HTemplateInstruction<0> {
690 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000691 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000692
693 DECLARE_INSTRUCTION(ReturnVoid)
694
695 private:
696 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
697};
698
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000699// Represents dex's RETURN opcodes. A HReturn is a control flow
700// instruction that branches to the exit block.
701class HReturn : public HTemplateInstruction<1> {
702 public:
703 explicit HReturn(HInstruction* value) {
704 SetRawInputAt(0, value);
705 }
706
707 DECLARE_INSTRUCTION(Return)
708
709 private:
710 DISALLOW_COPY_AND_ASSIGN(HReturn);
711};
712
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000713// The exit instruction is the only instruction of the exit block.
714// Instructions aborting the method (HTrow and HReturn) must branch to the
715// exit block.
716class HExit : public HTemplateInstruction<0> {
717 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000718 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000719
720 DECLARE_INSTRUCTION(Exit)
721
722 private:
723 DISALLOW_COPY_AND_ASSIGN(HExit);
724};
725
726// Jumps from one block to another.
727class HGoto : public HTemplateInstruction<0> {
728 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000729 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000730
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000731 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100732 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000733 }
734
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000735 DECLARE_INSTRUCTION(Goto)
736
737 private:
738 DISALLOW_COPY_AND_ASSIGN(HGoto);
739};
740
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000741// Conditional branch. A block ending with an HIf instruction must have
742// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000743class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000744 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000745 explicit HIf(HInstruction* input) {
746 SetRawInputAt(0, input);
747 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000748
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000749 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100750 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000751 }
752
753 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100754 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000755 }
756
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000757 DECLARE_INSTRUCTION(If)
758
759 private:
760 DISALLOW_COPY_AND_ASSIGN(HIf);
761};
762
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000763class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000764 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000765 HBinaryOperation(Primitive::Type result_type,
766 HInstruction* left,
767 HInstruction* right) : result_type_(result_type) {
768 SetRawInputAt(0, left);
769 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000770 }
771
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000772 HInstruction* GetLeft() const { return InputAt(0); }
773 HInstruction* GetRight() const { return InputAt(1); }
774 Primitive::Type GetResultType() const { return result_type_; }
775
776 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100777 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000778
779 private:
780 const Primitive::Type result_type_;
781
782 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
783};
784
785
786// Instruction to check if two inputs are equal to each other.
787class HEqual : public HBinaryOperation {
788 public:
789 HEqual(HInstruction* first, HInstruction* second)
790 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
791
792 virtual bool IsCommutative() { return true; }
793
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100794 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
795
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000796 DECLARE_INSTRUCTION(Equal)
797
798 private:
799 DISALLOW_COPY_AND_ASSIGN(HEqual);
800};
801
802// A local in the graph. Corresponds to a Dex register.
803class HLocal : public HTemplateInstruction<0> {
804 public:
805 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
806
807 DECLARE_INSTRUCTION(Local)
808
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000809 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000810
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000811 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000812 // The Dex register number.
813 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000814
815 DISALLOW_COPY_AND_ASSIGN(HLocal);
816};
817
818// Load a given local. The local is an input of this instruction.
819class HLoadLocal : public HTemplateInstruction<1> {
820 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100821 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000822 SetRawInputAt(0, local);
823 }
824
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100825 virtual Primitive::Type GetType() const { return type_; }
826
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000827 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
828
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000829 DECLARE_INSTRUCTION(LoadLocal)
830
831 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100832 const Primitive::Type type_;
833
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000834 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
835};
836
837// Store a value in a given local. This instruction has two inputs: the value
838// and the local.
839class HStoreLocal : public HTemplateInstruction<2> {
840 public:
841 HStoreLocal(HLocal* local, HInstruction* value) {
842 SetRawInputAt(0, local);
843 SetRawInputAt(1, value);
844 }
845
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000846 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
847
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000848 DECLARE_INSTRUCTION(StoreLocal)
849
850 private:
851 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
852};
853
854// Constants of the type int. Those can be from Dex instructions, or
855// synthesized (for example with the if-eqz instruction).
856class HIntConstant : public HTemplateInstruction<0> {
857 public:
858 explicit HIntConstant(int32_t value) : value_(value) { }
859
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000860 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100861 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000862
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000863 DECLARE_INSTRUCTION(IntConstant)
864
865 private:
866 const int32_t value_;
867
868 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
869};
870
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100871class HLongConstant : public HTemplateInstruction<0> {
872 public:
873 explicit HLongConstant(int64_t value) : value_(value) { }
874
875 int64_t GetValue() const { return value_; }
876
877 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
878
879 DECLARE_INSTRUCTION(LongConstant)
880
881 private:
882 const int64_t value_;
883
884 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
885};
886
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000887class HInvoke : public HInstruction {
888 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100889 HInvoke(ArenaAllocator* arena,
890 uint32_t number_of_arguments,
891 Primitive::Type return_type,
892 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000893 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100894 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000895 dex_pc_(dex_pc) {
896 inputs_.SetSize(number_of_arguments);
897 }
898
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100899 virtual size_t InputCount() const { return inputs_.Size(); }
900 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
901
902 // Runtime needs to walk the stack, so Dex -> Dex calls need to
903 // know their environment.
904 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000905
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100906 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100907 SetRawInputAt(index, argument);
908 }
909
910 virtual void SetRawInputAt(size_t index, HInstruction* input) {
911 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100912 }
913
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100914 virtual Primitive::Type GetType() const { return return_type_; }
915
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100916 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000917
918 protected:
919 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100920 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100921 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000922
923 private:
924 DISALLOW_COPY_AND_ASSIGN(HInvoke);
925};
926
927class HInvokeStatic : public HInvoke {
928 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100929 HInvokeStatic(ArenaAllocator* arena,
930 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100931 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100932 uint32_t dex_pc,
933 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100934 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
935 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000936
937 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
938
939 DECLARE_INSTRUCTION(InvokeStatic)
940
941 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100942 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000943
944 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
945};
946
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100947class HNewInstance : public HTemplateInstruction<0> {
948 public:
949 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
950
951 uint32_t GetDexPc() const { return dex_pc_; }
952 uint16_t GetTypeIndex() const { return type_index_; }
953
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100954 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
955
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100956 // Calls runtime so needs an environment.
957 virtual bool NeedsEnvironment() const { return true; }
958
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100959 DECLARE_INSTRUCTION(NewInstance)
960
961 private:
962 const uint32_t dex_pc_;
963 const uint16_t type_index_;
964
965 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
966};
967
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000968class HAdd : public HBinaryOperation {
969 public:
970 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
971 : HBinaryOperation(result_type, left, right) {}
972
973 virtual bool IsCommutative() { return true; }
974
975 DECLARE_INSTRUCTION(Add);
976
977 private:
978 DISALLOW_COPY_AND_ASSIGN(HAdd);
979};
980
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100981class HSub : public HBinaryOperation {
982 public:
983 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
984 : HBinaryOperation(result_type, left, right) {}
985
986 virtual bool IsCommutative() { return false; }
987
988 DECLARE_INSTRUCTION(Sub);
989
990 private:
991 DISALLOW_COPY_AND_ASSIGN(HSub);
992};
993
994// The value of a parameter in this method. Its location depends on
995// the calling convention.
996class HParameterValue : public HTemplateInstruction<0> {
997 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100998 HParameterValue(uint8_t index, Primitive::Type parameter_type)
999 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001000
1001 uint8_t GetIndex() const { return index_; }
1002
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001003 virtual Primitive::Type GetType() const { return parameter_type_; }
1004
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001005 DECLARE_INSTRUCTION(ParameterValue);
1006
1007 private:
1008 // The index of this parameter in the parameters list. Must be less
1009 // than HGraph::number_of_in_vregs_;
1010 const uint8_t index_;
1011
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001012 const Primitive::Type parameter_type_;
1013
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001014 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1015};
1016
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001017class HNot : public HTemplateInstruction<1> {
1018 public:
1019 explicit HNot(HInstruction* input) {
1020 SetRawInputAt(0, input);
1021 }
1022
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001023 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
1024
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001025 DECLARE_INSTRUCTION(Not);
1026
1027 private:
1028 DISALLOW_COPY_AND_ASSIGN(HNot);
1029};
1030
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001031class HPhi : public HInstruction {
1032 public:
1033 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
1034 : inputs_(arena, number_of_inputs),
1035 reg_number_(reg_number),
1036 type_(type) {
1037 inputs_.SetSize(number_of_inputs);
1038 }
1039
1040 virtual size_t InputCount() const { return inputs_.Size(); }
1041 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1042
1043 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1044 inputs_.Put(index, input);
1045 }
1046
1047 void AddInput(HInstruction* input);
1048
1049 virtual Primitive::Type GetType() const { return type_; }
1050
1051 uint32_t GetRegNumber() const { return reg_number_; }
1052
1053 DECLARE_INSTRUCTION(Phi)
1054
1055 protected:
1056 GrowableArray<HInstruction*> inputs_;
1057 const uint32_t reg_number_;
1058 const Primitive::Type type_;
1059
1060 private:
1061 DISALLOW_COPY_AND_ASSIGN(HPhi);
1062};
1063
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001064class HGraphVisitor : public ValueObject {
1065 public:
1066 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
1067 virtual ~HGraphVisitor() { }
1068
1069 virtual void VisitInstruction(HInstruction* instruction) { }
1070 virtual void VisitBasicBlock(HBasicBlock* block);
1071
1072 void VisitInsertionOrder();
1073
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001074 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001075
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001076 // Visit functions for instruction classes.
1077#define DECLARE_VISIT_INSTRUCTION(name) \
1078 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
1079
1080 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1081
1082#undef DECLARE_VISIT_INSTRUCTION
1083
1084 private:
1085 HGraph* graph_;
1086
1087 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
1088};
1089
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001090class HInsertionOrderIterator : public ValueObject {
1091 public:
1092 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1093
1094 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1095 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1096 void Advance() { ++index_; }
1097
1098 private:
1099 const HGraph& graph_;
1100 size_t index_;
1101
1102 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1103};
1104
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001105class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001106 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001107 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001108
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001109 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
1110 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001111 void Advance() { ++index_; }
1112
1113 private:
1114 const HGraph& graph_;
1115 size_t index_;
1116
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001117 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001118};
1119
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001120class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001121 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001122 explicit HPostOrderIterator(const HGraph& graph)
1123 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001124
1125 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001126 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001127 void Advance() { --index_; }
1128
1129 private:
1130 const HGraph& graph_;
1131 size_t index_;
1132
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001133 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001134};
1135
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001136} // namespace art
1137
1138#endif // ART_COMPILER_OPTIMIZING_NODES_H_