blob: 46fe95e99f569916759d8fe36125fce189d1e2c8 [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;
28class HGraphVisitor;
29
30static const int kDefaultNumberOfBlocks = 8;
31static const int kDefaultNumberOfSuccessors = 2;
32static const int kDefaultNumberOfPredecessors = 2;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000033static const int kDefaultNumberOfBackEdges = 1;
Nicolas Geoffray818f2102014-02-18 16:43:35 +000034
35// Control-flow graph of a method. Contains a list of basic blocks.
36class HGraph : public ArenaObject {
37 public:
38 explicit HGraph(ArenaAllocator* arena)
39 : arena_(arena),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000040 blocks_(arena, kDefaultNumberOfBlocks),
41 dominator_order_(arena, kDefaultNumberOfBlocks) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000042
43 ArenaAllocator* arena() const { return arena_; }
44 const GrowableArray<HBasicBlock*>* blocks() const { return &blocks_; }
45
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000046 HBasicBlock* entry_block() const { return entry_block_; }
47 HBasicBlock* exit_block() const { return exit_block_; }
48
49 void set_entry_block(HBasicBlock* block) { entry_block_ = block; }
50 void set_exit_block(HBasicBlock* block) { exit_block_ = block; }
51
52
Nicolas Geoffray818f2102014-02-18 16:43:35 +000053 void AddBlock(HBasicBlock* block);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000054 void BuildDominatorTree();
Nicolas Geoffray818f2102014-02-18 16:43:35 +000055
56 private:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000057 HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
58 void VisitBlockForDominatorTree(HBasicBlock* block,
59 HBasicBlock* predecessor,
60 GrowableArray<size_t>* visits);
61 void FindBackEdges(ArenaBitVector* visited) const;
62 void VisitBlockForBackEdges(HBasicBlock* block,
63 ArenaBitVector* visited,
64 ArenaBitVector* visiting) const;
65 void RemoveDeadBlocks(const ArenaBitVector& visited) const;
66
Nicolas Geoffray818f2102014-02-18 16:43:35 +000067 ArenaAllocator* const arena_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000068
69 // List of blocks in insertion order.
Nicolas Geoffray818f2102014-02-18 16:43:35 +000070 GrowableArray<HBasicBlock*> blocks_;
71
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000072 // List of blocks to perform a pre-order dominator tree traversal.
73 GrowableArray<HBasicBlock*> dominator_order_;
74
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +000075 HBasicBlock* entry_block_;
76 HBasicBlock* exit_block_;
77
Nicolas Geoffray818f2102014-02-18 16:43:35 +000078 DISALLOW_COPY_AND_ASSIGN(HGraph);
79};
80
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000081class HLoopInformation : public ArenaObject {
82 public:
83 HLoopInformation(HBasicBlock* header, HGraph* graph)
84 : header_(header),
85 back_edges_(graph->arena(), kDefaultNumberOfBackEdges) { }
86
87 void AddBackEdge(HBasicBlock* back_edge) {
88 back_edges_.Add(back_edge);
89 }
90
91 int NumberOfBackEdges() const {
92 return back_edges_.Size();
93 }
94
95 private:
96 HBasicBlock* header_;
97 GrowableArray<HBasicBlock*> back_edges_;
98
99 DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
100};
101
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000102// A block in a method. Contains the list of instructions represented
103// as a double linked list. Each block knows its predecessors and
104// successors.
105class HBasicBlock : public ArenaObject {
106 public:
107 explicit HBasicBlock(HGraph* graph)
108 : graph_(graph),
109 predecessors_(graph->arena(), kDefaultNumberOfPredecessors),
110 successors_(graph->arena(), kDefaultNumberOfSuccessors),
111 first_instruction_(nullptr),
112 last_instruction_(nullptr),
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000113 loop_information_(nullptr),
114 dominator_(nullptr),
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000115 block_id_(-1) { }
116
117 const GrowableArray<HBasicBlock*>* predecessors() const {
118 return &predecessors_;
119 }
120
121 const GrowableArray<HBasicBlock*>* successors() const {
122 return &successors_;
123 }
124
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000125 void AddBackEdge(HBasicBlock* back_edge) {
126 if (loop_information_ == nullptr) {
127 loop_information_ = new (graph_->arena()) HLoopInformation(this, graph_);
128 }
129 loop_information_->AddBackEdge(back_edge);
130 }
131
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000132 HGraph* graph() const { return graph_; }
133
134 int block_id() const { return block_id_; }
135 void set_block_id(int id) { block_id_ = id; }
136
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000137 HBasicBlock* dominator() const { return dominator_; }
138 void set_dominator(HBasicBlock* dominator) { dominator_ = dominator; }
139
140 int NumberOfBackEdges() const {
141 return loop_information_ == nullptr
142 ? 0
143 : loop_information_->NumberOfBackEdges();
144 }
145
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000146 HInstruction* first_instruction() const { return first_instruction_; }
147 HInstruction* last_instruction() const { return last_instruction_; }
148
149 void AddSuccessor(HBasicBlock* block) {
150 successors_.Add(block);
151 block->predecessors_.Add(this);
152 }
153
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000154 void RemovePredecessor(HBasicBlock* block) {
155 predecessors_.Delete(block);
156 }
157
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000158 void AddInstruction(HInstruction* instruction);
159
160 private:
161 HGraph* const graph_;
162 GrowableArray<HBasicBlock*> predecessors_;
163 GrowableArray<HBasicBlock*> successors_;
164 HInstruction* first_instruction_;
165 HInstruction* last_instruction_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000166 HLoopInformation* loop_information_;
167 HBasicBlock* dominator_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000168 int block_id_;
169
170 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
171};
172
173#define FOR_EACH_INSTRUCTION(M) \
174 M(Exit) \
175 M(Goto) \
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000176 M(If) \
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000177 M(ReturnVoid) \
178
179#define DECLARE_INSTRUCTION(type) \
180 virtual void Accept(HGraphVisitor* visitor); \
181 virtual const char* DebugName() const { return #type; } \
182
183class HInstruction : public ArenaObject {
184 public:
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000185 HInstruction() : previous_(nullptr), next_(nullptr), block_(nullptr) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000186 virtual ~HInstruction() { }
187
188 HInstruction* next() const { return next_; }
189 HInstruction* previous() const { return previous_; }
190
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000191 HBasicBlock* block() const { return block_; }
192 void set_block(HBasicBlock* block) { block_ = block; }
193
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000194 virtual intptr_t InputCount() const = 0;
195 virtual HInstruction* InputAt(intptr_t i) const = 0;
196
197 virtual void Accept(HGraphVisitor* visitor) = 0;
198 virtual const char* DebugName() const = 0;
199
200 private:
201 HInstruction* previous_;
202 HInstruction* next_;
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000203 HBasicBlock* block_;
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000204
205 friend class HBasicBlock;
206
207 DISALLOW_COPY_AND_ASSIGN(HInstruction);
208};
209
210class HInstructionIterator : public ValueObject {
211 public:
212 explicit HInstructionIterator(HBasicBlock* block)
213 : instruction_(block->first_instruction()) {
214 next_ = Done() ? nullptr : instruction_->next();
215 }
216
217 inline bool Done() const { return instruction_ == nullptr; }
218 inline HInstruction* Current() { return instruction_; }
219 inline void Advance() {
220 instruction_ = next_;
221 next_ = Done() ? nullptr : instruction_->next();
222 }
223
224 private:
225 HInstruction* instruction_;
226 HInstruction* next_;
227};
228
229// An embedded container with N elements of type T. Used (with partial
230// specialization for N=0) because embedded arrays cannot have size 0.
231template<typename T, intptr_t N>
232class EmbeddedArray {
233 public:
234 EmbeddedArray() : elements_() { }
235
236 intptr_t length() const { return N; }
237
238 const T& operator[](intptr_t i) const {
239 ASSERT(i < length());
240 return elements_[i];
241 }
242
243 T& operator[](intptr_t i) {
244 ASSERT(i < length());
245 return elements_[i];
246 }
247
248 const T& At(intptr_t i) const {
249 return (*this)[i];
250 }
251
252 void SetAt(intptr_t i, const T& val) {
253 (*this)[i] = val;
254 }
255
256 private:
257 T elements_[N];
258};
259
260template<typename T>
261class EmbeddedArray<T, 0> {
262 public:
263 intptr_t length() const { return 0; }
264 const T& operator[](intptr_t i) const {
265 LOG(FATAL) << "Unreachable";
266 static T sentinel = 0;
267 return sentinel;
268 }
269 T& operator[](intptr_t i) {
270 LOG(FATAL) << "Unreachable";
271 static T sentinel = 0;
272 return sentinel;
273 }
274};
275
276template<intptr_t N>
277class HTemplateInstruction: public HInstruction {
278 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000279 HTemplateInstruction<N>() : inputs_() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000280 virtual ~HTemplateInstruction() { }
281
282 virtual intptr_t InputCount() const { return N; }
283 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
284
285 private:
286 EmbeddedArray<HInstruction*, N> inputs_;
287};
288
289// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
290// instruction that branches to the exit block.
291class HReturnVoid : public HTemplateInstruction<0> {
292 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000293 HReturnVoid() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000294
295 DECLARE_INSTRUCTION(ReturnVoid)
296
297 private:
298 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
299};
300
301// The exit instruction is the only instruction of the exit block.
302// Instructions aborting the method (HTrow and HReturn) must branch to the
303// exit block.
304class HExit : public HTemplateInstruction<0> {
305 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000306 HExit() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000307
308 DECLARE_INSTRUCTION(Exit)
309
310 private:
311 DISALLOW_COPY_AND_ASSIGN(HExit);
312};
313
314// Jumps from one block to another.
315class HGoto : public HTemplateInstruction<0> {
316 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000317 HGoto() { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000318
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000319 HBasicBlock* GetSuccessor() const {
320 return block()->successors()->Get(0);
321 }
322
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000323 DECLARE_INSTRUCTION(Goto)
324
325 private:
326 DISALLOW_COPY_AND_ASSIGN(HGoto);
327};
328
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +0000329// Conditional branch. A block ending with an HIf instruction must have
330// two successors.
331// TODO: Make it take an input.
332class HIf : public HTemplateInstruction<0> {
333 public:
334 HIf() { }
335
336 DECLARE_INSTRUCTION(If)
337
338 private:
339 DISALLOW_COPY_AND_ASSIGN(HIf);
340};
341
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000342class HGraphVisitor : public ValueObject {
343 public:
344 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
345 virtual ~HGraphVisitor() { }
346
347 virtual void VisitInstruction(HInstruction* instruction) { }
348 virtual void VisitBasicBlock(HBasicBlock* block);
349
350 void VisitInsertionOrder();
351
Nicolas Geoffrayd4dd2552014-02-28 10:23:58 +0000352 HGraph* graph() const { return graph_; }
353
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000354 // Visit functions for instruction classes.
355#define DECLARE_VISIT_INSTRUCTION(name) \
356 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
357
358 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
359
360#undef DECLARE_VISIT_INSTRUCTION
361
362 private:
363 HGraph* graph_;
364
365 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
366};
367
368} // namespace art
369
370#endif // ART_COMPILER_OPTIMIZING_NODES_H_