blob: 830d0c7846e7b36e51e8a63dac1aed9cdc4d0d4d [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;
27class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000028class HIntConstant;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000029class HGraphVisitor;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000030class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000031
32static const int kDefaultNumberOfBlocks = 8;
33static const int kDefaultNumberOfSuccessors = 2;
34static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000035static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000036
37// Control-flow graph of a method. Contains a list of basic blocks.
38class HGraph : public ArenaObject {
39 public:
40 explicit HGraph(ArenaAllocator* arena)
41 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000042 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000043 dominator_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010044 maximum_number_of_out_vregs_(0),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000045 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000046
Nicolas Geoffray787c3072014-03-17 10:20:19 +000047 ArenaAllocator* GetArena() const { return arena_; }
48 const GrowableArray<HBasicBlock*>* GetBlocks() const { return &blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000049
Nicolas Geoffray787c3072014-03-17 10:20:19 +000050 HBasicBlock* GetEntryBlock() const { return entry_block_; }
51 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000052
Nicolas Geoffray787c3072014-03-17 10:20:19 +000053 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
54 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000055
Nicolas Geoffray818f2102014-02-18 16:43:35 +000056 void AddBlock(HBasicBlock* block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000057 void BuildDominatorTree();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000058
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000059 int GetNextInstructionId() {
60 return current_instruction_id_++;
61 }
62
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010063 uint16_t GetMaximumNumberOfOutVRegs() const {
64 return maximum_number_of_out_vregs_;
65 }
66
67 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
68 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
69 }
70
Nicolas Geoffray818f2102014-02-18 16:43:35 +000071 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000072 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
73 void VisitBlockForDominatorTree(HBasicBlock* block,
74 HBasicBlock* predecessor,
75 GrowableArray<size_t>* visits);
76 void FindBackEdges(ArenaBitVector* visited) const;
77 void VisitBlockForBackEdges(HBasicBlock* block,
78 ArenaBitVector* visited,
79 ArenaBitVector* visiting) const;
80 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
81
Nicolas Geoffray818f2102014-02-18 16:43:35 +000082 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000083
84 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +000085 GrowableArray<HBasicBlock*> blocks_;
86
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000087 // List of blocks to perform a pre-order dominator tree traversal.
88 GrowableArray<HBasicBlock*> dominator_order_;
89
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000090 HBasicBlock* entry_block_;
91 HBasicBlock* exit_block_;
92
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010093 // The maximum number of arguments passed to a HInvoke in this graph.
94 uint16_t maximum_number_of_out_vregs_;
95
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000096 // The current id to assign to a newly added instruction. See HInstruction.id_.
97 int current_instruction_id_;
98
Nicolas Geoffray818f2102014-02-18 16:43:35 +000099 DISALLOW_COPY_AND_ASSIGN(HGraph);
100};
101
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000102class HLoopInformation : public ArenaObject {
103 public:
104 HLoopInformation(HBasicBlock* header, HGraph* graph)
105 : header_(header),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000106 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges) { }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000107
108 void AddBackEdge(HBasicBlock* back_edge) {
109 back_edges_.Add(back_edge);
110 }
111
112 int NumberOfBackEdges() const {
113 return back_edges_.Size();
114 }
115
116 private:
117 HBasicBlock* header_;
118 GrowableArray<HBasicBlock*> back_edges_;
119
120 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
121};
122
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000123// A block in a method. Contains the list of instructions represented
124// as a double linked list. Each block knows its predecessors and
125// successors.
126class HBasicBlock : public ArenaObject {
127 public:
128 explicit HBasicBlock(HGraph* graph)
129 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000130 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
131 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000132 first_instruction_(nullptr),
133 last_instruction_(nullptr),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000134 loop_information_(nullptr),
135 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000136 block_id_(-1) { }
137
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000138 const GrowableArray<HBasicBlock*>* GetPredecessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000139 return &predecessors_;
140 }
141
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000142 const GrowableArray<HBasicBlock*>* GetSuccessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000143 return &successors_;
144 }
145
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000146 void AddBackEdge(HBasicBlock* back_edge) {
147 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000148 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000149 }
150 loop_information_->AddBackEdge(back_edge);
151 }
152
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000153 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000154
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000155 int GetBlockId() const { return block_id_; }
156 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000157
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000158 HBasicBlock* GetDominator() const { return dominator_; }
159 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000160
161 int NumberOfBackEdges() const {
162 return loop_information_ == nullptr
163 ? 0
164 : loop_information_->NumberOfBackEdges();
165 }
166
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000167 HInstruction* GetFirstInstruction() const { return first_instruction_; }
168 HInstruction* GetLastInstruction() const { return last_instruction_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000169
170 void AddSuccessor(HBasicBlock* block) {
171 successors_.Add(block);
172 block->predecessors_.Add(this);
173 }
174
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000175 void RemovePredecessor(HBasicBlock* block) {
176 predecessors_.Delete(block);
177 }
178
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000179 void AddInstruction(HInstruction* instruction);
180
181 private:
182 HGraph* const graph_;
183 GrowableArray<HBasicBlock*> predecessors_;
184 GrowableArray<HBasicBlock*> successors_;
185 HInstruction* first_instruction_;
186 HInstruction* last_instruction_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000187 HLoopInformation* loop_information_;
188 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000189 int block_id_;
190
191 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
192};
193
194#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000195 M(Add) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000196 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000197 M(Exit) \
198 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000199 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000200 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000201 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000202 M(LoadLocal) \
203 M(Local) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100204 M(NewInstance) \
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100205 M(PushArgument) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000206 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000207 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000208 M(StoreLocal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000209
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000210#define FORWARD_DECLARATION(type) class H##type;
211FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
212#undef FORWARD_DECLARATION
213
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000214#define DECLARE_INSTRUCTION(type) \
215 virtual void Accept(HGraphVisitor* visitor); \
216 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000217 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000218
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000219class HUseListNode : public ArenaObject {
220 public:
221 HUseListNode(HInstruction* instruction, HUseListNode* tail)
222 : instruction_(instruction), tail_(tail) { }
223
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000224 HUseListNode* GetTail() const { return tail_; }
225 HInstruction* GetInstruction() const { return instruction_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000226
227 private:
228 HInstruction* const instruction_;
229 HUseListNode* const tail_;
230
231 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
232};
233
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000234class HInstruction : public ArenaObject {
235 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000236 HInstruction()
237 : previous_(nullptr),
238 next_(nullptr),
239 block_(nullptr),
240 id_(-1),
241 uses_(nullptr),
242 locations_(nullptr) { }
243
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000244 virtual ~HInstruction() { }
245
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000246 HInstruction* GetNext() const { return next_; }
247 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000248
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000249 HBasicBlock* GetBlock() const { return block_; }
250 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000251
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000252 virtual intptr_t InputCount() const = 0;
253 virtual HInstruction* InputAt(intptr_t i) const = 0;
254
255 virtual void Accept(HGraphVisitor* visitor) = 0;
256 virtual const char* DebugName() const = 0;
257
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000258 void AddUse(HInstruction* user) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000259 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode(user, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000260 }
261
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000262 HUseListNode* GetUses() const { return uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000263
264 bool HasUses() const { return uses_ != nullptr; }
265
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000266 int GetId() const { return id_; }
267 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000268
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000269 LocationSummary* GetLocations() const { return locations_; }
270 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000271
272#define INSTRUCTION_TYPE_CHECK(type) \
273 virtual H##type* As##type() { return nullptr; }
274
275 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
276#undef INSTRUCTION_TYPE_CHECK
277
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000278 private:
279 HInstruction* previous_;
280 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000281 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000282
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000283 // An instruction gets an id when it is added to the graph.
284 // It reflects creation order. A negative id means the instruction
285 // has not beed added to the graph.
286 int id_;
287
288 HUseListNode* uses_;
289
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000290 // Set by the code generator.
291 LocationSummary* locations_;
292
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000293 friend class HBasicBlock;
294
295 DISALLOW_COPY_AND_ASSIGN(HInstruction);
296};
297
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000298class HUseIterator : public ValueObject {
299 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000300 explicit HUseIterator(HInstruction* instruction) : current_(instruction->GetUses()) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000301
302 bool Done() const { return current_ == nullptr; }
303
304 void Advance() {
305 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000306 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000307 }
308
309 HInstruction* Current() const {
310 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000311 return current_->GetInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000312 }
313
314 private:
315 HUseListNode* current_;
316
317 friend class HValue;
318};
319
320class HInputIterator : public ValueObject {
321 public:
322 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
323
324 bool Done() const { return index_ == instruction_->InputCount(); }
325 HInstruction* Current() const { return instruction_->InputAt(index_); }
326 void Advance() { index_++; }
327
328 private:
329 HInstruction* instruction_;
330 int index_;
331
332 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
333};
334
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000335class HInstructionIterator : public ValueObject {
336 public:
337 explicit HInstructionIterator(HBasicBlock* block)
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000338 : instruction_(block->GetFirstInstruction()) {
339 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000340 }
341
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000342 bool Done() const { return instruction_ == nullptr; }
343 HInstruction* Current() const { return instruction_; }
344 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000345 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000346 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000347 }
348
349 private:
350 HInstruction* instruction_;
351 HInstruction* next_;
352};
353
354// An embedded container with N elements of type T. Used (with partial
355// specialization for N=0) because embedded arrays cannot have size 0.
356template<typename T, intptr_t N>
357class EmbeddedArray {
358 public:
359 EmbeddedArray() : elements_() { }
360
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000361 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000362
363 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000364 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000365 return elements_[i];
366 }
367
368 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000369 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000370 return elements_[i];
371 }
372
373 const T& At(intptr_t i) const {
374 return (*this)[i];
375 }
376
377 void SetAt(intptr_t i, const T& val) {
378 (*this)[i] = val;
379 }
380
381 private:
382 T elements_[N];
383};
384
385template<typename T>
386class EmbeddedArray<T, 0> {
387 public:
388 intptr_t length() const { return 0; }
389 const T& operator[](intptr_t i) const {
390 LOG(FATAL) << "Unreachable";
391 static T sentinel = 0;
392 return sentinel;
393 }
394 T& operator[](intptr_t i) {
395 LOG(FATAL) << "Unreachable";
396 static T sentinel = 0;
397 return sentinel;
398 }
399};
400
401template<intptr_t N>
402class HTemplateInstruction: public HInstruction {
403 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000404 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000405 virtual ~HTemplateInstruction() { }
406
407 virtual intptr_t InputCount() const { return N; }
408 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
409
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000410 protected:
411 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
412 inputs_[i] = instruction;
413 }
414
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000415 private:
416 EmbeddedArray<HInstruction*, N> inputs_;
417};
418
419// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
420// instruction that branches to the exit block.
421class HReturnVoid : public HTemplateInstruction<0> {
422 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000423 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000424
425 DECLARE_INSTRUCTION(ReturnVoid)
426
427 private:
428 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
429};
430
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000431// Represents dex's RETURN opcodes. A HReturn is a control flow
432// instruction that branches to the exit block.
433class HReturn : public HTemplateInstruction<1> {
434 public:
435 explicit HReturn(HInstruction* value) {
436 SetRawInputAt(0, value);
437 }
438
439 DECLARE_INSTRUCTION(Return)
440
441 private:
442 DISALLOW_COPY_AND_ASSIGN(HReturn);
443};
444
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000445// The exit instruction is the only instruction of the exit block.
446// Instructions aborting the method (HTrow and HReturn) must branch to the
447// exit block.
448class HExit : public HTemplateInstruction<0> {
449 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000450 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000451
452 DECLARE_INSTRUCTION(Exit)
453
454 private:
455 DISALLOW_COPY_AND_ASSIGN(HExit);
456};
457
458// Jumps from one block to another.
459class HGoto : public HTemplateInstruction<0> {
460 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000461 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000462
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000463 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000464 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000465 }
466
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000467 DECLARE_INSTRUCTION(Goto)
468
469 private:
470 DISALLOW_COPY_AND_ASSIGN(HGoto);
471};
472
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000473// Conditional branch. A block ending with an HIf instruction must have
474// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000475class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000476 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000477 explicit HIf(HInstruction* input) {
478 SetRawInputAt(0, input);
479 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000480
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000481 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000482 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000483 }
484
485 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000486 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000487 }
488
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000489 DECLARE_INSTRUCTION(If)
490
491 private:
492 DISALLOW_COPY_AND_ASSIGN(HIf);
493};
494
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000495class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000496 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000497 HBinaryOperation(Primitive::Type result_type,
498 HInstruction* left,
499 HInstruction* right) : result_type_(result_type) {
500 SetRawInputAt(0, left);
501 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000502 }
503
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000504 HInstruction* GetLeft() const { return InputAt(0); }
505 HInstruction* GetRight() const { return InputAt(1); }
506 Primitive::Type GetResultType() const { return result_type_; }
507
508 virtual bool IsCommutative() { return false; }
509
510 private:
511 const Primitive::Type result_type_;
512
513 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
514};
515
516
517// Instruction to check if two inputs are equal to each other.
518class HEqual : public HBinaryOperation {
519 public:
520 HEqual(HInstruction* first, HInstruction* second)
521 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
522
523 virtual bool IsCommutative() { return true; }
524
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000525 DECLARE_INSTRUCTION(Equal)
526
527 private:
528 DISALLOW_COPY_AND_ASSIGN(HEqual);
529};
530
531// A local in the graph. Corresponds to a Dex register.
532class HLocal : public HTemplateInstruction<0> {
533 public:
534 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
535
536 DECLARE_INSTRUCTION(Local)
537
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000538 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000539
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000540 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000541 // The Dex register number.
542 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000543
544 DISALLOW_COPY_AND_ASSIGN(HLocal);
545};
546
547// Load a given local. The local is an input of this instruction.
548class HLoadLocal : public HTemplateInstruction<1> {
549 public:
550 explicit HLoadLocal(HLocal* local) {
551 SetRawInputAt(0, local);
552 }
553
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000554 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
555
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000556 DECLARE_INSTRUCTION(LoadLocal)
557
558 private:
559 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
560};
561
562// Store a value in a given local. This instruction has two inputs: the value
563// and the local.
564class HStoreLocal : public HTemplateInstruction<2> {
565 public:
566 HStoreLocal(HLocal* local, HInstruction* value) {
567 SetRawInputAt(0, local);
568 SetRawInputAt(1, value);
569 }
570
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000571 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
572
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000573 DECLARE_INSTRUCTION(StoreLocal)
574
575 private:
576 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
577};
578
579// Constants of the type int. Those can be from Dex instructions, or
580// synthesized (for example with the if-eqz instruction).
581class HIntConstant : public HTemplateInstruction<0> {
582 public:
583 explicit HIntConstant(int32_t value) : value_(value) { }
584
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000585 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000586
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000587 DECLARE_INSTRUCTION(IntConstant)
588
589 private:
590 const int32_t value_;
591
592 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
593};
594
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000595class HInvoke : public HInstruction {
596 public:
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100597 HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000598 : inputs_(arena, number_of_arguments),
599 dex_pc_(dex_pc) {
600 inputs_.SetSize(number_of_arguments);
601 }
602
603 virtual intptr_t InputCount() const { return inputs_.Size(); }
604 virtual HInstruction* InputAt(intptr_t i) const { return inputs_.Get(i); }
605
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100606 void SetArgumentAt(size_t index, HInstruction* argument) {
607 inputs_.Put(index, argument);
608 }
609
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100610 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000611
612 protected:
613 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100614 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000615
616 private:
617 DISALLOW_COPY_AND_ASSIGN(HInvoke);
618};
619
620class HInvokeStatic : public HInvoke {
621 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100622 HInvokeStatic(ArenaAllocator* arena,
623 uint32_t number_of_arguments,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100624 uint32_t dex_pc,
625 uint32_t index_in_dex_cache)
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100626 : HInvoke(arena, number_of_arguments, dex_pc), index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000627
628 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
629
630 DECLARE_INSTRUCTION(InvokeStatic)
631
632 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100633 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000634
635 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
636};
637
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100638class HNewInstance : public HTemplateInstruction<0> {
639 public:
640 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
641
642 uint32_t GetDexPc() const { return dex_pc_; }
643 uint16_t GetTypeIndex() const { return type_index_; }
644
645 DECLARE_INSTRUCTION(NewInstance)
646
647 private:
648 const uint32_t dex_pc_;
649 const uint16_t type_index_;
650
651 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
652};
653
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100654// HPushArgument nodes are inserted after the evaluation of an argument
655// of a call. Their mere purpose is to ease the code generator's work.
656class HPushArgument : public HTemplateInstruction<1> {
657 public:
658 HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) {
659 SetRawInputAt(0, argument);
660 }
661
662 uint8_t GetArgumentIndex() const { return argument_index_; }
663
664 DECLARE_INSTRUCTION(PushArgument)
665
666 private:
667 const uint8_t argument_index_;
668
669 DISALLOW_COPY_AND_ASSIGN(HPushArgument);
670};
671
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000672class HAdd : public HBinaryOperation {
673 public:
674 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
675 : HBinaryOperation(result_type, left, right) {}
676
677 virtual bool IsCommutative() { return true; }
678
679 DECLARE_INSTRUCTION(Add);
680
681 private:
682 DISALLOW_COPY_AND_ASSIGN(HAdd);
683};
684
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000685class HGraphVisitor : public ValueObject {
686 public:
687 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
688 virtual ~HGraphVisitor() { }
689
690 virtual void VisitInstruction(HInstruction* instruction) { }
691 virtual void VisitBasicBlock(HBasicBlock* block);
692
693 void VisitInsertionOrder();
694
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000695 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000696
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000697 // Visit functions for instruction classes.
698#define DECLARE_VISIT_INSTRUCTION(name) \
699 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
700
701 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
702
703#undef DECLARE_VISIT_INSTRUCTION
704
705 private:
706 HGraph* graph_;
707
708 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
709};
710
711} // namespace art
712
713#endif // ART_COMPILER_OPTIMIZING_NODES_H_