blob: 958fc32360d17e555d212316e8c1e10bf066172f [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2013 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
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070018#ifndef ART_COMPILER_SEA_IR_IR_SEA_H_
19#define ART_COMPILER_SEA_IR_IR_SEA_H_
Brian Carlstrom7940e442013-07-12 13:46:57 -070020
21#include <set>
22#include <map>
23
24#include "dex_file.h"
25#include "dex_instruction.h"
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070026#include "sea_ir/ir/instruction_tools.h"
27#include "sea_ir/ir/instruction_nodes.h"
Brian Carlstrom1db91132013-07-12 18:05:20 -070028#include "utils/scoped_hashtable.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070029
Brian Carlstrom7940e442013-07-12 13:46:57 -070030namespace sea_ir {
Brian Carlstrom1db91132013-07-12 18:05:20 -070031
Brian Carlstrom1db91132013-07-12 18:05:20 -070032// Reverse post-order numbering constants
33enum RegionNumbering {
34 NOT_VISITED = -1,
35 VISITING = -2
36};
37
Dragos Sbirlea64479192013-08-01 15:38:43 -070038class TypeInference;
Dragos Sbirleae2245322013-07-29 14:16:14 -070039
Brian Carlstrom7940e442013-07-12 13:46:57 -070040class Region;
Brian Carlstrom1db91132013-07-12 18:05:20 -070041class InstructionNode;
42class PhiInstructionNode;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070043class SignatureNode;
Brian Carlstrom7940e442013-07-12 13:46:57 -070044
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070045// A SignatureNode is a declaration of one parameter in the function signature.
46// This class is used to provide place-holder definitions to which instructions
47// can return from the GetSSAUses() calls, instead of having missing SSA edges.
Brian Carlstrom1db91132013-07-12 18:05:20 -070048class SignatureNode: public InstructionNode {
49 public:
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070050 // Creates a new signature node representing the initial definition of the
51 // register @parameter_register which is the @position-th argument to the method.
52 explicit SignatureNode(unsigned int parameter_register, unsigned int position):
53 InstructionNode(NULL), parameter_register_(parameter_register), position_(position) { }
Brian Carlstrom7940e442013-07-12 13:46:57 -070054
Brian Carlstrom1db91132013-07-12 18:05:20 -070055 int GetResultRegister() const {
Dragos Sbirleadb063062013-07-23 16:29:09 -070056 return parameter_register_;
Brian Carlstrom1db91132013-07-12 18:05:20 -070057 }
58
Dragos Sbirlea64479192013-08-01 15:38:43 -070059 unsigned int GetPositionInSignature() const {
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070060 return position_;
61 }
62
Dragos Sbirlea64479192013-08-01 15:38:43 -070063 std::vector<int> GetUses() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070064 return std::vector<int>();
65 }
66
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070067 void Accept(IRVisitor* v) {
68 v->Visit(this);
69 v->Traverse(this);
70 }
71
Brian Carlstrom1db91132013-07-12 18:05:20 -070072 private:
Dragos Sbirlea64479192013-08-01 15:38:43 -070073 const unsigned int parameter_register_;
74 const unsigned int position_; // The position of this parameter node is
75 // in the function parameter list.
Brian Carlstrom1db91132013-07-12 18:05:20 -070076};
77
Brian Carlstrom1db91132013-07-12 18:05:20 -070078class PhiInstructionNode: public InstructionNode {
79 public:
80 explicit PhiInstructionNode(int register_no):
81 InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
Brian Carlstrom1db91132013-07-12 18:05:20 -070082 // Returns the register on which this phi-function is used.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070083 int GetRegisterNumber() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070084 return register_no_;
85 }
86
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070087 // Renames the use of @reg_no to refer to the instruction @definition.
Brian Carlstrom1db91132013-07-12 18:05:20 -070088 // Phi-functions are different than normal instructions in that they
89 // have multiple predecessor regions; this is why RenameToSSA has
90 // the additional parameter specifying that @parameter_id is the incoming
91 // edge for @definition, essentially creating SSA form.
92 void RenameToSSA(int reg_no, InstructionNode* definition, unsigned int predecessor_id) {
93 DCHECK(NULL != definition) << "Tried to rename to SSA using a NULL definition for "
94 << StringId() << " register " << reg_no;
95 if (definition_edges_.size() < predecessor_id+1) {
96 definition_edges_.resize(predecessor_id+1, NULL);
97 }
Brian Carlstrom1db91132013-07-12 18:05:20 -070098 if (NULL == definition_edges_.at(predecessor_id)) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070099 definition_edges_[predecessor_id] = new std::vector<InstructionNode*>();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700100 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700101 definition_edges_[predecessor_id]->push_back(definition);
Dragos Sbirleae2245322013-07-29 14:16:14 -0700102 definition->AddSSAUse(this);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700103 }
104
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700105 // Returns the ordered set of Instructions that define the input operands of this instruction.
106 // Precondition: SeaGraph.ConvertToSSA().
107 std::vector<InstructionNode*> GetSSAProducers() {
108 std::vector<InstructionNode*> producers;
109 for (std::vector<std::vector<InstructionNode*>*>::const_iterator
110 cit = definition_edges_.begin(); cit != definition_edges_.end(); cit++) {
111 producers.insert(producers.end(), (*cit)->begin(), (*cit)->end());
112 }
113 return producers;
114 }
115
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700116 // Returns the instruction that defines the phi register from predecessor
117 // on position @predecessor_pos. Note that the return value is vector<> just
118 // for consistency with the return value of GetSSAUses() on regular instructions,
119 // The returned vector should always have a single element because the IR is SSA.
120 std::vector<InstructionNode*>* GetSSAUses(int predecessor_pos) {
121 return definition_edges_.at(predecessor_pos);
122 }
123
124 void Accept(IRVisitor* v) {
125 v->Visit(this);
126 v->Traverse(this);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700127 }
128
129 private:
130 int register_no_;
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700131 // This vector has one entry for each predecessors, each with a single
132 // element, storing the id of the instruction that defines the register
133 // corresponding to this phi function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700134 std::vector<std::vector<InstructionNode*>*> definition_edges_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700135};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700137// This class corresponds to a basic block in traditional compiler IRs.
138// The dataflow analysis relies on this class both during execution and
139// for storing its results.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700140class Region : public SeaNode {
141 public:
Brian Carlstrom1db91132013-07-12 18:05:20 -0700142 explicit Region():
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700143 SeaNode(), successors_(), predecessors_(), reaching_defs_size_(0),
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700144 rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {
145 string_id_ = "cluster_" + string_id_;
146 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700147 // Adds @instruction as an instruction node child in the current region.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700148 void AddChild(sea_ir::InstructionNode* instruction);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700149 // Returns the last instruction node child of the current region.
150 // This child has the CFG successors pointing to the new regions.
151 SeaNode* GetLastChild() const;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700152 // Returns all the child instructions of this region, in program order.
153 std::vector<InstructionNode*>* GetInstructions() {
154 return &instructions_;
155 }
Dragos Sbirlea64479192013-08-01 15:38:43 -0700156
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 // Computes Downward Exposed Definitions for the current node.
158 void ComputeDownExposedDefs();
159 const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 // Performs one iteration of the reaching definitions algorithm
161 // and returns true if the reaching definitions set changed.
162 bool UpdateReachingDefs();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700163 // Returns the set of reaching definitions for the current region.
164 std::map<int, std::set<sea_ir::InstructionNode*>* >* GetReachingDefs();
165
Brian Carlstrom1db91132013-07-12 18:05:20 -0700166 void SetRPO(int rpo) {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700167 rpo_number_ = rpo;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700168 }
169
170 int GetRPO() {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700171 return rpo_number_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700172 }
173
174 void SetIDominator(Region* dom) {
175 idom_ = dom;
176 }
177
178 Region* GetIDominator() const {
179 return idom_;
180 }
181
182 void AddToIDominatedSet(Region* dominated) {
183 idominated_set_.insert(dominated);
184 }
185
186 const std::set<Region*>* GetIDominatedSet() {
187 return &idominated_set_;
188 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700189 // Adds @df_reg to the dominance frontier of the current region.
190 void AddToDominanceFrontier(Region* df_reg) {
191 df_.insert(df_reg);
192 }
193 // Returns the dominance frontier of the current region.
194 // Preconditions: SeaGraph.ComputeDominanceFrontier()
195 std::set<Region*>* GetDominanceFrontier() {
196 return &df_;
197 }
198 // Returns true if the region contains a phi function for @reg_no.
199 bool ContainsPhiFor(int reg_no) {
200 return (phi_set_.end() != phi_set_.find(reg_no));
201 }
202 // Returns the phi-functions from the region.
203 std::vector<PhiInstructionNode*>* GetPhiNodes() {
204 return &phi_instructions_;
205 }
206 // Adds a phi-function for @reg_no to this region.
207 // Note: The insertion order does not matter, as phi-functions
208 // are conceptually executed at the same time.
209 bool InsertPhiFor(int reg_no);
210 // Sets the phi-function uses to be as defined in @scoped_table for predecessor @@predecessor.
211 void SetPhiDefinitionsForUses(const utils::ScopedHashtable<int, InstructionNode*>* scoped_table,
212 Region* predecessor);
213
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700214 void Accept(IRVisitor* v) {
215 v->Visit(this);
216 v->Traverse(this);
217 }
218
219 void AddSuccessor(Region* successor) {
220 DCHECK(successor) << "Tried to add NULL successor to SEA node.";
221 successors_.push_back(successor);
222 return;
223 }
224 void AddPredecessor(Region* predecessor) {
225 DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
226 predecessors_.push_back(predecessor);
227 }
228
229 std::vector<sea_ir::Region*>* GetSuccessors() {
230 return &successors_;
231 }
232 std::vector<sea_ir::Region*>* GetPredecessors() {
233 return &predecessors_;
234 }
235
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 private:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700237 std::vector<sea_ir::Region*> successors_; // CFG successor nodes (regions)
238 std::vector<sea_ir::Region*> predecessors_; // CFG predecessor nodes (instructions/regions)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700239 std::vector<sea_ir::InstructionNode*> instructions_;
240 std::map<int, sea_ir::InstructionNode*> de_defs_;
241 std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs_;
242 int reaching_defs_size_;
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700243 int rpo_number_; // reverse postorder number of the region
Brian Carlstrom1db91132013-07-12 18:05:20 -0700244 // Immediate dominator node.
245 Region* idom_;
246 // The set of nodes immediately dominated by the region.
247 std::set<Region*> idominated_set_;
248 // Records the dominance frontier.
249 std::set<Region*> df_;
250 // Records the set of register numbers that have phi nodes in this region.
251 std::set<int> phi_set_;
252 std::vector<PhiInstructionNode*> phi_instructions_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700253};
254
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700255// A SeaGraph instance corresponds to a source code function.
256// Its main point is to encapsulate the SEA IR representation of it
257// and acts as starting point for visitors (ex: during code generation).
258class SeaGraph: IVisitable {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700259 public:
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700260 static SeaGraph* GetCurrentGraph(const art::DexFile&);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700261
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700262 void CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
263 uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700264 // Returns all regions corresponding to this SeaGraph.
265 std::vector<Region*>* GetRegions() {
266 return &regions_;
267 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700268 // Recursively computes the reverse postorder value for @crt_bb and successors.
269 static void ComputeRPO(Region* crt_bb, int& crt_rpo);
270 // Returns the "lowest common ancestor" of @i and @j in the dominator tree.
271 static Region* Intersect(Region* i, Region* j);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700272 // Returns the vector of parameters of the function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700273 std::vector<SignatureNode*>* GetParameterNodes() {
274 return &parameters_;
275 }
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700276
277 const art::DexFile* GetDexFile() const {
278 return &dex_file_;
279 }
280
Dragos Sbirlea64479192013-08-01 15:38:43 -0700281 virtual void Accept(IRVisitor* visitor) {
282 visitor->Initialize(this);
283 visitor->Visit(this);
284 visitor->Traverse(this);
285 }
286
287 TypeInference* ti_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700288 uint32_t class_def_idx_;
289 uint32_t method_idx_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700290 uint32_t method_access_flags_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700291
292 private:
Dragos Sbirlea64479192013-08-01 15:38:43 -0700293 explicit SeaGraph(const art::DexFile& df);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700294 // Registers @childReg as a region belonging to the SeaGraph instance.
295 void AddRegion(Region* childReg);
296 // Returns new region and registers it with the SeaGraph instance.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700297 Region* GetNewRegion();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700298 // Adds a (formal) parameter node to the vector of parameters of the function.
299 void AddParameterNode(SignatureNode* parameterNode) {
300 parameters_.push_back(parameterNode);
301 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700302 // Adds a CFG edge from @src node to @dst node.
303 void AddEdge(Region* src, Region* dst) const;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700304 // Builds the non-SSA sea-ir representation of the function @code_item from @dex_file
305 // with class id @class_def_idx and method id @method_idx.
306 void BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700307 const art::DexFile& dex_file, uint32_t class_def_idx,
308 uint32_t method_idx, uint32_t method_access_flags);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700309 // Computes immediate dominators for each region.
310 // Precondition: ComputeMethodSeaGraph()
311 void ComputeIDominators();
312 // Computes Downward Exposed Definitions for all regions in the graph.
313 void ComputeDownExposedDefs();
314 // Computes the reaching definitions set following the equations from
315 // Cooper & Torczon, "Engineering a Compiler", second edition, page 491.
316 // Precondition: ComputeDEDefs()
317 void ComputeReachingDefs();
318 // Computes the reverse-postorder numbering for the region nodes.
319 // Precondition: ComputeDEDefs()
320 void ComputeRPO();
321 // Computes the dominance frontier for all regions in the graph,
322 // following the algorithm from
323 // Cooper & Torczon, "Engineering a Compiler", second edition, page 499.
324 // Precondition: ComputeIDominators()
325 void ComputeDominanceFrontier();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700326 // Converts the IR to semi-pruned SSA form.
Brian Carlstrom1db91132013-07-12 18:05:20 -0700327 void ConvertToSSA();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700328 // Performs the renaming phase of the SSA transformation during ConvertToSSA() execution.
329 void RenameAsSSA();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700330 // Identifies the definitions corresponding to uses for region @node
331 // by using the scoped hashtable of names @ scoped_table.
332 void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700333
Dragos Sbirlea64479192013-08-01 15:38:43 -0700334
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700335
336 virtual ~SeaGraph() {}
337 // Generate LLVM IR for the method.
338 // Precondition: ConvertToSSA().
339 void GenerateLLVM();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700340
Brian Carlstrom7940e442013-07-12 13:46:57 -0700341 static SeaGraph graph_;
342 std::vector<Region*> regions_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700343 std::vector<SignatureNode*> parameters_;
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700344 const art::DexFile& dex_file_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700345 const art::DexFile::CodeItem* code_item_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700346};
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700347} // namespace sea_ir
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -0700348#endif // ART_COMPILER_SEA_IR_IR_SEA_H_