blob: a2cb1c47aeac8b553ba232df523ae4ac26beee9c [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 Geoffrayddb311f2014-05-16 09:28:54 +010032class LiveInterval;
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +000033class LocationSummary;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000034
35static const int kDefaultNumberOfBlocks = 8;
36static const int kDefaultNumberOfSuccessors = 2;
37static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000038static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000039
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010040class HInstructionList {
41 public:
42 HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
43
44 void AddInstruction(HInstruction* instruction);
45 void RemoveInstruction(HInstruction* instruction);
46
47 private:
48 HInstruction* first_instruction_;
49 HInstruction* last_instruction_;
50
51 friend class HBasicBlock;
52 friend class HInstructionIterator;
Nicolas Geoffray804d0932014-05-02 08:46:00 +010053 friend class HBackwardInstructionIterator;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010054
55 DISALLOW_COPY_AND_ASSIGN(HInstructionList);
56};
57
Nicolas Geoffray818f2102014-02-18 16:43:35 +000058// Control-flow graph of a method. Contains a list of basic blocks.
59class HGraph : public ArenaObject {
60 public:
61 explicit HGraph(ArenaAllocator* arena)
62 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000063 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010064 reverse_post_order_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010065 maximum_number_of_out_vregs_(0),
Nicolas Geoffrayf583e592014-04-07 13:20:42 +010066 number_of_vregs_(0),
67 number_of_in_vregs_(0),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000068 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000069
Nicolas Geoffray787c3072014-03-17 10:20:19 +000070 ArenaAllocator* GetArena() const { return arena_; }
Nicolas Geoffray804d0932014-05-02 08:46:00 +010071 const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000072
Nicolas Geoffray787c3072014-03-17 10:20:19 +000073 HBasicBlock* GetEntryBlock() const { return entry_block_; }
74 HBasicBlock* GetExitBlock() const { return exit_block_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000075
Nicolas Geoffray787c3072014-03-17 10:20:19 +000076 void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
77 void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000078
Nicolas Geoffray818f2102014-02-18 16:43:35 +000079 void AddBlock(HBasicBlock* block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010080
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000081 void BuildDominatorTree();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010082 void TransformToSSA();
83 void SimplifyCFG();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000084
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010085 // Find all natural loops in this graph. Aborts computation and returns false
Nicolas Geoffrayf635e632014-05-14 09:43:38 +010086 // if one loop is not natural, that is the header does not dominate the back
Nicolas Geoffray622d9c32014-05-12 16:11:02 +010087 // edge.
88 bool FindNaturalLoops() const;
89
90 void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
91 void SimplifyLoop(HBasicBlock* header);
92
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000093 int GetNextInstructionId() {
94 return current_instruction_id_++;
95 }
96
Nicolas Geoffray4a34a422014-04-03 10:38:37 +010097 uint16_t GetMaximumNumberOfOutVRegs() const {
98 return maximum_number_of_out_vregs_;
99 }
100
101 void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
102 maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
103 }
104
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100105 void SetNumberOfVRegs(uint16_t number_of_vregs) {
106 number_of_vregs_ = number_of_vregs;
107 }
108
109 uint16_t GetNumberOfVRegs() const {
110 return number_of_vregs_;
111 }
112
113 void SetNumberOfInVRegs(uint16_t value) {
114 number_of_in_vregs_ = value;
115 }
116
117 uint16_t GetNumberOfInVRegs() const {
118 return number_of_in_vregs_;
119 }
120
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100121 const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
122 return reverse_post_order_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100123 }
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100124
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000125 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000126 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
127 void VisitBlockForDominatorTree(HBasicBlock* block,
128 HBasicBlock* predecessor,
129 GrowableArray<size_t>* visits);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100130 void FindBackEdges(ArenaBitVector* visited);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000131 void VisitBlockForBackEdges(HBasicBlock* block,
132 ArenaBitVector* visited,
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100133 ArenaBitVector* visiting);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000134 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
135
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000136 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000137
138 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000139 GrowableArray<HBasicBlock*> blocks_;
140
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100141 // List of blocks to perform a reverse post order tree traversal.
142 GrowableArray<HBasicBlock*> reverse_post_order_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000143
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000144 HBasicBlock* entry_block_;
145 HBasicBlock* exit_block_;
146
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100147 // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100148 uint16_t maximum_number_of_out_vregs_;
149
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100150 // The number of virtual registers in this method. Contains the parameters.
151 uint16_t number_of_vregs_;
152
153 // The number of virtual registers used by parameters of this method.
154 uint16_t number_of_in_vregs_;
155
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000156 // The current id to assign to a newly added instruction. See HInstruction.id_.
157 int current_instruction_id_;
158
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000159 DISALLOW_COPY_AND_ASSIGN(HGraph);
160};
161
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000162class HLoopInformation : public ArenaObject {
163 public:
164 HLoopInformation(HBasicBlock* header, HGraph* graph)
165 : header_(header),
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100166 back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
167 blocks_(graph->GetArena(), graph->GetBlocks().Size(), false) {}
168
169 HBasicBlock* GetHeader() const {
170 return header_;
171 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000172
173 void AddBackEdge(HBasicBlock* back_edge) {
174 back_edges_.Add(back_edge);
175 }
176
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100177 void RemoveBackEdge(HBasicBlock* back_edge) {
178 back_edges_.Delete(back_edge);
179 }
180
181 bool IsBackEdge(HBasicBlock* block) {
182 for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
183 if (back_edges_.Get(i) == block) return true;
184 }
185 return false;
186 }
187
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000188 int NumberOfBackEdges() const {
189 return back_edges_.Size();
190 }
191
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100192 HBasicBlock* GetPreHeader() const;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100193
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100194 const GrowableArray<HBasicBlock*>& GetBackEdges() const {
195 return back_edges_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100196 }
197
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100198 void ClearBackEdges() {
199 back_edges_.Reset();
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100200 }
201
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100202 // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
203 // that is the header dominates the back edge.
204 bool Populate();
205
206 // Returns whether this loop information contains `block`.
207 // Note that this loop information *must* be populated before entering this function.
208 bool Contains(const HBasicBlock& block) const;
209
210 // Returns whether this loop information is an inner loop of `other`.
211 // Note that `other` *must* be populated before entering this function.
212 bool IsIn(const HLoopInformation& other) const;
213
214 const ArenaBitVector& GetBlocks() const { return blocks_; }
215
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000216 private:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100217 // Internal recursive implementation of `Populate`.
218 void PopulateRecursive(HBasicBlock* block);
219
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000220 HBasicBlock* header_;
221 GrowableArray<HBasicBlock*> back_edges_;
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100222 ArenaBitVector blocks_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000223
224 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
225};
226
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100227static constexpr size_t kNoLifetime = -1;
228
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000229// A block in a method. Contains the list of instructions represented
230// as a double linked list. Each block knows its predecessors and
231// successors.
232class HBasicBlock : public ArenaObject {
233 public:
234 explicit HBasicBlock(HGraph* graph)
235 : graph_(graph),
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000236 predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
237 successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000238 loop_information_(nullptr),
239 dominator_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100240 block_id_(-1),
241 lifetime_start_(kNoLifetime),
242 lifetime_end_(kNoLifetime) {}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000243
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100244 const GrowableArray<HBasicBlock*>& GetPredecessors() const {
245 return predecessors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000246 }
247
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100248 const GrowableArray<HBasicBlock*>& GetSuccessors() const {
249 return successors_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000250 }
251
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000252 void AddBackEdge(HBasicBlock* back_edge) {
253 if (loop_information_ == nullptr) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000254 loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000255 }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100256 DCHECK_EQ(loop_information_->GetHeader(), this);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000257 loop_information_->AddBackEdge(back_edge);
258 }
259
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000260 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000261
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000262 int GetBlockId() const { return block_id_; }
263 void SetBlockId(int id) { block_id_ = id; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000264
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000265 HBasicBlock* GetDominator() const { return dominator_; }
266 void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000267
268 int NumberOfBackEdges() const {
269 return loop_information_ == nullptr
270 ? 0
271 : loop_information_->NumberOfBackEdges();
272 }
273
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100274 HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
275 HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100276 const HInstructionList& GetInstructions() const { return instructions_; }
277 const HInstructionList& GetPhis() const { return phis_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000278
279 void AddSuccessor(HBasicBlock* block) {
280 successors_.Add(block);
281 block->predecessors_.Add(this);
282 }
283
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100284 void RemovePredecessor(HBasicBlock* block, bool remove_in_successor = true) {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000285 predecessors_.Delete(block);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100286 if (remove_in_successor) {
287 block->successors_.Delete(this);
288 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000289 }
290
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100291 void RemoveSuccessor(HBasicBlock* block, bool remove_in_predecessor = true) {
292 successors_.Delete(block);
293 if (remove_in_predecessor) {
294 block->predecessors_.Delete(this);
295 }
296 }
297
298 void ClearAllPredecessors() {
299 predecessors_.Reset();
300 }
301
302 void AddPredecessor(HBasicBlock* block) {
303 predecessors_.Add(block);
304 block->successors_.Add(this);
305 }
306
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100307 size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
308 for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
309 if (predecessors_.Get(i) == predecessor) {
310 return i;
311 }
312 }
313 return -1;
314 }
315
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000316 void AddInstruction(HInstruction* instruction);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100317 void RemoveInstruction(HInstruction* instruction);
318 void AddPhi(HPhi* phi);
319 void RemovePhi(HPhi* phi);
320
321 bool IsLoopHeader() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100322 return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100323 }
324
325 HLoopInformation* GetLoopInformation() const {
326 return loop_information_;
327 }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000328
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100329 // Set the loop_information_ on this block. This method overrides the current
330 // loop_information if it is an outer loop of the passed loop information.
331 void SetInLoop(HLoopInformation* info) {
332 if (IsLoopHeader()) {
333 // Nothing to do. This just means `info` is an outer loop.
334 } else if (loop_information_ == nullptr) {
335 loop_information_ = info;
336 } else if (loop_information_->Contains(*info->GetHeader())) {
337 // Block is currently part of an outer loop. Make it part of this inner loop.
338 // Note that a non loop header having a loop information means this loop information
339 // has already been populated
340 loop_information_ = info;
341 } else {
342 // Block is part of an inner loop. Do not update the loop information.
343 // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
344 // at this point, because this method is being called while populating `info`.
345 }
346 }
347
348 // Returns wheter this block dominates the blocked passed as parameter.
349 bool Dominates(HBasicBlock* block) const;
350
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100351 size_t GetLifetimeStart() const { return lifetime_start_; }
352 size_t GetLifetimeEnd() const { return lifetime_end_; }
353
354 void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
355 void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
356
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000357 private:
358 HGraph* const graph_;
359 GrowableArray<HBasicBlock*> predecessors_;
360 GrowableArray<HBasicBlock*> successors_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100361 HInstructionList instructions_;
362 HInstructionList phis_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000363 HLoopInformation* loop_information_;
364 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000365 int block_id_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100366 size_t lifetime_start_;
367 size_t lifetime_end_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000368
369 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
370};
371
372#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000373 M(Add) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000374 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000375 M(Exit) \
376 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000377 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000378 M(IntConstant) \
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000379 M(InvokeStatic) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000380 M(LoadLocal) \
381 M(Local) \
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100382 M(LongConstant) \
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100383 M(NewInstance) \
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +0100384 M(Not) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100385 M(ParameterValue) \
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100386 M(Phi) \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000387 M(Return) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000388 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000389 M(StoreLocal) \
Nicolas Geoffrayf583e592014-04-07 13:20:42 +0100390 M(Sub) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000391
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000392#define FORWARD_DECLARATION(type) class H##type;
393FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
394#undef FORWARD_DECLARATION
395
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000396#define DECLARE_INSTRUCTION(type) \
397 virtual void Accept(HGraphVisitor* visitor); \
398 virtual const char* DebugName() const { return #type; } \
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000399 virtual H##type* As##type() { return this; } \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000400
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100401template <typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000402class HUseListNode : public ArenaObject {
403 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100404 HUseListNode(T* user, size_t index, HUseListNode* tail)
405 : user_(user), index_(index), tail_(tail) { }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000406
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000407 HUseListNode* GetTail() const { return tail_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100408 T* GetUser() const { return user_; }
409 size_t GetIndex() const { return index_; }
410
411 void SetTail(HUseListNode<T>* node) { tail_ = node; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000412
413 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100414 T* const user_;
415 const size_t index_;
416 HUseListNode<T>* tail_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000417
418 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
419};
420
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000421class HInstruction : public ArenaObject {
422 public:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000423 HInstruction()
424 : previous_(nullptr),
425 next_(nullptr),
426 block_(nullptr),
427 id_(-1),
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100428 ssa_index_(-1),
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000429 uses_(nullptr),
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100430 env_uses_(nullptr),
431 environment_(nullptr),
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100432 locations_(nullptr),
433 live_interval_(nullptr),
434 lifetime_position_(kNoLifetime) {}
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000435
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000436 virtual ~HInstruction() { }
437
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000438 HInstruction* GetNext() const { return next_; }
439 HInstruction* GetPrevious() const { return previous_; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000440
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000441 HBasicBlock* GetBlock() const { return block_; }
442 void SetBlock(HBasicBlock* block) { block_ = block; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000443
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100444 virtual size_t InputCount() const = 0;
445 virtual HInstruction* InputAt(size_t i) const = 0;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000446
447 virtual void Accept(HGraphVisitor* visitor) = 0;
448 virtual const char* DebugName() const = 0;
449
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100450 virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100451 virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100452
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100453 virtual bool NeedsEnvironment() const { return false; }
454
455 void AddUseAt(HInstruction* user, size_t index) {
456 uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000457 }
458
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100459 void AddEnvUseAt(HEnvironment* user, size_t index) {
460 env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
461 user, index, env_uses_);
462 }
463
464 void RemoveUser(HInstruction* user, size_t index);
465
466 HUseListNode<HInstruction>* GetUses() const { return uses_; }
467 HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000468
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100469 bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000470
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100471 size_t NumberOfUses() const {
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100472 // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100473 size_t result = 0;
474 HUseListNode<HInstruction>* current = uses_;
475 while (current != nullptr) {
476 current = current->GetTail();
477 ++result;
478 }
479 return result;
480 }
481
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000482 int GetId() const { return id_; }
483 void SetId(int id) { id_ = id; }
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000484
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100485 int GetSsaIndex() const { return ssa_index_; }
486 void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
487 bool HasSsaIndex() const { return ssa_index_ != -1; }
488
489 bool HasEnvironment() const { return environment_ != nullptr; }
490 HEnvironment* GetEnvironment() const { return environment_; }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100491 void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
492
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000493 LocationSummary* GetLocations() const { return locations_; }
494 void SetLocations(LocationSummary* locations) { locations_ = locations; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000495
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100496 void ReplaceWith(HInstruction* instruction);
497
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000498#define INSTRUCTION_TYPE_CHECK(type) \
499 virtual H##type* As##type() { return nullptr; }
500
501 FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
502#undef INSTRUCTION_TYPE_CHECK
503
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100504 size_t GetLifetimePosition() const { return lifetime_position_; }
505 void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
506 LiveInterval* GetLiveInterval() const { return live_interval_; }
507 void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
508 bool HasLiveInterval() const { return live_interval_ != nullptr; }
509
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000510 private:
511 HInstruction* previous_;
512 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000513 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000514
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000515 // An instruction gets an id when it is added to the graph.
516 // It reflects creation order. A negative id means the instruction
517 // has not beed added to the graph.
518 int id_;
519
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100520 // When doing liveness analysis, instructions that have uses get an SSA index.
521 int ssa_index_;
522
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100523 // List of instructions that have this instruction as input.
524 HUseListNode<HInstruction>* uses_;
525
526 // List of environments that contain this instruction.
527 HUseListNode<HEnvironment>* env_uses_;
528
529 HEnvironment* environment_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000530
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000531 // Set by the code generator.
532 LocationSummary* locations_;
533
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100534 // Set by the liveness analysis.
535 LiveInterval* live_interval_;
536
537 // Set by the liveness analysis, this is the position in a linear
538 // order of blocks where this instruction's live interval start.
539 size_t lifetime_position_;
540
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000541 friend class HBasicBlock;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100542 friend class HInstructionList;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000543
544 DISALLOW_COPY_AND_ASSIGN(HInstruction);
545};
546
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100547template<typename T>
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000548class HUseIterator : public ValueObject {
549 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100550 explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000551
552 bool Done() const { return current_ == nullptr; }
553
554 void Advance() {
555 DCHECK(!Done());
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000556 current_ = current_->GetTail();
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000557 }
558
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100559 HUseListNode<T>* Current() const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000560 DCHECK(!Done());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100561 return current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000562 }
563
564 private:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100565 HUseListNode<T>* current_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000566
567 friend class HValue;
568};
569
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100570// A HEnvironment object contains the values of virtual registers at a given location.
571class HEnvironment : public ArenaObject {
572 public:
573 HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
574 vregs_.SetSize(number_of_vregs);
575 for (size_t i = 0; i < number_of_vregs; i++) {
576 vregs_.Put(i, nullptr);
577 }
578 }
579
580 void Populate(const GrowableArray<HInstruction*>& env) {
581 for (size_t i = 0; i < env.Size(); i++) {
582 HInstruction* instruction = env.Get(i);
583 vregs_.Put(i, instruction);
584 if (instruction != nullptr) {
585 instruction->AddEnvUseAt(this, i);
586 }
587 }
588 }
589
590 void SetRawEnvAt(size_t index, HInstruction* instruction) {
591 vregs_.Put(index, instruction);
592 }
593
594 GrowableArray<HInstruction*>* GetVRegs() {
595 return &vregs_;
596 }
597
598 private:
599 GrowableArray<HInstruction*> vregs_;
600
601 DISALLOW_COPY_AND_ASSIGN(HEnvironment);
602};
603
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000604class HInputIterator : public ValueObject {
605 public:
606 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
607
608 bool Done() const { return index_ == instruction_->InputCount(); }
609 HInstruction* Current() const { return instruction_->InputAt(index_); }
610 void Advance() { index_++; }
611
612 private:
613 HInstruction* instruction_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100614 size_t index_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000615
616 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
617};
618
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000619class HInstructionIterator : public ValueObject {
620 public:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100621 explicit HInstructionIterator(const HInstructionList& instructions)
622 : instruction_(instructions.first_instruction_) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000623 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000624 }
625
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000626 bool Done() const { return instruction_ == nullptr; }
627 HInstruction* Current() const { return instruction_; }
628 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000629 instruction_ = next_;
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000630 next_ = Done() ? nullptr : instruction_->GetNext();
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000631 }
632
633 private:
634 HInstruction* instruction_;
635 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100636
637 DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000638};
639
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100640class HBackwardInstructionIterator : public ValueObject {
641 public:
642 explicit HBackwardInstructionIterator(const HInstructionList& instructions)
643 : instruction_(instructions.last_instruction_) {
644 next_ = Done() ? nullptr : instruction_->GetPrevious();
645 }
646
647 bool Done() const { return instruction_ == nullptr; }
648 HInstruction* Current() const { return instruction_; }
649 void Advance() {
650 instruction_ = next_;
651 next_ = Done() ? nullptr : instruction_->GetPrevious();
652 }
653
654 private:
655 HInstruction* instruction_;
656 HInstruction* next_;
Nicolas Geoffrayddb311f2014-05-16 09:28:54 +0100657
658 DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100659};
660
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000661// An embedded container with N elements of type T. Used (with partial
662// specialization for N=0) because embedded arrays cannot have size 0.
663template<typename T, intptr_t N>
664class EmbeddedArray {
665 public:
666 EmbeddedArray() : elements_() { }
667
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000668 intptr_t GetLength() const { return N; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000669
670 const T& operator[](intptr_t i) const {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000671 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000672 return elements_[i];
673 }
674
675 T& operator[](intptr_t i) {
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000676 DCHECK_LT(i, GetLength());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000677 return elements_[i];
678 }
679
680 const T& At(intptr_t i) const {
681 return (*this)[i];
682 }
683
684 void SetAt(intptr_t i, const T& val) {
685 (*this)[i] = val;
686 }
687
688 private:
689 T elements_[N];
690};
691
692template<typename T>
693class EmbeddedArray<T, 0> {
694 public:
695 intptr_t length() const { return 0; }
696 const T& operator[](intptr_t i) const {
697 LOG(FATAL) << "Unreachable";
698 static T sentinel = 0;
699 return sentinel;
700 }
701 T& operator[](intptr_t i) {
702 LOG(FATAL) << "Unreachable";
703 static T sentinel = 0;
704 return sentinel;
705 }
706};
707
708template<intptr_t N>
709class HTemplateInstruction: public HInstruction {
710 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000711 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000712 virtual ~HTemplateInstruction() { }
713
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100714 virtual size_t InputCount() const { return N; }
715 virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000716
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000717 protected:
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100718 virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000719 inputs_[i] = instruction;
720 }
721
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000722 private:
723 EmbeddedArray<HInstruction*, N> inputs_;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100724
725 friend class SsaBuilder;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000726};
727
728// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
729// instruction that branches to the exit block.
730class HReturnVoid : public HTemplateInstruction<0> {
731 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000732 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000733
734 DECLARE_INSTRUCTION(ReturnVoid)
735
736 private:
737 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
738};
739
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000740// Represents dex's RETURN opcodes. A HReturn is a control flow
741// instruction that branches to the exit block.
742class HReturn : public HTemplateInstruction<1> {
743 public:
744 explicit HReturn(HInstruction* value) {
745 SetRawInputAt(0, value);
746 }
747
748 DECLARE_INSTRUCTION(Return)
749
750 private:
751 DISALLOW_COPY_AND_ASSIGN(HReturn);
752};
753
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000754// The exit instruction is the only instruction of the exit block.
755// Instructions aborting the method (HTrow and HReturn) must branch to the
756// exit block.
757class HExit : public HTemplateInstruction<0> {
758 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000759 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000760
761 DECLARE_INSTRUCTION(Exit)
762
763 private:
764 DISALLOW_COPY_AND_ASSIGN(HExit);
765};
766
767// Jumps from one block to another.
768class HGoto : public HTemplateInstruction<0> {
769 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000770 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000771
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000772 HBasicBlock* GetSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100773 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000774 }
775
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000776 DECLARE_INSTRUCTION(Goto)
777
778 private:
779 DISALLOW_COPY_AND_ASSIGN(HGoto);
780};
781
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000782// Conditional branch. A block ending with an HIf instruction must have
783// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000784class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000785 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000786 explicit HIf(HInstruction* input) {
787 SetRawInputAt(0, input);
788 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000789
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000790 HBasicBlock* IfTrueSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100791 return GetBlock()->GetSuccessors().Get(0);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000792 }
793
794 HBasicBlock* IfFalseSuccessor() const {
Nicolas Geoffray622d9c32014-05-12 16:11:02 +0100795 return GetBlock()->GetSuccessors().Get(1);
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000796 }
797
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000798 DECLARE_INSTRUCTION(If)
799
800 private:
801 DISALLOW_COPY_AND_ASSIGN(HIf);
802};
803
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000804class HBinaryOperation : public HTemplateInstruction<2> {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000805 public:
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000806 HBinaryOperation(Primitive::Type result_type,
807 HInstruction* left,
808 HInstruction* right) : result_type_(result_type) {
809 SetRawInputAt(0, left);
810 SetRawInputAt(1, right);
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000811 }
812
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000813 HInstruction* GetLeft() const { return InputAt(0); }
814 HInstruction* GetRight() const { return InputAt(1); }
815 Primitive::Type GetResultType() const { return result_type_; }
816
817 virtual bool IsCommutative() { return false; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100818 virtual Primitive::Type GetType() const { return GetResultType(); }
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +0000819
820 private:
821 const Primitive::Type result_type_;
822
823 DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
824};
825
826
827// Instruction to check if two inputs are equal to each other.
828class HEqual : public HBinaryOperation {
829 public:
830 HEqual(HInstruction* first, HInstruction* second)
831 : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
832
833 virtual bool IsCommutative() { return true; }
834
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100835 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
836
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000837 DECLARE_INSTRUCTION(Equal)
838
839 private:
840 DISALLOW_COPY_AND_ASSIGN(HEqual);
841};
842
843// A local in the graph. Corresponds to a Dex register.
844class HLocal : public HTemplateInstruction<0> {
845 public:
846 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
847
848 DECLARE_INSTRUCTION(Local)
849
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000850 uint16_t GetRegNumber() const { return reg_number_; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000851
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000852 private:
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000853 // The Dex register number.
854 const uint16_t reg_number_;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000855
856 DISALLOW_COPY_AND_ASSIGN(HLocal);
857};
858
859// Load a given local. The local is an input of this instruction.
860class HLoadLocal : public HTemplateInstruction<1> {
861 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100862 explicit HLoadLocal(HLocal* local, Primitive::Type type) : type_(type) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000863 SetRawInputAt(0, local);
864 }
865
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100866 virtual Primitive::Type GetType() const { return type_; }
867
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000868 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
869
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000870 DECLARE_INSTRUCTION(LoadLocal)
871
872 private:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100873 const Primitive::Type type_;
874
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000875 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
876};
877
878// Store a value in a given local. This instruction has two inputs: the value
879// and the local.
880class HStoreLocal : public HTemplateInstruction<2> {
881 public:
882 HStoreLocal(HLocal* local, HInstruction* value) {
883 SetRawInputAt(0, local);
884 SetRawInputAt(1, value);
885 }
886
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000887 HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
888
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000889 DECLARE_INSTRUCTION(StoreLocal)
890
891 private:
892 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
893};
894
895// Constants of the type int. Those can be from Dex instructions, or
896// synthesized (for example with the if-eqz instruction).
897class HIntConstant : public HTemplateInstruction<0> {
898 public:
899 explicit HIntConstant(int32_t value) : value_(value) { }
900
Nicolas Geoffray787c3072014-03-17 10:20:19 +0000901 int32_t GetValue() const { return value_; }
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100902 virtual Primitive::Type GetType() const { return Primitive::kPrimInt; }
Nicolas Geoffraybab4ed72014-03-11 17:53:17 +0000903
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000904 DECLARE_INSTRUCTION(IntConstant)
905
906 private:
907 const int32_t value_;
908
909 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
910};
911
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100912class HLongConstant : public HTemplateInstruction<0> {
913 public:
914 explicit HLongConstant(int64_t value) : value_(value) { }
915
916 int64_t GetValue() const { return value_; }
917
918 virtual Primitive::Type GetType() const { return Primitive::kPrimLong; }
919
920 DECLARE_INSTRUCTION(LongConstant)
921
922 private:
923 const int64_t value_;
924
925 DISALLOW_COPY_AND_ASSIGN(HLongConstant);
926};
927
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000928class HInvoke : public HInstruction {
929 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100930 HInvoke(ArenaAllocator* arena,
931 uint32_t number_of_arguments,
932 Primitive::Type return_type,
933 uint32_t dex_pc)
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000934 : inputs_(arena, number_of_arguments),
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100935 return_type_(return_type),
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000936 dex_pc_(dex_pc) {
937 inputs_.SetSize(number_of_arguments);
938 }
939
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100940 virtual size_t InputCount() const { return inputs_.Size(); }
941 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
942
943 // Runtime needs to walk the stack, so Dex -> Dex calls need to
944 // know their environment.
945 virtual bool NeedsEnvironment() const { return true; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000946
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100947 void SetArgumentAt(size_t index, HInstruction* argument) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100948 SetRawInputAt(index, argument);
949 }
950
951 virtual void SetRawInputAt(size_t index, HInstruction* input) {
952 inputs_.Put(index, input);
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100953 }
954
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100955 virtual Primitive::Type GetType() const { return return_type_; }
956
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100957 uint32_t GetDexPc() const { return dex_pc_; }
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000958
959 protected:
960 GrowableArray<HInstruction*> inputs_;
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100961 const Primitive::Type return_type_;
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100962 const uint32_t dex_pc_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000963
964 private:
965 DISALLOW_COPY_AND_ASSIGN(HInvoke);
966};
967
968class HInvokeStatic : public HInvoke {
969 public:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100970 HInvokeStatic(ArenaAllocator* arena,
971 uint32_t number_of_arguments,
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100972 Primitive::Type return_type,
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100973 uint32_t dex_pc,
974 uint32_t index_in_dex_cache)
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100975 : HInvoke(arena, number_of_arguments, return_type, dex_pc),
976 index_in_dex_cache_(index_in_dex_cache) {}
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000977
978 uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
979
980 DECLARE_INSTRUCTION(InvokeStatic)
981
982 private:
Nicolas Geoffray4a34a422014-04-03 10:38:37 +0100983 const uint32_t index_in_dex_cache_;
Nicolas Geoffray8ccc3f52014-03-19 10:34:11 +0000984
985 DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
986};
987
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +0100988class HNewInstance : public HTemplateInstruction<0> {
989 public:
990 HNewInstance(uint32_t dex_pc, uint16_t type_index) : dex_pc_(dex_pc), type_index_(type_index) {}
991
992 uint32_t GetDexPc() const { return dex_pc_; }
993 uint16_t GetTypeIndex() const { return type_index_; }
994
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +0100995 virtual Primitive::Type GetType() const { return Primitive::kPrimNot; }
996
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100997 // Calls runtime so needs an environment.
998 virtual bool NeedsEnvironment() const { return true; }
999
Nicolas Geoffray2e7038a2014-04-03 18:49:58 +01001000 DECLARE_INSTRUCTION(NewInstance)
1001
1002 private:
1003 const uint32_t dex_pc_;
1004 const uint16_t type_index_;
1005
1006 DISALLOW_COPY_AND_ASSIGN(HNewInstance);
1007};
1008
Nicolas Geoffrayd8ee7372014-03-28 15:43:40 +00001009class HAdd : public HBinaryOperation {
1010 public:
1011 HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1012 : HBinaryOperation(result_type, left, right) {}
1013
1014 virtual bool IsCommutative() { return true; }
1015
1016 DECLARE_INSTRUCTION(Add);
1017
1018 private:
1019 DISALLOW_COPY_AND_ASSIGN(HAdd);
1020};
1021
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001022class HSub : public HBinaryOperation {
1023 public:
1024 HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1025 : HBinaryOperation(result_type, left, right) {}
1026
1027 virtual bool IsCommutative() { return false; }
1028
1029 DECLARE_INSTRUCTION(Sub);
1030
1031 private:
1032 DISALLOW_COPY_AND_ASSIGN(HSub);
1033};
1034
1035// The value of a parameter in this method. Its location depends on
1036// the calling convention.
1037class HParameterValue : public HTemplateInstruction<0> {
1038 public:
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001039 HParameterValue(uint8_t index, Primitive::Type parameter_type)
1040 : index_(index), parameter_type_(parameter_type) {}
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001041
1042 uint8_t GetIndex() const { return index_; }
1043
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001044 virtual Primitive::Type GetType() const { return parameter_type_; }
1045
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001046 DECLARE_INSTRUCTION(ParameterValue);
1047
1048 private:
1049 // The index of this parameter in the parameters list. Must be less
1050 // than HGraph::number_of_in_vregs_;
1051 const uint8_t index_;
1052
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001053 const Primitive::Type parameter_type_;
1054
Nicolas Geoffrayf583e592014-04-07 13:20:42 +01001055 DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1056};
1057
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001058class HNot : public HTemplateInstruction<1> {
1059 public:
1060 explicit HNot(HInstruction* input) {
1061 SetRawInputAt(0, input);
1062 }
1063
Nicolas Geoffray01bc96d2014-04-11 17:43:50 +01001064 virtual Primitive::Type GetType() const { return Primitive::kPrimBoolean; }
1065
Nicolas Geoffrayb55f8352014-04-07 15:26:35 +01001066 DECLARE_INSTRUCTION(Not);
1067
1068 private:
1069 DISALLOW_COPY_AND_ASSIGN(HNot);
1070};
1071
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001072class HPhi : public HInstruction {
1073 public:
1074 HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
1075 : inputs_(arena, number_of_inputs),
1076 reg_number_(reg_number),
1077 type_(type) {
1078 inputs_.SetSize(number_of_inputs);
1079 }
1080
1081 virtual size_t InputCount() const { return inputs_.Size(); }
1082 virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1083
1084 virtual void SetRawInputAt(size_t index, HInstruction* input) {
1085 inputs_.Put(index, input);
1086 }
1087
1088 void AddInput(HInstruction* input);
1089
1090 virtual Primitive::Type GetType() const { return type_; }
1091
1092 uint32_t GetRegNumber() const { return reg_number_; }
1093
1094 DECLARE_INSTRUCTION(Phi)
1095
1096 protected:
1097 GrowableArray<HInstruction*> inputs_;
1098 const uint32_t reg_number_;
1099 const Primitive::Type type_;
1100
1101 private:
1102 DISALLOW_COPY_AND_ASSIGN(HPhi);
1103};
1104
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001105class HGraphVisitor : public ValueObject {
1106 public:
1107 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
1108 virtual ~HGraphVisitor() { }
1109
1110 virtual void VisitInstruction(HInstruction* instruction) { }
1111 virtual void VisitBasicBlock(HBasicBlock* block);
1112
1113 void VisitInsertionOrder();
1114
Nicolas Geoffray787c3072014-03-17 10:20:19 +00001115 HGraph* GetGraph() const { return graph_; }
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +00001116
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001117 // Visit functions for instruction classes.
1118#define DECLARE_VISIT_INSTRUCTION(name) \
1119 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
1120
1121 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
1122
1123#undef DECLARE_VISIT_INSTRUCTION
1124
1125 private:
1126 HGraph* graph_;
1127
1128 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
1129};
1130
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001131class HInsertionOrderIterator : public ValueObject {
1132 public:
1133 explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1134
1135 bool Done() const { return index_ == graph_.GetBlocks().Size(); }
1136 HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
1137 void Advance() { ++index_; }
1138
1139 private:
1140 const HGraph& graph_;
1141 size_t index_;
1142
1143 DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
1144};
1145
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001146class HReversePostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001147 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001148 explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001149
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001150 bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
1151 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001152 void Advance() { ++index_; }
1153
1154 private:
1155 const HGraph& graph_;
1156 size_t index_;
1157
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001158 DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001159};
1160
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001161class HPostOrderIterator : public ValueObject {
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001162 public:
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001163 explicit HPostOrderIterator(const HGraph& graph)
1164 : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001165
1166 bool Done() const { return index_ == 0; }
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001167 HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001168 void Advance() { --index_; }
1169
1170 private:
1171 const HGraph& graph_;
1172 size_t index_;
1173
Nicolas Geoffray622d9c32014-05-12 16:11:02 +01001174 DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
Nicolas Geoffray804d0932014-05-02 08:46:00 +01001175};
1176
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001177} // namespace art
1178
1179#endif // ART_COMPILER_OPTIMIZING_NODES_H_