blob: d1f672f4b0dfe325e6c9491c61c88df49664fb2e [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 Geoffrayf583e592014-04-07 13:20:42 +010045 number_of_vregs_(0),
46 number_of_in_vregs_(0),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000047 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000048
Nicolas Geoffray787c3072014-03-17 10:20:19 +000049 ArenaAllocator* GetArena() const { return arena_; }
50 const GrowableArray<HBasicBlock*>* GetBlocks() const { return &blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000051
Nicolas Geoffray787c3072014-03-17 10:20:19 +000052 HBasicBlock* GetEntryBlock() const { return entry_block_; }
53 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000054
Nicolas Geoffray787c3072014-03-17 10:20:19 +000055 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
56 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000057
Nicolas Geoffray818f2102014-02-18 16:43:35 +000058 void AddBlock(HBasicBlock* block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000059 void BuildDominatorTree();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000060
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000061 int GetNextInstructionId() {
62 return current_instruction_id_++;
63 }
64
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010065 uint16_t GetMaximumNumberOfOutVRegs() const {
66 return maximum_number_of_out_vregs_;
67 }
68
69 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
70 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
71 }
72
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010073 void SetNumberOfVRegs(uint16_t number_of_vregs) {
74 number_of_vregs_ = number_of_vregs;
75 }
76
77 uint16_t GetNumberOfVRegs() const {
78 return number_of_vregs_;
79 }
80
81 void SetNumberOfInVRegs(uint16_t value) {
82 number_of_in_vregs_ = value;
83 }
84
85 uint16_t GetNumberOfInVRegs() const {
86 return number_of_in_vregs_;
87 }
88
89
Nicolas Geoffray818f2102014-02-18 16:43:35 +000090 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000091 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
92 void VisitBlockForDominatorTree(HBasicBlock* block,
93 HBasicBlock* predecessor,
94 GrowableArray<size_t>* visits);
95 void FindBackEdges(ArenaBitVector* visited) const;
96 void VisitBlockForBackEdges(HBasicBlock* block,
97 ArenaBitVector* visited,
98 ArenaBitVector* visiting) const;
99 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
100
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000101 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000102
103 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000104 GrowableArray<HBasicBlock*> blocks_;
105
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000106 // List of blocks to perform a pre-order dominator tree traversal.
107 GrowableArray<HBasicBlock*> dominator_order_;
108
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000109 HBasicBlock* entry_block_;
110 HBasicBlock* exit_block_;
111
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100112 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100113 uint16_t maximum_number_of_out_vregs_;
114
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100115 // The number of virtual registers in this method. Contains the parameters.
116 uint16_t number_of_vregs_;
117
118 // The number of virtual registers used by parameters of this method.
119 uint16_t number_of_in_vregs_;
120
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000121 // The current id to assign to a newly added instruction. See HInstruction.id_.
122 int current_instruction_id_;
123
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000124 DISALLOW_COPY_AND_ASSIGN(HGraph);
125};
126
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000127class HLoopInformation : public ArenaObject {
128 public:
129 HLoopInformation(HBasicBlock* header, HGraph* graph)
130 : header_(header),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000131 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges) { }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000132
133 void AddBackEdge(HBasicBlock* back_edge) {
134 back_edges_.Add(back_edge);
135 }
136
137 int NumberOfBackEdges() const {
138 return back_edges_.Size();
139 }
140
141 private:
142 HBasicBlock* header_;
143 GrowableArray<HBasicBlock*> back_edges_;
144
145 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
146};
147
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000148// A block in a method. Contains the list of instructions represented
149// as a double linked list. Each block knows its predecessors and
150// successors.
151class HBasicBlock : public ArenaObject {
152 public:
153 explicit HBasicBlock(HGraph* graph)
154 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000155 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
156 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000157 first_instruction_(nullptr),
158 last_instruction_(nullptr),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000159 loop_information_(nullptr),
160 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000161 block_id_(-1) { }
162
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000163 const GrowableArray<HBasicBlock*>* GetPredecessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000164 return &predecessors_;
165 }
166
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000167 const GrowableArray<HBasicBlock*>* GetSuccessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000168 return &successors_;
169 }
170
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000171 void AddBackEdge(HBasicBlock* back_edge) {
172 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000173 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000174 }
175 loop_information_->AddBackEdge(back_edge);
176 }
177
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000178 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000179
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000180 int GetBlockId() const { return block_id_; }
181 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000182
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000183 HBasicBlock* GetDominator() const { return dominator_; }
184 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000185
186 int NumberOfBackEdges() const {
187 return loop_information_ == nullptr
188 ? 0
189 : loop_information_->NumberOfBackEdges();
190 }
191
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000192 HInstruction* GetFirstInstruction() const { return first_instruction_; }
193 HInstruction* GetLastInstruction() const { return last_instruction_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000194
195 void AddSuccessor(HBasicBlock* block) {
196 successors_.Add(block);
197 block->predecessors_.Add(this);
198 }
199
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000200 void RemovePredecessor(HBasicBlock* block) {
201 predecessors_.Delete(block);
202 }
203
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000204 void AddInstruction(HInstruction* instruction);
205
206 private:
207 HGraph* const graph_;
208 GrowableArray<HBasicBlock*> predecessors_;
209 GrowableArray<HBasicBlock*> successors_;
210 HInstruction* first_instruction_;
211 HInstruction* last_instruction_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000212 HLoopInformation* loop_information_;
213 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000214 int block_id_;
215
216 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
217};
218
219#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000220 M(Add) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000221 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000222 M(Exit) \
223 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000224 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000225 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000226 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000227 M(LoadLocal) \
228 M(Local) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100229 M(NewInstance) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100230 M(ParameterValue) \
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100231 M(PushArgument) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000232 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000233 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000234 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100235 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000236
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000237#define FORWARD_DECLARATION(type) class H##type;
238FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
239#undef FORWARD_DECLARATION
240
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000241#define DECLARE_INSTRUCTION(type) \
242 virtual void Accept(HGraphVisitor* visitor); \
243 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000244 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000245
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000246class HUseListNode : public ArenaObject {
247 public:
248 HUseListNode(HInstruction* instruction, HUseListNode* tail)
249 : instruction_(instruction), tail_(tail) { }
250
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000251 HUseListNode* GetTail() const { return tail_; }
252 HInstruction* GetInstruction() const { return instruction_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000253
254 private:
255 HInstruction* const instruction_;
256 HUseListNode* const tail_;
257
258 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
259};
260
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000261class HInstruction : public ArenaObject {
262 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000263 HInstruction()
264 : previous_(nullptr),
265 next_(nullptr),
266 block_(nullptr),
267 id_(-1),
268 uses_(nullptr),
269 locations_(nullptr) { }
270
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000271 virtual ~HInstruction() { }
272
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000273 HInstruction* GetNext() const { return next_; }
274 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000275
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000276 HBasicBlock* GetBlock() const { return block_; }
277 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000278
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000279 virtual intptr_t InputCount() const = 0;
280 virtual HInstruction* InputAt(intptr_t i) const = 0;
281
282 virtual void Accept(HGraphVisitor* visitor) = 0;
283 virtual const char* DebugName() const = 0;
284
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000285 void AddUse(HInstruction* user) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000286 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode(user, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000287 }
288
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000289 HUseListNode* GetUses() const { return uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000290
291 bool HasUses() const { return uses_ != nullptr; }
292
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000293 int GetId() const { return id_; }
294 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000295
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000296 LocationSummary* GetLocations() const { return locations_; }
297 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000298
299#define INSTRUCTION_TYPE_CHECK(type) \
300 virtual H##type* As##type() { return nullptr; }
301
302 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
303#undef INSTRUCTION_TYPE_CHECK
304
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000305 private:
306 HInstruction* previous_;
307 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000308 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000309
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000310 // An instruction gets an id when it is added to the graph.
311 // It reflects creation order. A negative id means the instruction
312 // has not beed added to the graph.
313 int id_;
314
315 HUseListNode* uses_;
316
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000317 // Set by the code generator.
318 LocationSummary* locations_;
319
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000320 friend class HBasicBlock;
321
322 DISALLOW_COPY_AND_ASSIGN(HInstruction);
323};
324
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000325class HUseIterator : public ValueObject {
326 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000327 explicit HUseIterator(HInstruction* instruction) : current_(instruction->GetUses()) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000328
329 bool Done() const { return current_ == nullptr; }
330
331 void Advance() {
332 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000333 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000334 }
335
336 HInstruction* Current() const {
337 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000338 return current_->GetInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000339 }
340
341 private:
342 HUseListNode* current_;
343
344 friend class HValue;
345};
346
347class HInputIterator : public ValueObject {
348 public:
349 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
350
351 bool Done() const { return index_ == instruction_->InputCount(); }
352 HInstruction* Current() const { return instruction_->InputAt(index_); }
353 void Advance() { index_++; }
354
355 private:
356 HInstruction* instruction_;
357 int index_;
358
359 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
360};
361
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000362class HInstructionIterator : public ValueObject {
363 public:
364 explicit HInstructionIterator(HBasicBlock* block)
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000365 : instruction_(block->GetFirstInstruction()) {
366 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000367 }
368
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000369 bool Done() const { return instruction_ == nullptr; }
370 HInstruction* Current() const { return instruction_; }
371 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000372 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000373 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000374 }
375
376 private:
377 HInstruction* instruction_;
378 HInstruction* next_;
379};
380
381// An embedded container with N elements of type T. Used (with partial
382// specialization for N=0) because embedded arrays cannot have size 0.
383template<typename T, intptr_t N>
384class EmbeddedArray {
385 public:
386 EmbeddedArray() : elements_() { }
387
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000388 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000389
390 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000391 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000392 return elements_[i];
393 }
394
395 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000396 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000397 return elements_[i];
398 }
399
400 const T& At(intptr_t i) const {
401 return (*this)[i];
402 }
403
404 void SetAt(intptr_t i, const T& val) {
405 (*this)[i] = val;
406 }
407
408 private:
409 T elements_[N];
410};
411
412template<typename T>
413class EmbeddedArray<T, 0> {
414 public:
415 intptr_t length() const { return 0; }
416 const T& operator[](intptr_t i) const {
417 LOG(FATAL) << "Unreachable";
418 static T sentinel = 0;
419 return sentinel;
420 }
421 T& operator[](intptr_t i) {
422 LOG(FATAL) << "Unreachable";
423 static T sentinel = 0;
424 return sentinel;
425 }
426};
427
428template<intptr_t N>
429class HTemplateInstruction: public HInstruction {
430 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000431 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000432 virtual ~HTemplateInstruction() { }
433
434 virtual intptr_t InputCount() const { return N; }
435 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
436
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000437 protected:
438 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
439 inputs_[i] = instruction;
440 }
441
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000442 private:
443 EmbeddedArray<HInstruction*, N> inputs_;
444};
445
446// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
447// instruction that branches to the exit block.
448class HReturnVoid : public HTemplateInstruction<0> {
449 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000450 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000451
452 DECLARE_INSTRUCTION(ReturnVoid)
453
454 private:
455 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
456};
457
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000458// Represents dex's RETURN opcodes. A HReturn is a control flow
459// instruction that branches to the exit block.
460class HReturn : public HTemplateInstruction<1> {
461 public:
462 explicit HReturn(HInstruction* value) {
463 SetRawInputAt(0, value);
464 }
465
466 DECLARE_INSTRUCTION(Return)
467
468 private:
469 DISALLOW_COPY_AND_ASSIGN(HReturn);
470};
471
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000472// The exit instruction is the only instruction of the exit block.
473// Instructions aborting the method (HTrow and HReturn) must branch to the
474// exit block.
475class HExit : public HTemplateInstruction<0> {
476 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000477 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000478
479 DECLARE_INSTRUCTION(Exit)
480
481 private:
482 DISALLOW_COPY_AND_ASSIGN(HExit);
483};
484
485// Jumps from one block to another.
486class HGoto : public HTemplateInstruction<0> {
487 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000488 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000489
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000490 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000491 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000492 }
493
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000494 DECLARE_INSTRUCTION(Goto)
495
496 private:
497 DISALLOW_COPY_AND_ASSIGN(HGoto);
498};
499
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000500// Conditional branch. A block ending with an HIf instruction must have
501// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000502class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000503 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000504 explicit HIf(HInstruction* input) {
505 SetRawInputAt(0, input);
506 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000507
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000508 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000509 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000510 }
511
512 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000513 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000514 }
515
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000516 DECLARE_INSTRUCTION(If)
517
518 private:
519 DISALLOW_COPY_AND_ASSIGN(HIf);
520};
521
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000522class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000523 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000524 HBinaryOperation(Primitive::Type result_type,
525 HInstruction* left,
526 HInstruction* right) : result_type_(result_type) {
527 SetRawInputAt(0, left);
528 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000529 }
530
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000531 HInstruction* GetLeft() const { return InputAt(0); }
532 HInstruction* GetRight() const { return InputAt(1); }
533 Primitive::Type GetResultType() const { return result_type_; }
534
535 virtual bool IsCommutative() { return false; }
536
537 private:
538 const Primitive::Type result_type_;
539
540 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
541};
542
543
544// Instruction to check if two inputs are equal to each other.
545class HEqual : public HBinaryOperation {
546 public:
547 HEqual(HInstruction* first, HInstruction* second)
548 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
549
550 virtual bool IsCommutative() { return true; }
551
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000552 DECLARE_INSTRUCTION(Equal)
553
554 private:
555 DISALLOW_COPY_AND_ASSIGN(HEqual);
556};
557
558// A local in the graph. Corresponds to a Dex register.
559class HLocal : public HTemplateInstruction<0> {
560 public:
561 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
562
563 DECLARE_INSTRUCTION(Local)
564
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000565 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000566
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000567 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000568 // The Dex register number.
569 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000570
571 DISALLOW_COPY_AND_ASSIGN(HLocal);
572};
573
574// Load a given local. The local is an input of this instruction.
575class HLoadLocal : public HTemplateInstruction<1> {
576 public:
577 explicit HLoadLocal(HLocal* local) {
578 SetRawInputAt(0, local);
579 }
580
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000581 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
582
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000583 DECLARE_INSTRUCTION(LoadLocal)
584
585 private:
586 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
587};
588
589// Store a value in a given local. This instruction has two inputs: the value
590// and the local.
591class HStoreLocal : public HTemplateInstruction<2> {
592 public:
593 HStoreLocal(HLocal* local, HInstruction* value) {
594 SetRawInputAt(0, local);
595 SetRawInputAt(1, value);
596 }
597
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000598 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
599
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000600 DECLARE_INSTRUCTION(StoreLocal)
601
602 private:
603 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
604};
605
606// Constants of the type int. Those can be from Dex instructions, or
607// synthesized (for example with the if-eqz instruction).
608class HIntConstant : public HTemplateInstruction<0> {
609 public:
610 explicit HIntConstant(int32_t value) : value_(value) { }
611
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000612 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000613
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000614 DECLARE_INSTRUCTION(IntConstant)
615
616 private:
617 const int32_t value_;
618
619 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
620};
621
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000622class HInvoke : public HInstruction {
623 public:
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100624 HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000625 : inputs_(arena, number_of_arguments),
626 dex_pc_(dex_pc) {
627 inputs_.SetSize(number_of_arguments);
628 }
629
630 virtual intptr_t InputCount() const { return inputs_.Size(); }
631 virtual HInstruction* InputAt(intptr_t i) const { return inputs_.Get(i); }
632
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100633 void SetArgumentAt(size_t index, HInstruction* argument) {
634 inputs_.Put(index, argument);
635 }
636
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100637 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000638
639 protected:
640 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100641 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000642
643 private:
644 DISALLOW_COPY_AND_ASSIGN(HInvoke);
645};
646
647class HInvokeStatic : public HInvoke {
648 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100649 HInvokeStatic(ArenaAllocator* arena,
650 uint32_t number_of_arguments,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100651 uint32_t dex_pc,
652 uint32_t index_in_dex_cache)
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100653 : HInvoke(arena, number_of_arguments, dex_pc), index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000654
655 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
656
657 DECLARE_INSTRUCTION(InvokeStatic)
658
659 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100660 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000661
662 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
663};
664
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100665class HNewInstance : public HTemplateInstruction<0> {
666 public:
667 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
668
669 uint32_t GetDexPc() const { return dex_pc_; }
670 uint16_t GetTypeIndex() const { return type_index_; }
671
672 DECLARE_INSTRUCTION(NewInstance)
673
674 private:
675 const uint32_t dex_pc_;
676 const uint16_t type_index_;
677
678 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
679};
680
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100681// HPushArgument nodes are inserted after the evaluation of an argument
682// of a call. Their mere purpose is to ease the code generator's work.
683class HPushArgument : public HTemplateInstruction<1> {
684 public:
685 HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) {
686 SetRawInputAt(0, argument);
687 }
688
689 uint8_t GetArgumentIndex() const { return argument_index_; }
690
691 DECLARE_INSTRUCTION(PushArgument)
692
693 private:
694 const uint8_t argument_index_;
695
696 DISALLOW_COPY_AND_ASSIGN(HPushArgument);
697};
698
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000699class HAdd : public HBinaryOperation {
700 public:
701 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
702 : HBinaryOperation(result_type, left, right) {}
703
704 virtual bool IsCommutative() { return true; }
705
706 DECLARE_INSTRUCTION(Add);
707
708 private:
709 DISALLOW_COPY_AND_ASSIGN(HAdd);
710};
711
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100712class HSub : public HBinaryOperation {
713 public:
714 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
715 : HBinaryOperation(result_type, left, right) {}
716
717 virtual bool IsCommutative() { return false; }
718
719 DECLARE_INSTRUCTION(Sub);
720
721 private:
722 DISALLOW_COPY_AND_ASSIGN(HSub);
723};
724
725// The value of a parameter in this method. Its location depends on
726// the calling convention.
727class HParameterValue : public HTemplateInstruction<0> {
728 public:
729 explicit HParameterValue(uint8_t index) : index_(index) {}
730
731 uint8_t GetIndex() const { return index_; }
732
733 DECLARE_INSTRUCTION(ParameterValue);
734
735 private:
736 // The index of this parameter in the parameters list. Must be less
737 // than HGraph::number_of_in_vregs_;
738 const uint8_t index_;
739
740 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
741};
742
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000743class HGraphVisitor : public ValueObject {
744 public:
745 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
746 virtual ~HGraphVisitor() { }
747
748 virtual void VisitInstruction(HInstruction* instruction) { }
749 virtual void VisitBasicBlock(HBasicBlock* block);
750
751 void VisitInsertionOrder();
752
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000753 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000754
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000755 // Visit functions for instruction classes.
756#define DECLARE_VISIT_INSTRUCTION(name) \
757 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
758
759 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
760
761#undef DECLARE_VISIT_INSTRUCTION
762
763 private:
764 HGraph* graph_;
765
766 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
767};
768
769} // namespace art
770
771#endif // ART_COMPILER_OPTIMIZING_NODES_H_