blob: adea0baa2d9351c4cde39a42edcd1b37eff3f25b [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 Geoffrayb55f8352014-04-07 15:26:35 +0100230 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100231 M(ParameterValue) \
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100232 M(PushArgument) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000233 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000234 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000235 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100236 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000237
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000238#define FORWARD_DECLARATION(type) class H##type;
239FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
240#undef FORWARD_DECLARATION
241
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000242#define DECLARE_INSTRUCTION(type) \
243 virtual void Accept(HGraphVisitor* visitor); \
244 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000245 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000246
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000247class HUseListNode : public ArenaObject {
248 public:
249 HUseListNode(HInstruction* instruction, HUseListNode* tail)
250 : instruction_(instruction), tail_(tail) { }
251
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000252 HUseListNode* GetTail() const { return tail_; }
253 HInstruction* GetInstruction() const { return instruction_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000254
255 private:
256 HInstruction* const instruction_;
257 HUseListNode* const tail_;
258
259 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
260};
261
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000262class HInstruction : public ArenaObject {
263 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000264 HInstruction()
265 : previous_(nullptr),
266 next_(nullptr),
267 block_(nullptr),
268 id_(-1),
269 uses_(nullptr),
270 locations_(nullptr) { }
271
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000272 virtual ~HInstruction() { }
273
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000274 HInstruction* GetNext() const { return next_; }
275 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000276
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000277 HBasicBlock* GetBlock() const { return block_; }
278 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000279
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000280 virtual intptr_t InputCount() const = 0;
281 virtual HInstruction* InputAt(intptr_t i) const = 0;
282
283 virtual void Accept(HGraphVisitor* visitor) = 0;
284 virtual const char* DebugName() const = 0;
285
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000286 void AddUse(HInstruction* user) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000287 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode(user, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000288 }
289
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000290 HUseListNode* GetUses() const { return uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000291
292 bool HasUses() const { return uses_ != nullptr; }
293
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000294 int GetId() const { return id_; }
295 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000296
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000297 LocationSummary* GetLocations() const { return locations_; }
298 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000299
300#define INSTRUCTION_TYPE_CHECK(type) \
301 virtual H##type* As##type() { return nullptr; }
302
303 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
304#undef INSTRUCTION_TYPE_CHECK
305
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000306 private:
307 HInstruction* previous_;
308 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000309 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000310
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000311 // An instruction gets an id when it is added to the graph.
312 // It reflects creation order. A negative id means the instruction
313 // has not beed added to the graph.
314 int id_;
315
316 HUseListNode* uses_;
317
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000318 // Set by the code generator.
319 LocationSummary* locations_;
320
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000321 friend class HBasicBlock;
322
323 DISALLOW_COPY_AND_ASSIGN(HInstruction);
324};
325
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000326class HUseIterator : public ValueObject {
327 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000328 explicit HUseIterator(HInstruction* instruction) : current_(instruction->GetUses()) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000329
330 bool Done() const { return current_ == nullptr; }
331
332 void Advance() {
333 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000334 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000335 }
336
337 HInstruction* Current() const {
338 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000339 return current_->GetInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000340 }
341
342 private:
343 HUseListNode* current_;
344
345 friend class HValue;
346};
347
348class HInputIterator : public ValueObject {
349 public:
350 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
351
352 bool Done() const { return index_ == instruction_->InputCount(); }
353 HInstruction* Current() const { return instruction_->InputAt(index_); }
354 void Advance() { index_++; }
355
356 private:
357 HInstruction* instruction_;
358 int index_;
359
360 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
361};
362
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000363class HInstructionIterator : public ValueObject {
364 public:
365 explicit HInstructionIterator(HBasicBlock* block)
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000366 : instruction_(block->GetFirstInstruction()) {
367 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000368 }
369
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000370 bool Done() const { return instruction_ == nullptr; }
371 HInstruction* Current() const { return instruction_; }
372 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000373 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000374 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000375 }
376
377 private:
378 HInstruction* instruction_;
379 HInstruction* next_;
380};
381
382// An embedded container with N elements of type T. Used (with partial
383// specialization for N=0) because embedded arrays cannot have size 0.
384template<typename T, intptr_t N>
385class EmbeddedArray {
386 public:
387 EmbeddedArray() : elements_() { }
388
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000389 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000390
391 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000392 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000393 return elements_[i];
394 }
395
396 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000397 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000398 return elements_[i];
399 }
400
401 const T& At(intptr_t i) const {
402 return (*this)[i];
403 }
404
405 void SetAt(intptr_t i, const T& val) {
406 (*this)[i] = val;
407 }
408
409 private:
410 T elements_[N];
411};
412
413template<typename T>
414class EmbeddedArray<T, 0> {
415 public:
416 intptr_t length() const { return 0; }
417 const T& operator[](intptr_t i) const {
418 LOG(FATAL) << "Unreachable";
419 static T sentinel = 0;
420 return sentinel;
421 }
422 T& operator[](intptr_t i) {
423 LOG(FATAL) << "Unreachable";
424 static T sentinel = 0;
425 return sentinel;
426 }
427};
428
429template<intptr_t N>
430class HTemplateInstruction: public HInstruction {
431 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000432 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000433 virtual ~HTemplateInstruction() { }
434
435 virtual intptr_t InputCount() const { return N; }
436 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
437
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000438 protected:
439 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
440 inputs_[i] = instruction;
441 }
442
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000443 private:
444 EmbeddedArray<HInstruction*, N> inputs_;
445};
446
447// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
448// instruction that branches to the exit block.
449class HReturnVoid : public HTemplateInstruction<0> {
450 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000451 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000452
453 DECLARE_INSTRUCTION(ReturnVoid)
454
455 private:
456 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
457};
458
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000459// Represents dex's RETURN opcodes. A HReturn is a control flow
460// instruction that branches to the exit block.
461class HReturn : public HTemplateInstruction<1> {
462 public:
463 explicit HReturn(HInstruction* value) {
464 SetRawInputAt(0, value);
465 }
466
467 DECLARE_INSTRUCTION(Return)
468
469 private:
470 DISALLOW_COPY_AND_ASSIGN(HReturn);
471};
472
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000473// The exit instruction is the only instruction of the exit block.
474// Instructions aborting the method (HTrow and HReturn) must branch to the
475// exit block.
476class HExit : public HTemplateInstruction<0> {
477 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000478 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000479
480 DECLARE_INSTRUCTION(Exit)
481
482 private:
483 DISALLOW_COPY_AND_ASSIGN(HExit);
484};
485
486// Jumps from one block to another.
487class HGoto : public HTemplateInstruction<0> {
488 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000489 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000490
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000491 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000492 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000493 }
494
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000495 DECLARE_INSTRUCTION(Goto)
496
497 private:
498 DISALLOW_COPY_AND_ASSIGN(HGoto);
499};
500
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000501// Conditional branch. A block ending with an HIf instruction must have
502// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000503class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000504 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000505 explicit HIf(HInstruction* input) {
506 SetRawInputAt(0, input);
507 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000508
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000509 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000510 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000511 }
512
513 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000514 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000515 }
516
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000517 DECLARE_INSTRUCTION(If)
518
519 private:
520 DISALLOW_COPY_AND_ASSIGN(HIf);
521};
522
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000523class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000524 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000525 HBinaryOperation(Primitive::Type result_type,
526 HInstruction* left,
527 HInstruction* right) : result_type_(result_type) {
528 SetRawInputAt(0, left);
529 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000530 }
531
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000532 HInstruction* GetLeft() const { return InputAt(0); }
533 HInstruction* GetRight() const { return InputAt(1); }
534 Primitive::Type GetResultType() const { return result_type_; }
535
536 virtual bool IsCommutative() { return false; }
537
538 private:
539 const Primitive::Type result_type_;
540
541 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
542};
543
544
545// Instruction to check if two inputs are equal to each other.
546class HEqual : public HBinaryOperation {
547 public:
548 HEqual(HInstruction* first, HInstruction* second)
549 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
550
551 virtual bool IsCommutative() { return true; }
552
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000553 DECLARE_INSTRUCTION(Equal)
554
555 private:
556 DISALLOW_COPY_AND_ASSIGN(HEqual);
557};
558
559// A local in the graph. Corresponds to a Dex register.
560class HLocal : public HTemplateInstruction<0> {
561 public:
562 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
563
564 DECLARE_INSTRUCTION(Local)
565
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000566 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000567
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000568 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000569 // The Dex register number.
570 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000571
572 DISALLOW_COPY_AND_ASSIGN(HLocal);
573};
574
575// Load a given local. The local is an input of this instruction.
576class HLoadLocal : public HTemplateInstruction<1> {
577 public:
578 explicit HLoadLocal(HLocal* local) {
579 SetRawInputAt(0, local);
580 }
581
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000582 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
583
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000584 DECLARE_INSTRUCTION(LoadLocal)
585
586 private:
587 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
588};
589
590// Store a value in a given local. This instruction has two inputs: the value
591// and the local.
592class HStoreLocal : public HTemplateInstruction<2> {
593 public:
594 HStoreLocal(HLocal* local, HInstruction* value) {
595 SetRawInputAt(0, local);
596 SetRawInputAt(1, value);
597 }
598
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000599 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
600
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000601 DECLARE_INSTRUCTION(StoreLocal)
602
603 private:
604 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
605};
606
607// Constants of the type int. Those can be from Dex instructions, or
608// synthesized (for example with the if-eqz instruction).
609class HIntConstant : public HTemplateInstruction<0> {
610 public:
611 explicit HIntConstant(int32_t value) : value_(value) { }
612
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000613 int32_t GetValue() const { return value_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000614
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000615 DECLARE_INSTRUCTION(IntConstant)
616
617 private:
618 const int32_t value_;
619
620 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
621};
622
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000623class HInvoke : public HInstruction {
624 public:
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100625 HInvoke(ArenaAllocator* arena, uint32_t number_of_arguments, uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000626 : inputs_(arena, number_of_arguments),
627 dex_pc_(dex_pc) {
628 inputs_.SetSize(number_of_arguments);
629 }
630
631 virtual intptr_t InputCount() const { return inputs_.Size(); }
632 virtual HInstruction* InputAt(intptr_t i) const { return inputs_.Get(i); }
633
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100634 void SetArgumentAt(size_t index, HInstruction* argument) {
635 inputs_.Put(index, argument);
636 }
637
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100638 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000639
640 protected:
641 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100642 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000643
644 private:
645 DISALLOW_COPY_AND_ASSIGN(HInvoke);
646};
647
648class HInvokeStatic : public HInvoke {
649 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100650 HInvokeStatic(ArenaAllocator* arena,
651 uint32_t number_of_arguments,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100652 uint32_t dex_pc,
653 uint32_t index_in_dex_cache)
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100654 : HInvoke(arena, number_of_arguments, dex_pc), index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000655
656 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
657
658 DECLARE_INSTRUCTION(InvokeStatic)
659
660 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100661 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000662
663 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
664};
665
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100666class HNewInstance : public HTemplateInstruction<0> {
667 public:
668 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
669
670 uint32_t GetDexPc() const { return dex_pc_; }
671 uint16_t GetTypeIndex() const { return type_index_; }
672
673 DECLARE_INSTRUCTION(NewInstance)
674
675 private:
676 const uint32_t dex_pc_;
677 const uint16_t type_index_;
678
679 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
680};
681
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100682// HPushArgument nodes are inserted after the evaluation of an argument
683// of a call. Their mere purpose is to ease the code generator's work.
684class HPushArgument : public HTemplateInstruction<1> {
685 public:
686 HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) {
687 SetRawInputAt(0, argument);
688 }
689
690 uint8_t GetArgumentIndex() const { return argument_index_; }
691
692 DECLARE_INSTRUCTION(PushArgument)
693
694 private:
695 const uint8_t argument_index_;
696
697 DISALLOW_COPY_AND_ASSIGN(HPushArgument);
698};
699
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000700class HAdd : public HBinaryOperation {
701 public:
702 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
703 : HBinaryOperation(result_type, left, right) {}
704
705 virtual bool IsCommutative() { return true; }
706
707 DECLARE_INSTRUCTION(Add);
708
709 private:
710 DISALLOW_COPY_AND_ASSIGN(HAdd);
711};
712
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100713class HSub : public HBinaryOperation {
714 public:
715 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
716 : HBinaryOperation(result_type, left, right) {}
717
718 virtual bool IsCommutative() { return false; }
719
720 DECLARE_INSTRUCTION(Sub);
721
722 private:
723 DISALLOW_COPY_AND_ASSIGN(HSub);
724};
725
726// The value of a parameter in this method. Its location depends on
727// the calling convention.
728class HParameterValue : public HTemplateInstruction<0> {
729 public:
730 explicit HParameterValue(uint8_t index) : index_(index) {}
731
732 uint8_t GetIndex() const { return index_; }
733
734 DECLARE_INSTRUCTION(ParameterValue);
735
736 private:
737 // The index of this parameter in the parameters list. Must be less
738 // than HGraph::number_of_in_vregs_;
739 const uint8_t index_;
740
741 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
742};
743
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100744class HNot : public HTemplateInstruction<1> {
745 public:
746 explicit HNot(HInstruction* input) {
747 SetRawInputAt(0, input);
748 }
749
750 DECLARE_INSTRUCTION(Not);
751
752 private:
753 DISALLOW_COPY_AND_ASSIGN(HNot);
754};
755
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000756class HGraphVisitor : public ValueObject {
757 public:
758 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
759 virtual ~HGraphVisitor() { }
760
761 virtual void VisitInstruction(HInstruction* instruction) { }
762 virtual void VisitBasicBlock(HBasicBlock* block);
763
764 void VisitInsertionOrder();
765
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000766 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000767
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000768 // Visit functions for instruction classes.
769#define DECLARE_VISIT_INSTRUCTION(name) \
770 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
771
772 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
773
774#undef DECLARE_VISIT_INSTRUCTION
775
776 private:
777 HGraph* graph_;
778
779 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
780};
781
782} // namespace art
783
784#endif // ART_COMPILER_OPTIMIZING_NODES_H_