blob: d7e74f8262a8c2a9fd694f5248b470e6bf50810b [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 Geoffray01bc96d2014-04-11 17:43:50 +0100229 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100230 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100231 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100232 M(ParameterValue) \
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100233 M(PushArgument) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000234 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000235 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000236 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100237 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000238
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000239#define FORWARD_DECLARATION(type) class H##type;
240FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
241#undef FORWARD_DECLARATION
242
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000243#define DECLARE_INSTRUCTION(type) \
244 virtual void Accept(HGraphVisitor* visitor); \
245 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000246 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000247
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000248class HUseListNode : public ArenaObject {
249 public:
250 HUseListNode(HInstruction* instruction, HUseListNode* tail)
251 : instruction_(instruction), tail_(tail) { }
252
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000253 HUseListNode* GetTail() const { return tail_; }
254 HInstruction* GetInstruction() const { return instruction_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000255
256 private:
257 HInstruction* const instruction_;
258 HUseListNode* const tail_;
259
260 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
261};
262
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000263class HInstruction : public ArenaObject {
264 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000265 HInstruction()
266 : previous_(nullptr),
267 next_(nullptr),
268 block_(nullptr),
269 id_(-1),
270 uses_(nullptr),
271 locations_(nullptr) { }
272
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000273 virtual ~HInstruction() { }
274
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000275 HInstruction* GetNext() const { return next_; }
276 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000277
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000278 HBasicBlock* GetBlock() const { return block_; }
279 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000280
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000281 virtual intptr_t InputCount() const = 0;
282 virtual HInstruction* InputAt(intptr_t i) const = 0;
283
284 virtual void Accept(HGraphVisitor* visitor) = 0;
285 virtual const char* DebugName() const = 0;
286
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100287 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
288
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000289 void AddUse(HInstruction* user) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000290 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode(user, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000291 }
292
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000293 HUseListNode* GetUses() const { return uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000294
295 bool HasUses() const { return uses_ != nullptr; }
296
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000297 int GetId() const { return id_; }
298 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000299
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000300 LocationSummary* GetLocations() const { return locations_; }
301 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000302
303#define INSTRUCTION_TYPE_CHECK(type) \
304 virtual H##type* As##type() { return nullptr; }
305
306 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
307#undef INSTRUCTION_TYPE_CHECK
308
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000309 private:
310 HInstruction* previous_;
311 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000312 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000313
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000314 // An instruction gets an id when it is added to the graph.
315 // It reflects creation order. A negative id means the instruction
316 // has not beed added to the graph.
317 int id_;
318
319 HUseListNode* uses_;
320
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000321 // Set by the code generator.
322 LocationSummary* locations_;
323
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000324 friend class HBasicBlock;
325
326 DISALLOW_COPY_AND_ASSIGN(HInstruction);
327};
328
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000329class HUseIterator : public ValueObject {
330 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000331 explicit HUseIterator(HInstruction* instruction) : current_(instruction->GetUses()) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000332
333 bool Done() const { return current_ == nullptr; }
334
335 void Advance() {
336 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000337 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000338 }
339
340 HInstruction* Current() const {
341 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000342 return current_->GetInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000343 }
344
345 private:
346 HUseListNode* current_;
347
348 friend class HValue;
349};
350
351class HInputIterator : public ValueObject {
352 public:
353 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
354
355 bool Done() const { return index_ == instruction_->InputCount(); }
356 HInstruction* Current() const { return instruction_->InputAt(index_); }
357 void Advance() { index_++; }
358
359 private:
360 HInstruction* instruction_;
361 int index_;
362
363 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
364};
365
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000366class HInstructionIterator : public ValueObject {
367 public:
368 explicit HInstructionIterator(HBasicBlock* block)
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000369 : instruction_(block->GetFirstInstruction()) {
370 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000371 }
372
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000373 bool Done() const { return instruction_ == nullptr; }
374 HInstruction* Current() const { return instruction_; }
375 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000376 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000377 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000378 }
379
380 private:
381 HInstruction* instruction_;
382 HInstruction* next_;
383};
384
385// An embedded container with N elements of type T. Used (with partial
386// specialization for N=0) because embedded arrays cannot have size 0.
387template<typename T, intptr_t N>
388class EmbeddedArray {
389 public:
390 EmbeddedArray() : elements_() { }
391
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000392 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000393
394 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000395 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000396 return elements_[i];
397 }
398
399 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000400 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000401 return elements_[i];
402 }
403
404 const T& At(intptr_t i) const {
405 return (*this)[i];
406 }
407
408 void SetAt(intptr_t i, const T& val) {
409 (*this)[i] = val;
410 }
411
412 private:
413 T elements_[N];
414};
415
416template<typename T>
417class EmbeddedArray<T, 0> {
418 public:
419 intptr_t length() const { return 0; }
420 const T& operator[](intptr_t i) const {
421 LOG(FATAL) << "Unreachable";
422 static T sentinel = 0;
423 return sentinel;
424 }
425 T& operator[](intptr_t i) {
426 LOG(FATAL) << "Unreachable";
427 static T sentinel = 0;
428 return sentinel;
429 }
430};
431
432template<intptr_t N>
433class HTemplateInstruction: public HInstruction {
434 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000435 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000436 virtual ~HTemplateInstruction() { }
437
438 virtual intptr_t InputCount() const { return N; }
439 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
440
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000441 protected:
442 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
443 inputs_[i] = instruction;
444 }
445
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000446 private:
447 EmbeddedArray<HInstruction*, N> inputs_;
448};
449
450// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
451// instruction that branches to the exit block.
452class HReturnVoid : public HTemplateInstruction<0> {
453 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000454 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000455
456 DECLARE_INSTRUCTION(ReturnVoid)
457
458 private:
459 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
460};
461
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000462// Represents dex's RETURN opcodes. A HReturn is a control flow
463// instruction that branches to the exit block.
464class HReturn : public HTemplateInstruction<1> {
465 public:
466 explicit HReturn(HInstruction* value) {
467 SetRawInputAt(0, value);
468 }
469
470 DECLARE_INSTRUCTION(Return)
471
472 private:
473 DISALLOW_COPY_AND_ASSIGN(HReturn);
474};
475
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000476// The exit instruction is the only instruction of the exit block.
477// Instructions aborting the method (HTrow and HReturn) must branch to the
478// exit block.
479class HExit : public HTemplateInstruction<0> {
480 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000481 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000482
483 DECLARE_INSTRUCTION(Exit)
484
485 private:
486 DISALLOW_COPY_AND_ASSIGN(HExit);
487};
488
489// Jumps from one block to another.
490class HGoto : public HTemplateInstruction<0> {
491 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000492 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000493
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000494 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000495 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000496 }
497
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000498 DECLARE_INSTRUCTION(Goto)
499
500 private:
501 DISALLOW_COPY_AND_ASSIGN(HGoto);
502};
503
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000504// Conditional branch. A block ending with an HIf instruction must have
505// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000506class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000507 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000508 explicit HIf(HInstruction* input) {
509 SetRawInputAt(0, input);
510 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000511
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000512 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000513 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000514 }
515
516 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000517 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000518 }
519
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000520 DECLARE_INSTRUCTION(If)
521
522 private:
523 DISALLOW_COPY_AND_ASSIGN(HIf);
524};
525
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000526class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000527 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000528 HBinaryOperation(Primitive::Type result_type,
529 HInstruction* left,
530 HInstruction* right) : result_type_(result_type) {
531 SetRawInputAt(0, left);
532 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000533 }
534
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000535 HInstruction* GetLeft() const { return InputAt(0); }
536 HInstruction* GetRight() const { return InputAt(1); }
537 Primitive::Type GetResultType() const { return result_type_; }
538
539 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100540 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000541
542 private:
543 const Primitive::Type result_type_;
544
545 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
546};
547
548
549// Instruction to check if two inputs are equal to each other.
550class HEqual : public HBinaryOperation {
551 public:
552 HEqual(HInstruction* first, HInstruction* second)
553 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
554
555 virtual bool IsCommutative() { return true; }
556
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100557 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
558
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000559 DECLARE_INSTRUCTION(Equal)
560
561 private:
562 DISALLOW_COPY_AND_ASSIGN(HEqual);
563};
564
565// A local in the graph. Corresponds to a Dex register.
566class HLocal : public HTemplateInstruction<0> {
567 public:
568 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
569
570 DECLARE_INSTRUCTION(Local)
571
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000572 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000573
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000574 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000575 // The Dex register number.
576 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000577
578 DISALLOW_COPY_AND_ASSIGN(HLocal);
579};
580
581// Load a given local. The local is an input of this instruction.
582class HLoadLocal : public HTemplateInstruction<1> {
583 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100584 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000585 SetRawInputAt(0, local);
586 }
587
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100588 virtual Primitive::Type GetType() const { return type_; }
589
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000590 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
591
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000592 DECLARE_INSTRUCTION(LoadLocal)
593
594 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100595 const Primitive::Type type_;
596
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000597 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
598};
599
600// Store a value in a given local. This instruction has two inputs: the value
601// and the local.
602class HStoreLocal : public HTemplateInstruction<2> {
603 public:
604 HStoreLocal(HLocal* local, HInstruction* value) {
605 SetRawInputAt(0, local);
606 SetRawInputAt(1, value);
607 }
608
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000609 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
610
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000611 DECLARE_INSTRUCTION(StoreLocal)
612
613 private:
614 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
615};
616
617// Constants of the type int. Those can be from Dex instructions, or
618// synthesized (for example with the if-eqz instruction).
619class HIntConstant : public HTemplateInstruction<0> {
620 public:
621 explicit HIntConstant(int32_t value) : value_(value) { }
622
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000623 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100624 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000625
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000626 DECLARE_INSTRUCTION(IntConstant)
627
628 private:
629 const int32_t value_;
630
631 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
632};
633
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100634class HLongConstant : public HTemplateInstruction<0> {
635 public:
636 explicit HLongConstant(int64_t value) : value_(value) { }
637
638 int64_t GetValue() const { return value_; }
639
640 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
641
642 DECLARE_INSTRUCTION(LongConstant)
643
644 private:
645 const int64_t value_;
646
647 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
648};
649
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000650class HInvoke : public HInstruction {
651 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100652 HInvoke(ArenaAllocator* arena,
653 uint32_t number_of_arguments,
654 Primitive::Type return_type,
655 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000656 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100657 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000658 dex_pc_(dex_pc) {
659 inputs_.SetSize(number_of_arguments);
660 }
661
662 virtual intptr_t InputCount() const { return inputs_.Size(); }
663 virtual HInstruction* InputAt(intptr_t i) const { return inputs_.Get(i); }
664
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100665 void SetArgumentAt(size_t index, HInstruction* argument) {
666 inputs_.Put(index, argument);
667 }
668
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100669 virtual Primitive::Type GetType() const { return return_type_; }
670
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100671 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000672
673 protected:
674 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100675 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100676 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000677
678 private:
679 DISALLOW_COPY_AND_ASSIGN(HInvoke);
680};
681
682class HInvokeStatic : public HInvoke {
683 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100684 HInvokeStatic(ArenaAllocator* arena,
685 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100686 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100687 uint32_t dex_pc,
688 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100689 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
690 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000691
692 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
693
694 DECLARE_INSTRUCTION(InvokeStatic)
695
696 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100697 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000698
699 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
700};
701
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100702class HNewInstance : public HTemplateInstruction<0> {
703 public:
704 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
705
706 uint32_t GetDexPc() const { return dex_pc_; }
707 uint16_t GetTypeIndex() const { return type_index_; }
708
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100709 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
710
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100711 DECLARE_INSTRUCTION(NewInstance)
712
713 private:
714 const uint32_t dex_pc_;
715 const uint16_t type_index_;
716
717 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
718};
719
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100720// HPushArgument nodes are inserted after the evaluation of an argument
721// of a call. Their mere purpose is to ease the code generator's work.
722class HPushArgument : public HTemplateInstruction<1> {
723 public:
724 HPushArgument(HInstruction* argument, uint8_t argument_index) : argument_index_(argument_index) {
725 SetRawInputAt(0, argument);
726 }
727
728 uint8_t GetArgumentIndex() const { return argument_index_; }
729
730 DECLARE_INSTRUCTION(PushArgument)
731
732 private:
733 const uint8_t argument_index_;
734
735 DISALLOW_COPY_AND_ASSIGN(HPushArgument);
736};
737
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000738class HAdd : public HBinaryOperation {
739 public:
740 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
741 : HBinaryOperation(result_type, left, right) {}
742
743 virtual bool IsCommutative() { return true; }
744
745 DECLARE_INSTRUCTION(Add);
746
747 private:
748 DISALLOW_COPY_AND_ASSIGN(HAdd);
749};
750
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100751class HSub : public HBinaryOperation {
752 public:
753 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
754 : HBinaryOperation(result_type, left, right) {}
755
756 virtual bool IsCommutative() { return false; }
757
758 DECLARE_INSTRUCTION(Sub);
759
760 private:
761 DISALLOW_COPY_AND_ASSIGN(HSub);
762};
763
764// The value of a parameter in this method. Its location depends on
765// the calling convention.
766class HParameterValue : public HTemplateInstruction<0> {
767 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100768 HParameterValue(uint8_t index, Primitive::Type parameter_type)
769 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100770
771 uint8_t GetIndex() const { return index_; }
772
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100773 virtual Primitive::Type GetType() const { return parameter_type_; }
774
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100775 DECLARE_INSTRUCTION(ParameterValue);
776
777 private:
778 // The index of this parameter in the parameters list. Must be less
779 // than HGraph::number_of_in_vregs_;
780 const uint8_t index_;
781
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100782 const Primitive::Type parameter_type_;
783
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100784 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
785};
786
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100787class HNot : public HTemplateInstruction<1> {
788 public:
789 explicit HNot(HInstruction* input) {
790 SetRawInputAt(0, input);
791 }
792
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100793 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
794
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100795 DECLARE_INSTRUCTION(Not);
796
797 private:
798 DISALLOW_COPY_AND_ASSIGN(HNot);
799};
800
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000801class HGraphVisitor : public ValueObject {
802 public:
803 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
804 virtual ~HGraphVisitor() { }
805
806 virtual void VisitInstruction(HInstruction* instruction) { }
807 virtual void VisitBasicBlock(HBasicBlock* block);
808
809 void VisitInsertionOrder();
810
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000811 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000812
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000813 // Visit functions for instruction classes.
814#define DECLARE_VISIT_INSTRUCTION(name) \
815 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
816
817 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
818
819#undef DECLARE_VISIT_INSTRUCTION
820
821 private:
822 HGraph* graph_;
823
824 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
825};
826
827} // namespace art
828
829#endif // ART_COMPILER_OPTIMIZING_NODES_H_