blob: 28d0c174e587e3f2e9f6383eba40156407a6ab13 [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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070018#ifndef ART_COMPILER_SEA_IR_SEA_H_
19#define ART_COMPILER_SEA_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 Sbirlea0e260a32013-06-21 09:20:34 -070026#include "instruction_tools.h"
27#include "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
Brian Carlstrom7940e442013-07-12 13:46:57 -070038class Region;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070039
Brian Carlstrom1db91132013-07-12 18:05:20 -070040class InstructionNode;
41class PhiInstructionNode;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070042class SignatureNode;
Brian Carlstrom7940e442013-07-12 13:46:57 -070043
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070044// A SignatureNode is a declaration of one parameter in the function signature.
45// This class is used to provide place-holder definitions to which instructions
46// can return from the GetSSAUses() calls, instead of having missing SSA edges.
Brian Carlstrom1db91132013-07-12 18:05:20 -070047class SignatureNode: public InstructionNode {
48 public:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070049 explicit SignatureNode(unsigned int parameter_register):
Brian Carlstrom1db91132013-07-12 18:05:20 -070050 InstructionNode(NULL), defined_regs_() {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070051 defined_regs_.push_back(parameter_register);
Brian Carlstrom1db91132013-07-12 18:05:20 -070052 }
Brian Carlstrom7940e442013-07-12 13:46:57 -070053
Brian Carlstrom1db91132013-07-12 18:05:20 -070054 void ToDot(std::string& result) const {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070055 result += StringId() +" [label=\"signature:";
Brian Carlstrom1db91132013-07-12 18:05:20 -070056 std::stringstream vector_printer;
57 if (!defined_regs_.empty()) {
58 for (unsigned int crt_el = 0; crt_el < defined_regs_.size()-1; crt_el++) {
59 vector_printer << defined_regs_[crt_el] <<",";
60 }
61 vector_printer << defined_regs_[defined_regs_.size()-1] <<";";
62 }
63 result += "\"] // signature node\n";
64 }
65
66 std::vector<int> GetDefinitions() const {
67 return defined_regs_;
68 }
69
70 int GetResultRegister() const {
71 return NO_REGISTER;
72 }
73
74 std::vector<int> GetUses() {
75 return std::vector<int>();
76 }
77
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070078 void Accept(IRVisitor* v) {
79 v->Visit(this);
80 v->Traverse(this);
81 }
82
Brian Carlstrom1db91132013-07-12 18:05:20 -070083 private:
84 std::vector<int> defined_regs_;
85};
86
Brian Carlstrom1db91132013-07-12 18:05:20 -070087class PhiInstructionNode: public InstructionNode {
88 public:
89 explicit PhiInstructionNode(int register_no):
90 InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
91 // Appends to @result the .dot string representation of the instruction.
92 void ToDot(std::string& result) const;
93 // Returns the register on which this phi-function is used.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070094 int GetRegisterNumber() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070095 return register_no_;
96 }
97
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070098 // Renames the use of @reg_no to refer to the instruction @definition.
Brian Carlstrom1db91132013-07-12 18:05:20 -070099 // Phi-functions are different than normal instructions in that they
100 // have multiple predecessor regions; this is why RenameToSSA has
101 // the additional parameter specifying that @parameter_id is the incoming
102 // edge for @definition, essentially creating SSA form.
103 void RenameToSSA(int reg_no, InstructionNode* definition, unsigned int predecessor_id) {
104 DCHECK(NULL != definition) << "Tried to rename to SSA using a NULL definition for "
105 << StringId() << " register " << reg_no;
106 if (definition_edges_.size() < predecessor_id+1) {
107 definition_edges_.resize(predecessor_id+1, NULL);
108 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700109 if (NULL == definition_edges_.at(predecessor_id)) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700110 definition_edges_[predecessor_id] = new std::vector<InstructionNode*>();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700111 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700112 definition_edges_[predecessor_id]->push_back(definition);
113 }
114
115 // Returns the instruction that defines the phi register from predecessor
116 // on position @predecessor_pos. Note that the return value is vector<> just
117 // for consistency with the return value of GetSSAUses() on regular instructions,
118 // The returned vector should always have a single element because the IR is SSA.
119 std::vector<InstructionNode*>* GetSSAUses(int predecessor_pos) {
120 return definition_edges_.at(predecessor_pos);
121 }
122
123 void Accept(IRVisitor* v) {
124 v->Visit(this);
125 v->Traverse(this);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700126 }
127
128 private:
129 int register_no_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700130 std::vector<std::vector<InstructionNode*>*> definition_edges_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700131};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700132
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700133// This class corresponds to a basic block in traditional compiler IRs.
134// The dataflow analysis relies on this class both during execution and
135// for storing its results.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700136class Region : public SeaNode {
137 public:
Brian Carlstrom1db91132013-07-12 18:05:20 -0700138 explicit Region():
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700139 SeaNode(), successors_(), predecessors_(), reaching_defs_size_(0),
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700140 rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {}
Brian Carlstrom1db91132013-07-12 18:05:20 -0700141 // Adds @instruction as an instruction node child in the current region.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700142 void AddChild(sea_ir::InstructionNode* instruction);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700143 // Returns the last instruction node child of the current region.
144 // This child has the CFG successors pointing to the new regions.
145 SeaNode* GetLastChild() const;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700146 // Returns all the child instructions of this region, in program order.
147 std::vector<InstructionNode*>* GetInstructions() {
148 return &instructions_;
149 }
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150 // Appends to @result a dot language formatted string representing the node and
151 // (by convention) outgoing edges, so that the composition of theToDot() of all nodes
152 // builds a complete dot graph (without prolog and epilog though).
153 virtual void ToDot(std::string& result) const;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700154 // Computes Downward Exposed Definitions for the current node.
155 void ComputeDownExposedDefs();
156 const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700157 // Performs one iteration of the reaching definitions algorithm
158 // and returns true if the reaching definitions set changed.
159 bool UpdateReachingDefs();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700160 // Returns the set of reaching definitions for the current region.
161 std::map<int, std::set<sea_ir::InstructionNode*>* >* GetReachingDefs();
162
Brian Carlstrom1db91132013-07-12 18:05:20 -0700163 void SetRPO(int rpo) {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700164 rpo_number_ = rpo;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700165 }
166
167 int GetRPO() {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700168 return rpo_number_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700169 }
170
171 void SetIDominator(Region* dom) {
172 idom_ = dom;
173 }
174
175 Region* GetIDominator() const {
176 return idom_;
177 }
178
179 void AddToIDominatedSet(Region* dominated) {
180 idominated_set_.insert(dominated);
181 }
182
183 const std::set<Region*>* GetIDominatedSet() {
184 return &idominated_set_;
185 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700186 // Adds @df_reg to the dominance frontier of the current region.
187 void AddToDominanceFrontier(Region* df_reg) {
188 df_.insert(df_reg);
189 }
190 // Returns the dominance frontier of the current region.
191 // Preconditions: SeaGraph.ComputeDominanceFrontier()
192 std::set<Region*>* GetDominanceFrontier() {
193 return &df_;
194 }
195 // Returns true if the region contains a phi function for @reg_no.
196 bool ContainsPhiFor(int reg_no) {
197 return (phi_set_.end() != phi_set_.find(reg_no));
198 }
199 // Returns the phi-functions from the region.
200 std::vector<PhiInstructionNode*>* GetPhiNodes() {
201 return &phi_instructions_;
202 }
203 // Adds a phi-function for @reg_no to this region.
204 // Note: The insertion order does not matter, as phi-functions
205 // are conceptually executed at the same time.
206 bool InsertPhiFor(int reg_no);
207 // Sets the phi-function uses to be as defined in @scoped_table for predecessor @@predecessor.
208 void SetPhiDefinitionsForUses(const utils::ScopedHashtable<int, InstructionNode*>* scoped_table,
209 Region* predecessor);
210
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700211 void Accept(IRVisitor* v) {
212 v->Visit(this);
213 v->Traverse(this);
214 }
215
216 void AddSuccessor(Region* successor) {
217 DCHECK(successor) << "Tried to add NULL successor to SEA node.";
218 successors_.push_back(successor);
219 return;
220 }
221 void AddPredecessor(Region* predecessor) {
222 DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
223 predecessors_.push_back(predecessor);
224 }
225
226 std::vector<sea_ir::Region*>* GetSuccessors() {
227 return &successors_;
228 }
229 std::vector<sea_ir::Region*>* GetPredecessors() {
230 return &predecessors_;
231 }
232
Brian Carlstrom7940e442013-07-12 13:46:57 -0700233 private:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700234 std::vector<sea_ir::Region*> successors_; // CFG successor nodes (regions)
235 std::vector<sea_ir::Region*> predecessors_; // CFG predecessor nodes (instructions/regions)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700236 std::vector<sea_ir::InstructionNode*> instructions_;
237 std::map<int, sea_ir::InstructionNode*> de_defs_;
238 std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs_;
239 int reaching_defs_size_;
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700240 int rpo_number_; // reverse postorder number of the region
Brian Carlstrom1db91132013-07-12 18:05:20 -0700241 // Immediate dominator node.
242 Region* idom_;
243 // The set of nodes immediately dominated by the region.
244 std::set<Region*> idominated_set_;
245 // Records the dominance frontier.
246 std::set<Region*> df_;
247 // Records the set of register numbers that have phi nodes in this region.
248 std::set<int> phi_set_;
249 std::vector<PhiInstructionNode*> phi_instructions_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700250};
251
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700252// A SeaGraph instance corresponds to a source code function.
253// Its main point is to encapsulate the SEA IR representation of it
254// and acts as starting point for visitors (ex: during code generation).
255class SeaGraph: IVisitable {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700256 public:
257 static SeaGraph* GetCurrentGraph();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700258
Brian Carlstrom7940e442013-07-12 13:46:57 -0700259 void CompileMethod(const art::DexFile::CodeItem* code_item,
260 uint32_t class_def_idx, uint32_t method_idx, const art::DexFile& dex_file);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700261 // Returns all regions corresponding to this SeaGraph.
262 std::vector<Region*>* GetRegions() {
263 return &regions_;
264 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700265 // Returns a string representation of the region and its Instruction children.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700266 void DumpSea(std::string filename) const;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700267 // Recursively computes the reverse postorder value for @crt_bb and successors.
268 static void ComputeRPO(Region* crt_bb, int& crt_rpo);
269 // Returns the "lowest common ancestor" of @i and @j in the dominator tree.
270 static Region* Intersect(Region* i, Region* j);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700271 //Returns the vector of parameters of the function.
272 std::vector<SignatureNode*>* GetParameterNodes() {
273 return &parameters_;
274 }
275 uint32_t class_def_idx_;
276 uint32_t method_idx_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700277
278 private:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700279 SeaGraph(): class_def_idx_(0), method_idx_(0), regions_(), parameters_() {
280 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700281 // Registers @childReg as a region belonging to the SeaGraph instance.
282 void AddRegion(Region* childReg);
283 // Returns new region and registers it with the SeaGraph instance.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700284 Region* GetNewRegion();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700285 // Adds a (formal) parameter node to the vector of parameters of the function.
286 void AddParameterNode(SignatureNode* parameterNode) {
287 parameters_.push_back(parameterNode);
288 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700289 // Adds a CFG edge from @src node to @dst node.
290 void AddEdge(Region* src, Region* dst) const;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700291 // Builds the non-SSA sea-ir representation of the function @code_item from @dex_file
292 // with class id @class_def_idx and method id @method_idx.
293 void BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
294 const art::DexFile& dex_file, uint32_t class_def_idx, uint32_t method_idx);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700295 // Computes immediate dominators for each region.
296 // Precondition: ComputeMethodSeaGraph()
297 void ComputeIDominators();
298 // Computes Downward Exposed Definitions for all regions in the graph.
299 void ComputeDownExposedDefs();
300 // Computes the reaching definitions set following the equations from
301 // Cooper & Torczon, "Engineering a Compiler", second edition, page 491.
302 // Precondition: ComputeDEDefs()
303 void ComputeReachingDefs();
304 // Computes the reverse-postorder numbering for the region nodes.
305 // Precondition: ComputeDEDefs()
306 void ComputeRPO();
307 // Computes the dominance frontier for all regions in the graph,
308 // following the algorithm from
309 // Cooper & Torczon, "Engineering a Compiler", second edition, page 499.
310 // Precondition: ComputeIDominators()
311 void ComputeDominanceFrontier();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700312 // Converts the IR to semi-pruned SSA form.
Brian Carlstrom1db91132013-07-12 18:05:20 -0700313 void ConvertToSSA();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700314 // Performs the renaming phase of the SSA transformation during ConvertToSSA() execution.
315 void RenameAsSSA();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700316 // Identifies the definitions corresponding to uses for region @node
317 // by using the scoped hashtable of names @ scoped_table.
318 void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700319
320 virtual void Accept(IRVisitor* visitor) {
321 visitor->Initialize(this);
322 visitor->Visit(this);
323 visitor->Traverse(this);
324 }
325
326 virtual ~SeaGraph() {}
327 // Generate LLVM IR for the method.
328 // Precondition: ConvertToSSA().
329 void GenerateLLVM();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700330
Brian Carlstrom7940e442013-07-12 13:46:57 -0700331 static SeaGraph graph_;
332 std::vector<Region*> regions_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700333 std::vector<SignatureNode*> parameters_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700334};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700335} // end namespace sea_ir
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700336#endif // ART_COMPILER_SEA_IR_SEA_H_