blob: bb08bd0e9ad099e94d96148a9d0ee8fad34cf497 [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_NODES_H_
18#define ART_COMPILER_OPTIMIZING_NODES_H_
19
20#include "utils/allocation.h"
Nicolas Geoffray0e336432014-02-26 18:24:38 +000021#include "utils/arena_bit_vector.h"
Nicolas Geoffray818f2102014-02-18 16:43:35 +000022#include "utils/growable_array.h"
23
24namespace art {
25
26class HBasicBlock;
27class HInstruction;
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000028class HIntConstant;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000029class HGraphVisitor;
30
31static const int kDefaultNumberOfBlocks = 8;
32static const int kDefaultNumberOfSuccessors = 2;
33static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000034static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000035
36// Control-flow graph of a method. Contains a list of basic blocks.
37class HGraph : public ArenaObject {
38 public:
39 explicit HGraph(ArenaAllocator* arena)
40 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000041 blocks_(arena, kDefaultNumberOfBlocks),
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000042 dominator_order_(arena, kDefaultNumberOfBlocks),
43 current_instruction_id_(0) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000044
45 ArenaAllocator* arena() const { return arena_; }
46 const GrowableArray<HBasicBlock*>* blocks() const { return &blocks_; }
47
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000048 HBasicBlock* entry_block() const { return entry_block_; }
49 HBasicBlock* exit_block() const { return exit_block_; }
50
51 void set_entry_block(HBasicBlock* block) { entry_block_ = block; }
52 void set_exit_block(HBasicBlock* block) { exit_block_ = block; }
53
Nicolas Geoffray818f2102014-02-18 16:43:35 +000054 void AddBlock(HBasicBlock* block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000055 void BuildDominatorTree();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000056
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000057 int GetNextInstructionId() {
58 return current_instruction_id_++;
59 }
60
Nicolas Geoffray818f2102014-02-18 16:43:35 +000061 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
63 void VisitBlockForDominatorTree(HBasicBlock* block,
64 HBasicBlock* predecessor,
65 GrowableArray<size_t>* visits);
66 void FindBackEdges(ArenaBitVector* visited) const;
67 void VisitBlockForBackEdges(HBasicBlock* block,
68 ArenaBitVector* visited,
69 ArenaBitVector* visiting) const;
70 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
71
Nicolas Geoffray818f2102014-02-18 16:43:35 +000072 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000073
74 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +000075 GrowableArray<HBasicBlock*> blocks_;
76
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000077 // List of blocks to perform a pre-order dominator tree traversal.
78 GrowableArray<HBasicBlock*> dominator_order_;
79
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000080 HBasicBlock* entry_block_;
81 HBasicBlock* exit_block_;
82
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +000083 // The current id to assign to a newly added instruction. See HInstruction.id_.
84 int current_instruction_id_;
85
Nicolas Geoffray818f2102014-02-18 16:43:35 +000086 DISALLOW_COPY_AND_ASSIGN(HGraph);
87};
88
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000089class HLoopInformation : public ArenaObject {
90 public:
91 HLoopInformation(HBasicBlock* header, HGraph* graph)
92 : header_(header),
93 back_edges_(graph->arena(), kDefaultNumberOfBackEdges) { }
94
95 void AddBackEdge(HBasicBlock* back_edge) {
96 back_edges_.Add(back_edge);
97 }
98
99 int NumberOfBackEdges() const {
100 return back_edges_.Size();
101 }
102
103 private:
104 HBasicBlock* header_;
105 GrowableArray<HBasicBlock*> back_edges_;
106
107 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
108};
109
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000110// A block in a method. Contains the list of instructions represented
111// as a double linked list. Each block knows its predecessors and
112// successors.
113class HBasicBlock : public ArenaObject {
114 public:
115 explicit HBasicBlock(HGraph* graph)
116 : graph_(graph),
117 predecessors_(graph->arena(), kDefaultNumberOfPredecessors),
118 successors_(graph->arena(), kDefaultNumberOfSuccessors),
119 first_instruction_(nullptr),
120 last_instruction_(nullptr),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000121 loop_information_(nullptr),
122 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000123 block_id_(-1) { }
124
125 const GrowableArray<HBasicBlock*>* predecessors() const {
126 return &predecessors_;
127 }
128
129 const GrowableArray<HBasicBlock*>* successors() const {
130 return &successors_;
131 }
132
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000133 void AddBackEdge(HBasicBlock* back_edge) {
134 if (loop_information_ == nullptr) {
135 loop_information_ = new (graph_->arena()) HLoopInformation(this, graph_);
136 }
137 loop_information_->AddBackEdge(back_edge);
138 }
139
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000140 HGraph* graph() const { return graph_; }
141
142 int block_id() const { return block_id_; }
143 void set_block_id(int id) { block_id_ = id; }
144
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000145 HBasicBlock* dominator() const { return dominator_; }
146 void set_dominator(HBasicBlock* dominator) { dominator_ = dominator; }
147
148 int NumberOfBackEdges() const {
149 return loop_information_ == nullptr
150 ? 0
151 : loop_information_->NumberOfBackEdges();
152 }
153
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000154 HInstruction* first_instruction() const { return first_instruction_; }
155 HInstruction* last_instruction() const { return last_instruction_; }
156
157 void AddSuccessor(HBasicBlock* block) {
158 successors_.Add(block);
159 block->predecessors_.Add(this);
160 }
161
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000162 void RemovePredecessor(HBasicBlock* block) {
163 predecessors_.Delete(block);
164 }
165
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000166 void AddInstruction(HInstruction* instruction);
167
168 private:
169 HGraph* const graph_;
170 GrowableArray<HBasicBlock*> predecessors_;
171 GrowableArray<HBasicBlock*> successors_;
172 HInstruction* first_instruction_;
173 HInstruction* last_instruction_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000174 HLoopInformation* loop_information_;
175 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000176 int block_id_;
177
178 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
179};
180
181#define FOR_EACH_INSTRUCTION(M) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000182 M(Equal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000183 M(Exit) \
184 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000185 M(If) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000186 M(IntConstant) \
187 M(LoadLocal) \
188 M(Local) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000189 M(ReturnVoid) \
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000190 M(StoreLocal) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000191
192#define DECLARE_INSTRUCTION(type) \
193 virtual void Accept(HGraphVisitor* visitor); \
194 virtual const char* DebugName() const { return #type; } \
195
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000196class HUseListNode : public ArenaObject {
197 public:
198 HUseListNode(HInstruction* instruction, HUseListNode* tail)
199 : instruction_(instruction), tail_(tail) { }
200
201 HUseListNode* tail() const { return tail_; }
202 HInstruction* instruction() const { return instruction_; }
203
204 private:
205 HInstruction* const instruction_;
206 HUseListNode* const tail_;
207
208 DISALLOW_COPY_AND_ASSIGN(HUseListNode);
209};
210
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000211class HInstruction : public ArenaObject {
212 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000213 HInstruction() : previous_(nullptr), next_(nullptr), block_(nullptr), id_(-1), uses_(nullptr) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000214 virtual ~HInstruction() { }
215
216 HInstruction* next() const { return next_; }
217 HInstruction* previous() const { return previous_; }
218
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000219 HBasicBlock* block() const { return block_; }
220 void set_block(HBasicBlock* block) { block_ = block; }
221
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000222 virtual intptr_t InputCount() const = 0;
223 virtual HInstruction* InputAt(intptr_t i) const = 0;
224
225 virtual void Accept(HGraphVisitor* visitor) = 0;
226 virtual const char* DebugName() const = 0;
227
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000228 void AddUse(HInstruction* user) {
229 uses_ = new (block_->graph()->arena()) HUseListNode(user, uses_);
230 }
231
232 HUseListNode* uses() const { return uses_; }
233
234 bool HasUses() const { return uses_ != nullptr; }
235
236 int id() const { return id_; }
237 void set_id(int id) { id_ = id; }
238
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000239 private:
240 HInstruction* previous_;
241 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000242 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000243
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000244 // An instruction gets an id when it is added to the graph.
245 // It reflects creation order. A negative id means the instruction
246 // has not beed added to the graph.
247 int id_;
248
249 HUseListNode* uses_;
250
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000251 friend class HBasicBlock;
252
253 DISALLOW_COPY_AND_ASSIGN(HInstruction);
254};
255
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000256class HUseIterator : public ValueObject {
257 public:
258 explicit HUseIterator(HInstruction* instruction) : current_(instruction->uses()) { }
259
260 bool Done() const { return current_ == nullptr; }
261
262 void Advance() {
263 DCHECK(!Done());
264 current_ = current_->tail();
265 }
266
267 HInstruction* Current() const {
268 DCHECK(!Done());
269 return current_->instruction();
270 }
271
272 private:
273 HUseListNode* current_;
274
275 friend class HValue;
276};
277
278class HInputIterator : public ValueObject {
279 public:
280 explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) { }
281
282 bool Done() const { return index_ == instruction_->InputCount(); }
283 HInstruction* Current() const { return instruction_->InputAt(index_); }
284 void Advance() { index_++; }
285
286 private:
287 HInstruction* instruction_;
288 int index_;
289
290 DISALLOW_COPY_AND_ASSIGN(HInputIterator);
291};
292
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000293class HInstructionIterator : public ValueObject {
294 public:
295 explicit HInstructionIterator(HBasicBlock* block)
296 : instruction_(block->first_instruction()) {
297 next_ = Done() ? nullptr : instruction_->next();
298 }
299
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000300 bool Done() const { return instruction_ == nullptr; }
301 HInstruction* Current() const { return instruction_; }
302 void Advance() {
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000303 instruction_ = next_;
304 next_ = Done() ? nullptr : instruction_->next();
305 }
306
307 private:
308 HInstruction* instruction_;
309 HInstruction* next_;
310};
311
312// An embedded container with N elements of type T. Used (with partial
313// specialization for N=0) because embedded arrays cannot have size 0.
314template<typename T, intptr_t N>
315class EmbeddedArray {
316 public:
317 EmbeddedArray() : elements_() { }
318
319 intptr_t length() const { return N; }
320
321 const T& operator[](intptr_t i) const {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000322 DCHECK_LT(i, length());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000323 return elements_[i];
324 }
325
326 T& operator[](intptr_t i) {
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000327 DCHECK_LT(i, length());
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000328 return elements_[i];
329 }
330
331 const T& At(intptr_t i) const {
332 return (*this)[i];
333 }
334
335 void SetAt(intptr_t i, const T& val) {
336 (*this)[i] = val;
337 }
338
339 private:
340 T elements_[N];
341};
342
343template<typename T>
344class EmbeddedArray<T, 0> {
345 public:
346 intptr_t length() const { return 0; }
347 const T& operator[](intptr_t i) const {
348 LOG(FATAL) << "Unreachable";
349 static T sentinel = 0;
350 return sentinel;
351 }
352 T& operator[](intptr_t i) {
353 LOG(FATAL) << "Unreachable";
354 static T sentinel = 0;
355 return sentinel;
356 }
357};
358
359template<intptr_t N>
360class HTemplateInstruction: public HInstruction {
361 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000362 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000363 virtual ~HTemplateInstruction() { }
364
365 virtual intptr_t InputCount() const { return N; }
366 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
367
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000368 protected:
369 void SetRawInputAt(intptr_t i, HInstruction* instruction) {
370 inputs_[i] = instruction;
371 }
372
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000373 private:
374 EmbeddedArray<HInstruction*, N> inputs_;
375};
376
377// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
378// instruction that branches to the exit block.
379class HReturnVoid : public HTemplateInstruction<0> {
380 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000381 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000382
383 DECLARE_INSTRUCTION(ReturnVoid)
384
385 private:
386 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
387};
388
389// The exit instruction is the only instruction of the exit block.
390// Instructions aborting the method (HTrow and HReturn) must branch to the
391// exit block.
392class HExit : public HTemplateInstruction<0> {
393 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000394 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000395
396 DECLARE_INSTRUCTION(Exit)
397
398 private:
399 DISALLOW_COPY_AND_ASSIGN(HExit);
400};
401
402// Jumps from one block to another.
403class HGoto : public HTemplateInstruction<0> {
404 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000405 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000406
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000407 HBasicBlock* GetSuccessor() const {
408 return block()->successors()->Get(0);
409 }
410
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000411 DECLARE_INSTRUCTION(Goto)
412
413 private:
414 DISALLOW_COPY_AND_ASSIGN(HGoto);
415};
416
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000417// Conditional branch. A block ending with an HIf instruction must have
418// two successors.
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000419class HIf : public HTemplateInstruction<1> {
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000420 public:
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000421 explicit HIf(HInstruction* input) {
422 SetRawInputAt(0, input);
423 }
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000424
425 DECLARE_INSTRUCTION(If)
426
427 private:
428 DISALLOW_COPY_AND_ASSIGN(HIf);
429};
430
Nicolas Geoffray3ff386a2014-03-04 14:46:47 +0000431// Instruction to check if two inputs are equal to each other.
432class HEqual : public HTemplateInstruction<2> {
433 public:
434 HEqual(HInstruction* first, HInstruction* second) {
435 SetRawInputAt(0, first);
436 SetRawInputAt(1, second);
437 }
438
439 DECLARE_INSTRUCTION(Equal)
440
441 private:
442 DISALLOW_COPY_AND_ASSIGN(HEqual);
443};
444
445// A local in the graph. Corresponds to a Dex register.
446class HLocal : public HTemplateInstruction<0> {
447 public:
448 explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) { }
449
450 DECLARE_INSTRUCTION(Local)
451
452 private:
453 // The register number in Dex.
454 uint16_t reg_number_;
455
456 DISALLOW_COPY_AND_ASSIGN(HLocal);
457};
458
459// Load a given local. The local is an input of this instruction.
460class HLoadLocal : public HTemplateInstruction<1> {
461 public:
462 explicit HLoadLocal(HLocal* local) {
463 SetRawInputAt(0, local);
464 }
465
466 DECLARE_INSTRUCTION(LoadLocal)
467
468 private:
469 DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
470};
471
472// Store a value in a given local. This instruction has two inputs: the value
473// and the local.
474class HStoreLocal : public HTemplateInstruction<2> {
475 public:
476 HStoreLocal(HLocal* local, HInstruction* value) {
477 SetRawInputAt(0, local);
478 SetRawInputAt(1, value);
479 }
480
481 DECLARE_INSTRUCTION(StoreLocal)
482
483 private:
484 DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
485};
486
487// Constants of the type int. Those can be from Dex instructions, or
488// synthesized (for example with the if-eqz instruction).
489class HIntConstant : public HTemplateInstruction<0> {
490 public:
491 explicit HIntConstant(int32_t value) : value_(value) { }
492
493 DECLARE_INSTRUCTION(IntConstant)
494
495 private:
496 const int32_t value_;
497
498 DISALLOW_COPY_AND_ASSIGN(HIntConstant);
499};
500
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000501class HGraphVisitor : public ValueObject {
502 public:
503 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
504 virtual ~HGraphVisitor() { }
505
506 virtual void VisitInstruction(HInstruction* instruction) { }
507 virtual void VisitBasicBlock(HBasicBlock* block);
508
509 void VisitInsertionOrder();
510
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000511 HGraph* graph() const { return graph_; }
512
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000513 // Visit functions for instruction classes.
514#define DECLARE_VISIT_INSTRUCTION(name) \
515 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
516
517 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
518
519#undef DECLARE_VISIT_INSTRUCTION
520
521 private:
522 HGraph* graph_;
523
524 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
525};
526
527} // namespace art
528
529#endif // ART_COMPILER_OPTIMIZING_NODES_H_