blob: 3d1c25e71b156892b2ec07c2f2fa93213f444b42 [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"
21#include "utils/growable_array.h"
22
23namespace art {
24
25class HBasicBlock;
26class HInstruction;
27class HGraphVisitor;
28
29static const int kDefaultNumberOfBlocks = 8;
30static const int kDefaultNumberOfSuccessors = 2;
31static const int kDefaultNumberOfPredecessors = 2;
32
33// Control-flow graph of a method. Contains a list of basic blocks.
34class HGraph : public ArenaObject {
35 public:
36 explicit HGraph(ArenaAllocator* arena)
37 : arena_(arena),
38 blocks_(arena, kDefaultNumberOfBlocks) { }
39
40 ArenaAllocator* arena() const { return arena_; }
41 const GrowableArray<HBasicBlock*>* blocks() const { return &blocks_; }
42
43 void AddBlock(HBasicBlock* block);
44
45 private:
46 ArenaAllocator* const arena_;
47 GrowableArray<HBasicBlock*> blocks_;
48
49 DISALLOW_COPY_AND_ASSIGN(HGraph);
50};
51
52// A block in a method. Contains the list of instructions represented
53// as a double linked list. Each block knows its predecessors and
54// successors.
55class HBasicBlock : public ArenaObject {
56 public:
57 explicit HBasicBlock(HGraph* graph)
58 : graph_(graph),
59 predecessors_(graph->arena(), kDefaultNumberOfPredecessors),
60 successors_(graph->arena(), kDefaultNumberOfSuccessors),
61 first_instruction_(nullptr),
62 last_instruction_(nullptr),
63 block_id_(-1) { }
64
65 const GrowableArray<HBasicBlock*>* predecessors() const {
66 return &predecessors_;
67 }
68
69 const GrowableArray<HBasicBlock*>* successors() const {
70 return &successors_;
71 }
72
73 HGraph* graph() const { return graph_; }
74
75 int block_id() const { return block_id_; }
76 void set_block_id(int id) { block_id_ = id; }
77
78 HInstruction* first_instruction() const { return first_instruction_; }
79 HInstruction* last_instruction() const { return last_instruction_; }
80
81 void AddSuccessor(HBasicBlock* block) {
82 successors_.Add(block);
83 block->predecessors_.Add(this);
84 }
85
86 void AddInstruction(HInstruction* instruction);
87
88 private:
89 HGraph* const graph_;
90 GrowableArray<HBasicBlock*> predecessors_;
91 GrowableArray<HBasicBlock*> successors_;
92 HInstruction* first_instruction_;
93 HInstruction* last_instruction_;
94 int block_id_;
95
96 DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
97};
98
99#define FOR_EACH_INSTRUCTION(M) \
100 M(Exit) \
101 M(Goto) \
102 M(ReturnVoid) \
103
104#define DECLARE_INSTRUCTION(type) \
105 virtual void Accept(HGraphVisitor* visitor); \
106 virtual const char* DebugName() const { return #type; } \
107
108class HInstruction : public ArenaObject {
109 public:
110 explicit HInstruction(HBasicBlock* block)
111 : previous_(nullptr),
112 next_(nullptr) { }
113 virtual ~HInstruction() { }
114
115 HInstruction* next() const { return next_; }
116 HInstruction* previous() const { return previous_; }
117
118 virtual intptr_t InputCount() const = 0;
119 virtual HInstruction* InputAt(intptr_t i) const = 0;
120
121 virtual void Accept(HGraphVisitor* visitor) = 0;
122 virtual const char* DebugName() const = 0;
123
124 private:
125 HInstruction* previous_;
126 HInstruction* next_;
127
128 friend class HBasicBlock;
129
130 DISALLOW_COPY_AND_ASSIGN(HInstruction);
131};
132
133class HInstructionIterator : public ValueObject {
134 public:
135 explicit HInstructionIterator(HBasicBlock* block)
136 : instruction_(block->first_instruction()) {
137 next_ = Done() ? nullptr : instruction_->next();
138 }
139
140 inline bool Done() const { return instruction_ == nullptr; }
141 inline HInstruction* Current() { return instruction_; }
142 inline void Advance() {
143 instruction_ = next_;
144 next_ = Done() ? nullptr : instruction_->next();
145 }
146
147 private:
148 HInstruction* instruction_;
149 HInstruction* next_;
150};
151
152// An embedded container with N elements of type T. Used (with partial
153// specialization for N=0) because embedded arrays cannot have size 0.
154template<typename T, intptr_t N>
155class EmbeddedArray {
156 public:
157 EmbeddedArray() : elements_() { }
158
159 intptr_t length() const { return N; }
160
161 const T& operator[](intptr_t i) const {
162 ASSERT(i < length());
163 return elements_[i];
164 }
165
166 T& operator[](intptr_t i) {
167 ASSERT(i < length());
168 return elements_[i];
169 }
170
171 const T& At(intptr_t i) const {
172 return (*this)[i];
173 }
174
175 void SetAt(intptr_t i, const T& val) {
176 (*this)[i] = val;
177 }
178
179 private:
180 T elements_[N];
181};
182
183template<typename T>
184class EmbeddedArray<T, 0> {
185 public:
186 intptr_t length() const { return 0; }
187 const T& operator[](intptr_t i) const {
188 LOG(FATAL) << "Unreachable";
189 static T sentinel = 0;
190 return sentinel;
191 }
192 T& operator[](intptr_t i) {
193 LOG(FATAL) << "Unreachable";
194 static T sentinel = 0;
195 return sentinel;
196 }
197};
198
199template<intptr_t N>
200class HTemplateInstruction: public HInstruction {
201 public:
202 HTemplateInstruction<N>(HBasicBlock* block)
203 : HInstruction(block),
204 inputs_() { }
205 virtual ~HTemplateInstruction() { }
206
207 virtual intptr_t InputCount() const { return N; }
208 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
209
210 private:
211 EmbeddedArray<HInstruction*, N> inputs_;
212};
213
214// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
215// instruction that branches to the exit block.
216class HReturnVoid : public HTemplateInstruction<0> {
217 public:
218 explicit HReturnVoid(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
219
220 DECLARE_INSTRUCTION(ReturnVoid)
221
222 private:
223 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
224};
225
226// The exit instruction is the only instruction of the exit block.
227// Instructions aborting the method (HTrow and HReturn) must branch to the
228// exit block.
229class HExit : public HTemplateInstruction<0> {
230 public:
231 explicit HExit(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
232
233 DECLARE_INSTRUCTION(Exit)
234
235 private:
236 DISALLOW_COPY_AND_ASSIGN(HExit);
237};
238
239// Jumps from one block to another.
240class HGoto : public HTemplateInstruction<0> {
241 public:
242 explicit HGoto(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
243
244 DECLARE_INSTRUCTION(Goto)
245
246 private:
247 DISALLOW_COPY_AND_ASSIGN(HGoto);
248};
249
250class HGraphVisitor : public ValueObject {
251 public:
252 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
253 virtual ~HGraphVisitor() { }
254
255 virtual void VisitInstruction(HInstruction* instruction) { }
256 virtual void VisitBasicBlock(HBasicBlock* block);
257
258 void VisitInsertionOrder();
259
260 // Visit functions for instruction classes.
261#define DECLARE_VISIT_INSTRUCTION(name) \
262 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
263
264 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
265
266#undef DECLARE_VISIT_INSTRUCTION
267
268 private:
269 HGraph* graph_;
270
271 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
272};
273
274} // namespace art
275
276#endif // ART_COMPILER_OPTIMIZING_NODES_H_