blob: 3da9ed9461ba94df67b267d9787d618f61b5f230 [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 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 Geoffray01bc96d2014-04-11 17:43:50 +0100286 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
287
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000288 void AddUse(HInstruction* user) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000289 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode(user, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000290 }
291
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000292 HUseListNode* GetUses() const { return uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000293
294 bool HasUses() const { return uses_ != nullptr; }
295
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000296 int GetId() const { return id_; }
297 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000298
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000299 LocationSummary* GetLocations() const { return locations_; }
300 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000301
302#define INSTRUCTION_TYPE_CHECK(type) \
303 virtual H##type* As##type() { return nullptr; }
304
305 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
306#undef INSTRUCTION_TYPE_CHECK
307
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000308 private:
309 HInstruction* previous_;
310 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000311 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000312
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000313 // An instruction gets an id when it is added to the graph.
314 // It reflects creation order. A negative id means the instruction
315 // has not beed added to the graph.
316 int id_;
317
318 HUseListNode* uses_;
319
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000320 // Set by the code generator.
321 LocationSummary* locations_;
322
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000323 friend class HBasicBlock;
324
325 DISALLOW_COPY_AND_ASSIGN(HInstruction);
326};
327
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000328class HUseIterator : public ValueObject {
329 public:
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000330 explicit HUseIterator(HInstruction* instruction) : current_(instruction->GetUses()) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000331
332 bool Done() const { return current_ == nullptr; }
333
334 void Advance() {
335 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000336 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000337 }
338
339 HInstruction* Current() const {
340 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000341 return current_->GetInstruction();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000342 }
343
344 private:
345 HUseListNode* current_;
346
347 friend class HValue;
348};
349
350class HInputIterator : public ValueObject {
351 public:
352 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
353
354 bool Done() const { return index_ == instruction_->InputCount(); }
355 HInstruction* Current() const { return instruction_->InputAt(index_); }
356 void Advance() { index_++; }
357
358 private:
359 HInstruction* instruction_;
360 int index_;
361
362 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
363};
364
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000365class HInstructionIterator : public ValueObject {
366 public:
367 explicit HInstructionIterator(HBasicBlock* block)
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000368 : instruction_(block->GetFirstInstruction()) {
369 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000370 }
371
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000372 bool Done() const { return instruction_ == nullptr; }
373 HInstruction* Current() const { return instruction_; }
374 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000375 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000376 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000377 }
378
379 private:
380 HInstruction* instruction_;
381 HInstruction* next_;
382};
383
384// An embedded container with N elements of type T. Used (with partial
385// specialization for N=0) because embedded arrays cannot have size 0.
386template<typename T, intptr_t N>
387class EmbeddedArray {
388 public:
389 EmbeddedArray() : elements_() { }
390
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000391 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000392
393 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000394 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000395 return elements_[i];
396 }
397
398 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000399 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000400 return elements_[i];
401 }
402
403 const T& At(intptr_t i) const {
404 return (*this)[i];
405 }
406
407 void SetAt(intptr_t i, const T& val) {
408 (*this)[i] = val;
409 }
410
411 private:
412 T elements_[N];
413};
414
415template<typename T>
416class EmbeddedArray<T, 0> {
417 public:
418 intptr_t length() const { return 0; }
419 const T& operator[](intptr_t i) const {
420 LOG(FATAL) << "Unreachable";
421 static T sentinel = 0;
422 return sentinel;
423 }
424 T& operator[](intptr_t i) {
425 LOG(FATAL) << "Unreachable";
426 static T sentinel = 0;
427 return sentinel;
428 }
429};
430
431template<intptr_t N>
432class HTemplateInstruction: public HInstruction {
433 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000434 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000435 virtual ~HTemplateInstruction() { }
436
437 virtual intptr_t InputCount() const { return N; }
438 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
439
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000440 protected:
441 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
442 inputs_[i] = instruction;
443 }
444
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000445 private:
446 EmbeddedArray<HInstruction*, N> inputs_;
447};
448
449// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
450// instruction that branches to the exit block.
451class HReturnVoid : public HTemplateInstruction<0> {
452 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000453 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000454
455 DECLARE_INSTRUCTION(ReturnVoid)
456
457 private:
458 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
459};
460
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000461// Represents dex's RETURN opcodes. A HReturn is a control flow
462// instruction that branches to the exit block.
463class HReturn : public HTemplateInstruction<1> {
464 public:
465 explicit HReturn(HInstruction* value) {
466 SetRawInputAt(0, value);
467 }
468
469 DECLARE_INSTRUCTION(Return)
470
471 private:
472 DISALLOW_COPY_AND_ASSIGN(HReturn);
473};
474
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000475// The exit instruction is the only instruction of the exit block.
476// Instructions aborting the method (HTrow and HReturn) must branch to the
477// exit block.
478class HExit : public HTemplateInstruction<0> {
479 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000480 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000481
482 DECLARE_INSTRUCTION(Exit)
483
484 private:
485 DISALLOW_COPY_AND_ASSIGN(HExit);
486};
487
488// Jumps from one block to another.
489class HGoto : public HTemplateInstruction<0> {
490 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000491 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000492
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000493 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000494 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000495 }
496
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000497 DECLARE_INSTRUCTION(Goto)
498
499 private:
500 DISALLOW_COPY_AND_ASSIGN(HGoto);
501};
502
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000503// Conditional branch. A block ending with an HIf instruction must have
504// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000505class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000506 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000507 explicit HIf(HInstruction* input) {
508 SetRawInputAt(0, input);
509 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000510
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000511 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000512 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000513 }
514
515 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000516 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000517 }
518
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000519 DECLARE_INSTRUCTION(If)
520
521 private:
522 DISALLOW_COPY_AND_ASSIGN(HIf);
523};
524
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000525class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000526 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000527 HBinaryOperation(Primitive::Type result_type,
528 HInstruction* left,
529 HInstruction* right) : result_type_(result_type) {
530 SetRawInputAt(0, left);
531 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000532 }
533
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000534 HInstruction* GetLeft() const { return InputAt(0); }
535 HInstruction* GetRight() const { return InputAt(1); }
536 Primitive::Type GetResultType() const { return result_type_; }
537
538 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100539 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000540
541 private:
542 const Primitive::Type result_type_;
543
544 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
545};
546
547
548// Instruction to check if two inputs are equal to each other.
549class HEqual : public HBinaryOperation {
550 public:
551 HEqual(HInstruction* first, HInstruction* second)
552 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
553
554 virtual bool IsCommutative() { return true; }
555
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100556 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
557
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000558 DECLARE_INSTRUCTION(Equal)
559
560 private:
561 DISALLOW_COPY_AND_ASSIGN(HEqual);
562};
563
564// A local in the graph. Corresponds to a Dex register.
565class HLocal : public HTemplateInstruction<0> {
566 public:
567 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
568
569 DECLARE_INSTRUCTION(Local)
570
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000571 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000572
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000573 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000574 // The Dex register number.
575 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000576
577 DISALLOW_COPY_AND_ASSIGN(HLocal);
578};
579
580// Load a given local. The local is an input of this instruction.
581class HLoadLocal : public HTemplateInstruction<1> {
582 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100583 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000584 SetRawInputAt(0, local);
585 }
586
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100587 virtual Primitive::Type GetType() const { return type_; }
588
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000589 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
590
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000591 DECLARE_INSTRUCTION(LoadLocal)
592
593 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100594 const Primitive::Type type_;
595
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000596 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
597};
598
599// Store a value in a given local. This instruction has two inputs: the value
600// and the local.
601class HStoreLocal : public HTemplateInstruction<2> {
602 public:
603 HStoreLocal(HLocal* local, HInstruction* value) {
604 SetRawInputAt(0, local);
605 SetRawInputAt(1, value);
606 }
607
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000608 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
609
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000610 DECLARE_INSTRUCTION(StoreLocal)
611
612 private:
613 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
614};
615
616// Constants of the type int. Those can be from Dex instructions, or
617// synthesized (for example with the if-eqz instruction).
618class HIntConstant : public HTemplateInstruction<0> {
619 public:
620 explicit HIntConstant(int32_t value) : value_(value) { }
621
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000622 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100623 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000624
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000625 DECLARE_INSTRUCTION(IntConstant)
626
627 private:
628 const int32_t value_;
629
630 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
631};
632
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100633class HLongConstant : public HTemplateInstruction<0> {
634 public:
635 explicit HLongConstant(int64_t value) : value_(value) { }
636
637 int64_t GetValue() const { return value_; }
638
639 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
640
641 DECLARE_INSTRUCTION(LongConstant)
642
643 private:
644 const int64_t value_;
645
646 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
647};
648
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000649class HInvoke : public HInstruction {
650 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100651 HInvoke(ArenaAllocator* arena,
652 uint32_t number_of_arguments,
653 Primitive::Type return_type,
654 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000655 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100656 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000657 dex_pc_(dex_pc) {
658 inputs_.SetSize(number_of_arguments);
659 }
660
661 virtual intptr_t InputCount() const { return inputs_.Size(); }
662 virtual HInstruction* InputAt(intptr_t i) const { return inputs_.Get(i); }
663
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100664 void SetArgumentAt(size_t index, HInstruction* argument) {
665 inputs_.Put(index, argument);
666 }
667
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100668 virtual Primitive::Type GetType() const { return return_type_; }
669
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100670 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000671
672 protected:
673 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100674 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100675 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000676
677 private:
678 DISALLOW_COPY_AND_ASSIGN(HInvoke);
679};
680
681class HInvokeStatic : public HInvoke {
682 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100683 HInvokeStatic(ArenaAllocator* arena,
684 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100685 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100686 uint32_t dex_pc,
687 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100688 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
689 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000690
691 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
692
693 DECLARE_INSTRUCTION(InvokeStatic)
694
695 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100696 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000697
698 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
699};
700
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100701class HNewInstance : public HTemplateInstruction<0> {
702 public:
703 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
704
705 uint32_t GetDexPc() const { return dex_pc_; }
706 uint16_t GetTypeIndex() const { return type_index_; }
707
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100708 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
709
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100710 DECLARE_INSTRUCTION(NewInstance)
711
712 private:
713 const uint32_t dex_pc_;
714 const uint16_t type_index_;
715
716 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
717};
718
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000719class HAdd : public HBinaryOperation {
720 public:
721 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
722 : HBinaryOperation(result_type, left, right) {}
723
724 virtual bool IsCommutative() { return true; }
725
726 DECLARE_INSTRUCTION(Add);
727
728 private:
729 DISALLOW_COPY_AND_ASSIGN(HAdd);
730};
731
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100732class HSub : public HBinaryOperation {
733 public:
734 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
735 : HBinaryOperation(result_type, left, right) {}
736
737 virtual bool IsCommutative() { return false; }
738
739 DECLARE_INSTRUCTION(Sub);
740
741 private:
742 DISALLOW_COPY_AND_ASSIGN(HSub);
743};
744
745// The value of a parameter in this method. Its location depends on
746// the calling convention.
747class HParameterValue : public HTemplateInstruction<0> {
748 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100749 HParameterValue(uint8_t index, Primitive::Type parameter_type)
750 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100751
752 uint8_t GetIndex() const { return index_; }
753
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100754 virtual Primitive::Type GetType() const { return parameter_type_; }
755
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100756 DECLARE_INSTRUCTION(ParameterValue);
757
758 private:
759 // The index of this parameter in the parameters list. Must be less
760 // than HGraph::number_of_in_vregs_;
761 const uint8_t index_;
762
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100763 const Primitive::Type parameter_type_;
764
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100765 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
766};
767
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100768class HNot : public HTemplateInstruction<1> {
769 public:
770 explicit HNot(HInstruction* input) {
771 SetRawInputAt(0, input);
772 }
773
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100774 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
775
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100776 DECLARE_INSTRUCTION(Not);
777
778 private:
779 DISALLOW_COPY_AND_ASSIGN(HNot);
780};
781
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000782class HGraphVisitor : public ValueObject {
783 public:
784 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
785 virtual ~HGraphVisitor() { }
786
787 virtual void VisitInstruction(HInstruction* instruction) { }
788 virtual void VisitBasicBlock(HBasicBlock* block);
789
790 void VisitInsertionOrder();
791
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000792 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000793
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000794 // Visit functions for instruction classes.
795#define DECLARE_VISIT_INSTRUCTION(name) \
796 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
797
798 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
799
800#undef DECLARE_VISIT_INSTRUCTION
801
802 private:
803 HGraph* graph_;
804
805 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
806};
807
808} // namespace art
809
810#endif // ART_COMPILER_OPTIMIZING_NODES_H_