blob: 93656703610903a5073424c5c0b524d661cc73d7 [file] [log] [blame]
Nicolas Geoffray68a5fef2014-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
114 HInstruction* next() const { return next_; }
115 HInstruction* previous() const { return previous_; }
116
117 virtual intptr_t InputCount() const = 0;
118 virtual HInstruction* InputAt(intptr_t i) const = 0;
119
120 virtual void Accept(HGraphVisitor* visitor) = 0;
121 virtual const char* DebugName() const = 0;
122
123 private:
124 HInstruction* previous_;
125 HInstruction* next_;
126
127 friend class HBasicBlock;
128
129 DISALLOW_COPY_AND_ASSIGN(HInstruction);
130};
131
132class HInstructionIterator : public ValueObject {
133 public:
134 explicit HInstructionIterator(HBasicBlock* block)
135 : instruction_(block->first_instruction()) {
136 next_ = Done() ? nullptr : instruction_->next();
137 }
138
139 inline bool Done() const { return instruction_ == nullptr; }
140 inline HInstruction* Current() { return instruction_; }
141 inline void Advance() {
142 instruction_ = next_;
143 next_ = Done() ? nullptr : instruction_->next();
144 }
145
146 private:
147 HInstruction* instruction_;
148 HInstruction* next_;
149};
150
151// An embedded container with N elements of type T. Used (with partial
152// specialization for N=0) because embedded arrays cannot have size 0.
153template<typename T, intptr_t N>
154class EmbeddedArray {
155 public:
156 EmbeddedArray() : elements_() { }
157
158 intptr_t length() const { return N; }
159
160 const T& operator[](intptr_t i) const {
161 ASSERT(i < length());
162 return elements_[i];
163 }
164
165 T& operator[](intptr_t i) {
166 ASSERT(i < length());
167 return elements_[i];
168 }
169
170 const T& At(intptr_t i) const {
171 return (*this)[i];
172 }
173
174 void SetAt(intptr_t i, const T& val) {
175 (*this)[i] = val;
176 }
177
178 private:
179 T elements_[N];
180};
181
182template<typename T>
183class EmbeddedArray<T, 0> {
184 public:
185 intptr_t length() const { return 0; }
186 const T& operator[](intptr_t i) const {
187 LOG(FATAL) << "Unreachable";
188 static T sentinel = 0;
189 return sentinel;
190 }
191 T& operator[](intptr_t i) {
192 LOG(FATAL) << "Unreachable";
193 static T sentinel = 0;
194 return sentinel;
195 }
196};
197
198template<intptr_t N>
199class HTemplateInstruction: public HInstruction {
200 public:
201 HTemplateInstruction<N>(HBasicBlock* block)
202 : HInstruction(block),
203 inputs_() { }
204
205 virtual intptr_t InputCount() const { return N; }
206 virtual HInstruction* InputAt(intptr_t i) const { return inputs_[i]; }
207
208 private:
209 EmbeddedArray<HInstruction*, N> inputs_;
210};
211
212// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
213// instruction that branches to the exit block.
214class HReturnVoid : public HTemplateInstruction<0> {
215 public:
216 explicit HReturnVoid(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
217
218 DECLARE_INSTRUCTION(ReturnVoid)
219
220 private:
221 DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
222};
223
224// The exit instruction is the only instruction of the exit block.
225// Instructions aborting the method (HTrow and HReturn) must branch to the
226// exit block.
227class HExit : public HTemplateInstruction<0> {
228 public:
229 explicit HExit(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
230
231 DECLARE_INSTRUCTION(Exit)
232
233 private:
234 DISALLOW_COPY_AND_ASSIGN(HExit);
235};
236
237// Jumps from one block to another.
238class HGoto : public HTemplateInstruction<0> {
239 public:
240 explicit HGoto(HBasicBlock* block) : HTemplateInstruction<0>(block) { }
241
242 DECLARE_INSTRUCTION(Goto)
243
244 private:
245 DISALLOW_COPY_AND_ASSIGN(HGoto);
246};
247
248class HGraphVisitor : public ValueObject {
249 public:
250 explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }
251 virtual ~HGraphVisitor() { }
252
253 virtual void VisitInstruction(HInstruction* instruction) { }
254 virtual void VisitBasicBlock(HBasicBlock* block);
255
256 void VisitInsertionOrder();
257
258 // Visit functions for instruction classes.
259#define DECLARE_VISIT_INSTRUCTION(name) \
260 virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
261
262 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
263
264#undef DECLARE_VISIT_INSTRUCTION
265
266 private:
267 HGraph* graph_;
268
269 DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
270};
271
272} // namespace art
273
274#endif // ART_COMPILER_OPTIMIZING_NODES_H_