blob: bd3d703e864e3c13301c609b4a7a59e59d60b916 [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;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010027class HEnvironment;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000028class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000029class HIntConstant;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000030class HGraphVisitor;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010031class HPhi;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000032class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000033
34static const int kDefaultNumberOfBlocks = 8;
35static const int kDefaultNumberOfSuccessors = 2;
36static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000037static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000038
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010039class HInstructionList {
40 public:
41 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
42
43 void AddInstruction(HInstruction* instruction);
44 void RemoveInstruction(HInstruction* instruction);
45
46 private:
47 HInstruction* first_instruction_;
48 HInstruction* last_instruction_;
49
50 friend class HBasicBlock;
51 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +010052 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010053
54 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
55};
56
Nicolas Geoffray818f2102014-02-18 16:43:35 +000057// Control-flow graph of a method. Contains a list of basic blocks.
58class HGraph : public ArenaObject {
59 public:
60 explicit HGraph(ArenaAllocator* arena)
61 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray804d0932014-05-02 08:46:00 +010063 post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010064 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010065 number_of_vregs_(0),
66 number_of_in_vregs_(0),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000067 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000068
Nicolas Geoffray787c3072014-03-17 10:20:19 +000069 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +010070 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000071
Nicolas Geoffray787c3072014-03-17 10:20:19 +000072 HBasicBlock* GetEntryBlock() const { return entry_block_; }
73 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000074
Nicolas Geoffray787c3072014-03-17 10:20:19 +000075 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
76 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000077
Nicolas Geoffray818f2102014-02-18 16:43:35 +000078 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010079
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000080 void BuildDominatorTree();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010081 void TransformToSSA();
82 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000083
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000084 int GetNextInstructionId() {
85 return current_instruction_id_++;
86 }
87
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010088 uint16_t GetMaximumNumberOfOutVRegs() const {
89 return maximum_number_of_out_vregs_;
90 }
91
92 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
93 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
94 }
95
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010096 void SetNumberOfVRegs(uint16_t number_of_vregs) {
97 number_of_vregs_ = number_of_vregs;
98 }
99
100 uint16_t GetNumberOfVRegs() const {
101 return number_of_vregs_;
102 }
103
104 void SetNumberOfInVRegs(uint16_t value) {
105 number_of_in_vregs_ = value;
106 }
107
108 uint16_t GetNumberOfInVRegs() const {
109 return number_of_in_vregs_;
110 }
111
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100112 const GrowableArray<HBasicBlock*>& GetPostOrder() const {
113 return post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100114 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100115
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000116 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000117 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
118 void VisitBlockForDominatorTree(HBasicBlock* block,
119 HBasicBlock* predecessor,
120 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100121 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000122 void VisitBlockForBackEdges(HBasicBlock* block,
123 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100124 ArenaBitVector* visiting);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
126
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000127 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000128
129 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000130 GrowableArray<HBasicBlock*> blocks_;
131
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100132 // List of blocks to perform a post order tree traversal.
133 GrowableArray<HBasicBlock*> post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000134
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000135 HBasicBlock* entry_block_;
136 HBasicBlock* exit_block_;
137
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100138 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100139 uint16_t maximum_number_of_out_vregs_;
140
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100141 // The number of virtual registers in this method. Contains the parameters.
142 uint16_t number_of_vregs_;
143
144 // The number of virtual registers used by parameters of this method.
145 uint16_t number_of_in_vregs_;
146
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000147 // The current id to assign to a newly added instruction. See HInstruction.id_.
148 int current_instruction_id_;
149
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000150 DISALLOW_COPY_AND_ASSIGN(HGraph);
151};
152
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000153class HLoopInformation : public ArenaObject {
154 public:
155 HLoopInformation(HBasicBlock* header, HGraph* graph)
156 : header_(header),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000157 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges) { }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000158
159 void AddBackEdge(HBasicBlock* back_edge) {
160 back_edges_.Add(back_edge);
161 }
162
163 int NumberOfBackEdges() const {
164 return back_edges_.Size();
165 }
166
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100167 void SetPreHeader(HBasicBlock* block);
168
169 HBasicBlock* GetPreHeader() const {
170 return pre_header_;
171 }
172
173 const GrowableArray<HBasicBlock*>* GetBackEdges() const {
174 return &back_edges_;
175 }
176
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000177 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100178 HBasicBlock* pre_header_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000179 HBasicBlock* header_;
180 GrowableArray<HBasicBlock*> back_edges_;
181
182 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
183};
184
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000185// A block in a method. Contains the list of instructions represented
186// as a double linked list. Each block knows its predecessors and
187// successors.
188class HBasicBlock : public ArenaObject {
189 public:
190 explicit HBasicBlock(HGraph* graph)
191 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000192 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
193 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000194 loop_information_(nullptr),
195 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000196 block_id_(-1) { }
197
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000198 const GrowableArray<HBasicBlock*>* GetPredecessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000199 return &predecessors_;
200 }
201
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000202 const GrowableArray<HBasicBlock*>* GetSuccessors() const {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000203 return &successors_;
204 }
205
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000206 void AddBackEdge(HBasicBlock* back_edge) {
207 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000208 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000209 }
210 loop_information_->AddBackEdge(back_edge);
211 }
212
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000213 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000214
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000215 int GetBlockId() const { return block_id_; }
216 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000217
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000218 HBasicBlock* GetDominator() const { return dominator_; }
219 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000220
221 int NumberOfBackEdges() const {
222 return loop_information_ == nullptr
223 ? 0
224 : loop_information_->NumberOfBackEdges();
225 }
226
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100227 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
228 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
229 HInstructionList const* GetInstructions() const { return &instructions_; }
230 HInstructionList const* GetPhis() const { return &phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000231
232 void AddSuccessor(HBasicBlock* block) {
233 successors_.Add(block);
234 block->predecessors_.Add(this);
235 }
236
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100237 void RemovePredecessor(HBasicBlock* block, bool remove_in_successor = true) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000238 predecessors_.Delete(block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100239 if (remove_in_successor) {
240 block->successors_.Delete(this);
241 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000242 }
243
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000244 void AddInstruction(HInstruction* instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100245 void RemoveInstruction(HInstruction* instruction);
246 void AddPhi(HPhi* phi);
247 void RemovePhi(HPhi* phi);
248
249 bool IsLoopHeader() const {
250 return loop_information_ != nullptr;
251 }
252
253 HLoopInformation* GetLoopInformation() const {
254 return loop_information_;
255 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000256
257 private:
258 HGraph* const graph_;
259 GrowableArray<HBasicBlock*> predecessors_;
260 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100261 HInstructionList instructions_;
262 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000263 HLoopInformation* loop_information_;
264 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000265 int block_id_;
266
267 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
268};
269
270#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000271 M(Add) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000272 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000273 M(Exit) \
274 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000275 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000276 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000277 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000278 M(LoadLocal) \
279 M(Local) \
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100280 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100281 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100282 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100283 M(ParameterValue) \
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100284 M(Phi) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000285 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000286 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000287 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100288 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000289
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000290#define FORWARD_DECLARATION(type) class H##type;
291FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
292#undef FORWARD_DECLARATION
293
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000294#define DECLARE_INSTRUCTION(type) \
295 virtual void Accept(HGraphVisitor* visitor); \
296 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000297 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000298
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100299template <typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000300class HUseListNode : public ArenaObject {
301 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100302 HUseListNode(T* user, size_t index, HUseListNode* tail)
303 : user_(user), index_(index), tail_(tail) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000304
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000305 HUseListNode* GetTail() const { return tail_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100306 T* GetUser() const { return user_; }
307 size_t GetIndex() const { return index_; }
308
309 void SetTail(HUseListNode<T>* node) { tail_ = node; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000310
311 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100312 T* const user_;
313 const size_t index_;
314 HUseListNode<T>* tail_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000315
316 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
317};
318
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000319class HInstruction : public ArenaObject {
320 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000321 HInstruction()
322 : previous_(nullptr),
323 next_(nullptr),
324 block_(nullptr),
325 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100326 ssa_index_(-1),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000327 uses_(nullptr),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100328 env_uses_(nullptr),
329 environment_(nullptr),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000330 locations_(nullptr) { }
331
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000332 virtual ~HInstruction() { }
333
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000334 HInstruction* GetNext() const { return next_; }
335 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000336
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000337 HBasicBlock* GetBlock() const { return block_; }
338 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000339
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100340 virtual size_t InputCount() const = 0;
341 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000342
343 virtual void Accept(HGraphVisitor* visitor) = 0;
344 virtual const char* DebugName() const = 0;
345
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100346 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100347 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100348
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100349 virtual bool NeedsEnvironment() const { return false; }
350
351 void AddUseAt(HInstruction* user, size_t index) {
352 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000353 }
354
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100355 void AddEnvUseAt(HEnvironment* user, size_t index) {
356 env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
357 user, index, env_uses_);
358 }
359
360 void RemoveUser(HInstruction* user, size_t index);
361
362 HUseListNode<HInstruction>* GetUses() const { return uses_; }
363 HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000364
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100365 bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000366
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000367 int GetId() const { return id_; }
368 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000369
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100370 int GetSsaIndex() const { return ssa_index_; }
371 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
372 bool HasSsaIndex() const { return ssa_index_ != -1; }
373
374 bool HasEnvironment() const { return environment_ != nullptr; }
375 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100376 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
377
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000378 LocationSummary* GetLocations() const { return locations_; }
379 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000380
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100381 void ReplaceWith(HInstruction* instruction);
382
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000383#define INSTRUCTION_TYPE_CHECK(type) \
384 virtual H##type* As##type() { return nullptr; }
385
386 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
387#undef INSTRUCTION_TYPE_CHECK
388
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000389 private:
390 HInstruction* previous_;
391 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000392 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000393
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000394 // An instruction gets an id when it is added to the graph.
395 // It reflects creation order. A negative id means the instruction
396 // has not beed added to the graph.
397 int id_;
398
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100399 // When doing liveness analysis, instructions that have uses get an SSA index.
400 int ssa_index_;
401
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100402 // List of instructions that have this instruction as input.
403 HUseListNode<HInstruction>* uses_;
404
405 // List of environments that contain this instruction.
406 HUseListNode<HEnvironment>* env_uses_;
407
408 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000409
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000410 // Set by the code generator.
411 LocationSummary* locations_;
412
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000413 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100414 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000415
416 DISALLOW_COPY_AND_ASSIGN(HInstruction);
417};
418
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100419template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000420class HUseIterator : public ValueObject {
421 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100422 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000423
424 bool Done() const { return current_ == nullptr; }
425
426 void Advance() {
427 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000428 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000429 }
430
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100431 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000432 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100433 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000434 }
435
436 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100437 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000438
439 friend class HValue;
440};
441
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100442// A HEnvironment object contains the values of virtual registers at a given location.
443class HEnvironment : public ArenaObject {
444 public:
445 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
446 vregs_.SetSize(number_of_vregs);
447 for (size_t i = 0; i < number_of_vregs; i++) {
448 vregs_.Put(i, nullptr);
449 }
450 }
451
452 void Populate(const GrowableArray<HInstruction*>& env) {
453 for (size_t i = 0; i < env.Size(); i++) {
454 HInstruction* instruction = env.Get(i);
455 vregs_.Put(i, instruction);
456 if (instruction != nullptr) {
457 instruction->AddEnvUseAt(this, i);
458 }
459 }
460 }
461
462 void SetRawEnvAt(size_t index, HInstruction* instruction) {
463 vregs_.Put(index, instruction);
464 }
465
466 GrowableArray<HInstruction*>* GetVRegs() {
467 return &vregs_;
468 }
469
470 private:
471 GrowableArray<HInstruction*> vregs_;
472
473 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
474};
475
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000476class HInputIterator : public ValueObject {
477 public:
478 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
479
480 bool Done() const { return index_ == instruction_->InputCount(); }
481 HInstruction* Current() const { return instruction_->InputAt(index_); }
482 void Advance() { index_++; }
483
484 private:
485 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100486 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000487
488 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
489};
490
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000491class HInstructionIterator : public ValueObject {
492 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100493 explicit HInstructionIterator(const HInstructionList& instructions)
494 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000495 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000496 }
497
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000498 bool Done() const { return instruction_ == nullptr; }
499 HInstruction* Current() const { return instruction_; }
500 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000501 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000502 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000503 }
504
505 private:
506 HInstruction* instruction_;
507 HInstruction* next_;
508};
509
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100510class HBackwardInstructionIterator : public ValueObject {
511 public:
512 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
513 : instruction_(instructions.last_instruction_) {
514 next_ = Done() ? nullptr : instruction_->GetPrevious();
515 }
516
517 bool Done() const { return instruction_ == nullptr; }
518 HInstruction* Current() const { return instruction_; }
519 void Advance() {
520 instruction_ = next_;
521 next_ = Done() ? nullptr : instruction_->GetPrevious();
522 }
523
524 private:
525 HInstruction* instruction_;
526 HInstruction* next_;
527};
528
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000529// An embedded container with N elements of type T. Used (with partial
530// specialization for N=0) because embedded arrays cannot have size 0.
531template<typename T, intptr_t N>
532class EmbeddedArray {
533 public:
534 EmbeddedArray() : elements_() { }
535
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000536 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000537
538 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000539 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000540 return elements_[i];
541 }
542
543 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000544 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000545 return elements_[i];
546 }
547
548 const T& At(intptr_t i) const {
549 return (*this)[i];
550 }
551
552 void SetAt(intptr_t i, const T& val) {
553 (*this)[i] = val;
554 }
555
556 private:
557 T elements_[N];
558};
559
560template<typename T>
561class EmbeddedArray<T, 0> {
562 public:
563 intptr_t length() const { return 0; }
564 const T& operator[](intptr_t i) const {
565 LOG(FATAL) << "Unreachable";
566 static T sentinel = 0;
567 return sentinel;
568 }
569 T& operator[](intptr_t i) {
570 LOG(FATAL) << "Unreachable";
571 static T sentinel = 0;
572 return sentinel;
573 }
574};
575
576template<intptr_t N>
577class HTemplateInstruction: public HInstruction {
578 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000579 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000580 virtual ~HTemplateInstruction() { }
581
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100582 virtual size_t InputCount() const { return N; }
583 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000584
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000585 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100586 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000587 inputs_[i] = instruction;
588 }
589
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000590 private:
591 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100592
593 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000594};
595
596// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
597// instruction that branches to the exit block.
598class HReturnVoid : public HTemplateInstruction<0> {
599 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000600 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000601
602 DECLARE_INSTRUCTION(ReturnVoid)
603
604 private:
605 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
606};
607
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000608// Represents dex's RETURN opcodes. A HReturn is a control flow
609// instruction that branches to the exit block.
610class HReturn : public HTemplateInstruction<1> {
611 public:
612 explicit HReturn(HInstruction* value) {
613 SetRawInputAt(0, value);
614 }
615
616 DECLARE_INSTRUCTION(Return)
617
618 private:
619 DISALLOW_COPY_AND_ASSIGN(HReturn);
620};
621
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000622// The exit instruction is the only instruction of the exit block.
623// Instructions aborting the method (HTrow and HReturn) must branch to the
624// exit block.
625class HExit : public HTemplateInstruction<0> {
626 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000627 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000628
629 DECLARE_INSTRUCTION(Exit)
630
631 private:
632 DISALLOW_COPY_AND_ASSIGN(HExit);
633};
634
635// Jumps from one block to another.
636class HGoto : public HTemplateInstruction<0> {
637 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000638 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000639
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000640 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000641 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000642 }
643
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000644 DECLARE_INSTRUCTION(Goto)
645
646 private:
647 DISALLOW_COPY_AND_ASSIGN(HGoto);
648};
649
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000650// Conditional branch. A block ending with an HIf instruction must have
651// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000652class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000653 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000654 explicit HIf(HInstruction* input) {
655 SetRawInputAt(0, input);
656 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000657
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000658 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000659 return GetBlock()->GetSuccessors()->Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000660 }
661
662 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000663 return GetBlock()->GetSuccessors()->Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000664 }
665
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000666 DECLARE_INSTRUCTION(If)
667
668 private:
669 DISALLOW_COPY_AND_ASSIGN(HIf);
670};
671
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000672class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000673 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000674 HBinaryOperation(Primitive::Type result_type,
675 HInstruction* left,
676 HInstruction* right) : result_type_(result_type) {
677 SetRawInputAt(0, left);
678 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000679 }
680
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000681 HInstruction* GetLeft() const { return InputAt(0); }
682 HInstruction* GetRight() const { return InputAt(1); }
683 Primitive::Type GetResultType() const { return result_type_; }
684
685 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100686 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000687
688 private:
689 const Primitive::Type result_type_;
690
691 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
692};
693
694
695// Instruction to check if two inputs are equal to each other.
696class HEqual : public HBinaryOperation {
697 public:
698 HEqual(HInstruction* first, HInstruction* second)
699 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
700
701 virtual bool IsCommutative() { return true; }
702
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100703 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
704
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000705 DECLARE_INSTRUCTION(Equal)
706
707 private:
708 DISALLOW_COPY_AND_ASSIGN(HEqual);
709};
710
711// A local in the graph. Corresponds to a Dex register.
712class HLocal : public HTemplateInstruction<0> {
713 public:
714 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
715
716 DECLARE_INSTRUCTION(Local)
717
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000718 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000719
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000720 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000721 // The Dex register number.
722 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000723
724 DISALLOW_COPY_AND_ASSIGN(HLocal);
725};
726
727// Load a given local. The local is an input of this instruction.
728class HLoadLocal : public HTemplateInstruction<1> {
729 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100730 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000731 SetRawInputAt(0, local);
732 }
733
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100734 virtual Primitive::Type GetType() const { return type_; }
735
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000736 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
737
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000738 DECLARE_INSTRUCTION(LoadLocal)
739
740 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100741 const Primitive::Type type_;
742
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000743 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
744};
745
746// Store a value in a given local. This instruction has two inputs: the value
747// and the local.
748class HStoreLocal : public HTemplateInstruction<2> {
749 public:
750 HStoreLocal(HLocal* local, HInstruction* value) {
751 SetRawInputAt(0, local);
752 SetRawInputAt(1, value);
753 }
754
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000755 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
756
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000757 DECLARE_INSTRUCTION(StoreLocal)
758
759 private:
760 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
761};
762
763// Constants of the type int. Those can be from Dex instructions, or
764// synthesized (for example with the if-eqz instruction).
765class HIntConstant : public HTemplateInstruction<0> {
766 public:
767 explicit HIntConstant(int32_t value) : value_(value) { }
768
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000769 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100770 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000771
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000772 DECLARE_INSTRUCTION(IntConstant)
773
774 private:
775 const int32_t value_;
776
777 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
778};
779
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100780class HLongConstant : public HTemplateInstruction<0> {
781 public:
782 explicit HLongConstant(int64_t value) : value_(value) { }
783
784 int64_t GetValue() const { return value_; }
785
786 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
787
788 DECLARE_INSTRUCTION(LongConstant)
789
790 private:
791 const int64_t value_;
792
793 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
794};
795
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000796class HInvoke : public HInstruction {
797 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100798 HInvoke(ArenaAllocator* arena,
799 uint32_t number_of_arguments,
800 Primitive::Type return_type,
801 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000802 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100803 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000804 dex_pc_(dex_pc) {
805 inputs_.SetSize(number_of_arguments);
806 }
807
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100808 virtual size_t InputCount() const { return inputs_.Size(); }
809 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
810
811 // Runtime needs to walk the stack, so Dex -> Dex calls need to
812 // know their environment.
813 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000814
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100815 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100816 SetRawInputAt(index, argument);
817 }
818
819 virtual void SetRawInputAt(size_t index, HInstruction* input) {
820 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100821 }
822
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100823 virtual Primitive::Type GetType() const { return return_type_; }
824
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100825 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000826
827 protected:
828 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100829 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100830 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000831
832 private:
833 DISALLOW_COPY_AND_ASSIGN(HInvoke);
834};
835
836class HInvokeStatic : public HInvoke {
837 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100838 HInvokeStatic(ArenaAllocator* arena,
839 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100840 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100841 uint32_t dex_pc,
842 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100843 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
844 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000845
846 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
847
848 DECLARE_INSTRUCTION(InvokeStatic)
849
850 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100851 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000852
853 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
854};
855
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100856class HNewInstance : public HTemplateInstruction<0> {
857 public:
858 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
859
860 uint32_t GetDexPc() const { return dex_pc_; }
861 uint16_t GetTypeIndex() const { return type_index_; }
862
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100863 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
864
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100865 // Calls runtime so needs an environment.
866 virtual bool NeedsEnvironment() const { return true; }
867
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100868 DECLARE_INSTRUCTION(NewInstance)
869
870 private:
871 const uint32_t dex_pc_;
872 const uint16_t type_index_;
873
874 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
875};
876
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000877class HAdd : public HBinaryOperation {
878 public:
879 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
880 : HBinaryOperation(result_type, left, right) {}
881
882 virtual bool IsCommutative() { return true; }
883
884 DECLARE_INSTRUCTION(Add);
885
886 private:
887 DISALLOW_COPY_AND_ASSIGN(HAdd);
888};
889
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100890class HSub : public HBinaryOperation {
891 public:
892 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
893 : HBinaryOperation(result_type, left, right) {}
894
895 virtual bool IsCommutative() { return false; }
896
897 DECLARE_INSTRUCTION(Sub);
898
899 private:
900 DISALLOW_COPY_AND_ASSIGN(HSub);
901};
902
903// The value of a parameter in this method. Its location depends on
904// the calling convention.
905class HParameterValue : public HTemplateInstruction<0> {
906 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100907 HParameterValue(uint8_t index, Primitive::Type parameter_type)
908 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100909
910 uint8_t GetIndex() const { return index_; }
911
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100912 virtual Primitive::Type GetType() const { return parameter_type_; }
913
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100914 DECLARE_INSTRUCTION(ParameterValue);
915
916 private:
917 // The index of this parameter in the parameters list. Must be less
918 // than HGraph::number_of_in_vregs_;
919 const uint8_t index_;
920
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100921 const Primitive::Type parameter_type_;
922
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100923 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
924};
925
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100926class HNot : public HTemplateInstruction<1> {
927 public:
928 explicit HNot(HInstruction* input) {
929 SetRawInputAt(0, input);
930 }
931
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100932 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
933
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100934 DECLARE_INSTRUCTION(Not);
935
936 private:
937 DISALLOW_COPY_AND_ASSIGN(HNot);
938};
939
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100940class HPhi : public HInstruction {
941 public:
942 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
943 : inputs_(arena, number_of_inputs),
944 reg_number_(reg_number),
945 type_(type) {
946 inputs_.SetSize(number_of_inputs);
947 }
948
949 virtual size_t InputCount() const { return inputs_.Size(); }
950 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
951
952 virtual void SetRawInputAt(size_t index, HInstruction* input) {
953 inputs_.Put(index, input);
954 }
955
956 void AddInput(HInstruction* input);
957
958 virtual Primitive::Type GetType() const { return type_; }
959
960 uint32_t GetRegNumber() const { return reg_number_; }
961
962 DECLARE_INSTRUCTION(Phi)
963
964 protected:
965 GrowableArray<HInstruction*> inputs_;
966 const uint32_t reg_number_;
967 const Primitive::Type type_;
968
969 private:
970 DISALLOW_COPY_AND_ASSIGN(HPhi);
971};
972
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000973class HGraphVisitor : public ValueObject {
974 public:
975 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
976 virtual ~HGraphVisitor() { }
977
978 virtual void VisitInstruction(HInstruction* instruction) { }
979 virtual void VisitBasicBlock(HBasicBlock* block);
980
981 void VisitInsertionOrder();
982
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000983 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000984
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000985 // Visit functions for instruction classes.
986#define DECLARE_VISIT_INSTRUCTION(name) \
987 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
988
989 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
990
991#undef DECLARE_VISIT_INSTRUCTION
992
993 private:
994 HGraph* graph_;
995
996 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
997};
998
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100999class HInsertionOrderIterator : public ValueObject {
1000 public:
1001 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1002
1003 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1004 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1005 void Advance() { ++index_; }
1006
1007 private:
1008 const HGraph& graph_;
1009 size_t index_;
1010
1011 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1012};
1013
1014class HPostOrderIterator : public ValueObject {
1015 public:
1016 explicit HPostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1017
1018 bool Done() const { return index_ == graph_.GetPostOrder().Size(); }
1019 HBasicBlock* Current() const { return graph_.GetPostOrder().Get(index_); }
1020 void Advance() { ++index_; }
1021
1022 private:
1023 const HGraph& graph_;
1024 size_t index_;
1025
1026 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
1027};
1028
1029class HReversePostOrderIterator : public ValueObject {
1030 public:
1031 explicit HReversePostOrderIterator(const HGraph& graph)
1032 : graph_(graph), index_(graph_.GetPostOrder().Size()) {}
1033
1034 bool Done() const { return index_ == 0; }
1035 HBasicBlock* Current() const { return graph_.GetPostOrder().Get(index_ - 1); }
1036 void Advance() { --index_; }
1037
1038 private:
1039 const HGraph& graph_;
1040 size_t index_;
1041
1042 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
1043};
1044
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001045} // namespace art
1046
1047#endif // ART_COMPILER_OPTIMIZING_NODES_H_