blob: 0b20ed7d7434cc9336a4e8f55533563ee0e18b1f [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
Dragos Sbirlea597e46b2013-08-07 18:15:44 -070024#include "utils/scoped_hashtable.h"
25#include "gtest/gtest_prod.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070026#include "dex_file.h"
27#include "dex_instruction.h"
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070028#include "sea_ir/ir/instruction_tools.h"
29#include "sea_ir/ir/instruction_nodes.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070030
Brian Carlstrom7940e442013-07-12 13:46:57 -070031namespace sea_ir {
Brian Carlstrom1db91132013-07-12 18:05:20 -070032
Brian Carlstrom1db91132013-07-12 18:05:20 -070033// Reverse post-order numbering constants
34enum RegionNumbering {
35 NOT_VISITED = -1,
36 VISITING = -2
37};
38
Dragos Sbirlea64479192013-08-01 15:38:43 -070039class TypeInference;
Dragos Sbirleae2245322013-07-29 14:16:14 -070040
Brian Carlstrom7940e442013-07-12 13:46:57 -070041class Region;
Brian Carlstrom1db91132013-07-12 18:05:20 -070042class InstructionNode;
43class PhiInstructionNode;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070044class SignatureNode;
Brian Carlstrom7940e442013-07-12 13:46:57 -070045
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070046// A SignatureNode is a declaration of one parameter in the function signature.
47// This class is used to provide place-holder definitions to which instructions
48// can return from the GetSSAUses() calls, instead of having missing SSA edges.
Brian Carlstrom1db91132013-07-12 18:05:20 -070049class SignatureNode: public InstructionNode {
50 public:
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070051 // Creates a new signature node representing the initial definition of the
52 // register @parameter_register which is the @position-th argument to the method.
53 explicit SignatureNode(unsigned int parameter_register, unsigned int position):
54 InstructionNode(NULL), parameter_register_(parameter_register), position_(position) { }
Brian Carlstrom7940e442013-07-12 13:46:57 -070055
Brian Carlstrom1db91132013-07-12 18:05:20 -070056 int GetResultRegister() const {
Dragos Sbirleadb063062013-07-23 16:29:09 -070057 return parameter_register_;
Brian Carlstrom1db91132013-07-12 18:05:20 -070058 }
59
Dragos Sbirlea64479192013-08-01 15:38:43 -070060 unsigned int GetPositionInSignature() const {
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070061 return position_;
62 }
63
Dragos Sbirlea64479192013-08-01 15:38:43 -070064 std::vector<int> GetUses() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070065 return std::vector<int>();
66 }
67
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070068 void Accept(IRVisitor* v) {
69 v->Visit(this);
70 v->Traverse(this);
71 }
72
Brian Carlstrom1db91132013-07-12 18:05:20 -070073 private:
Dragos Sbirlea64479192013-08-01 15:38:43 -070074 const unsigned int parameter_register_;
75 const unsigned int position_; // The position of this parameter node is
76 // in the function parameter list.
Brian Carlstrom1db91132013-07-12 18:05:20 -070077};
78
Brian Carlstrom1db91132013-07-12 18:05:20 -070079class PhiInstructionNode: public InstructionNode {
80 public:
81 explicit PhiInstructionNode(int register_no):
82 InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
Brian Carlstrom1db91132013-07-12 18:05:20 -070083 // Returns the register on which this phi-function is used.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070084 int GetRegisterNumber() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070085 return register_no_;
86 }
87
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070088 // Renames the use of @reg_no to refer to the instruction @definition.
Brian Carlstrom1db91132013-07-12 18:05:20 -070089 // Phi-functions are different than normal instructions in that they
90 // have multiple predecessor regions; this is why RenameToSSA has
91 // the additional parameter specifying that @parameter_id is the incoming
92 // edge for @definition, essentially creating SSA form.
93 void RenameToSSA(int reg_no, InstructionNode* definition, unsigned int predecessor_id) {
94 DCHECK(NULL != definition) << "Tried to rename to SSA using a NULL definition for "
95 << StringId() << " register " << reg_no;
96 if (definition_edges_.size() < predecessor_id+1) {
97 definition_edges_.resize(predecessor_id+1, NULL);
98 }
Brian Carlstrom1db91132013-07-12 18:05:20 -070099 if (NULL == definition_edges_.at(predecessor_id)) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700100 definition_edges_[predecessor_id] = new std::vector<InstructionNode*>();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700101 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700102 definition_edges_[predecessor_id]->push_back(definition);
Dragos Sbirleae2245322013-07-29 14:16:14 -0700103 definition->AddSSAUse(this);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700104 }
105
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700106 // Returns the ordered set of Instructions that define the input operands of this instruction.
107 // Precondition: SeaGraph.ConvertToSSA().
108 std::vector<InstructionNode*> GetSSAProducers() {
109 std::vector<InstructionNode*> producers;
110 for (std::vector<std::vector<InstructionNode*>*>::const_iterator
111 cit = definition_edges_.begin(); cit != definition_edges_.end(); cit++) {
112 producers.insert(producers.end(), (*cit)->begin(), (*cit)->end());
113 }
114 return producers;
115 }
116
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700117 // Returns the instruction that defines the phi register from predecessor
118 // on position @predecessor_pos. Note that the return value is vector<> just
119 // for consistency with the return value of GetSSAUses() on regular instructions,
120 // The returned vector should always have a single element because the IR is SSA.
121 std::vector<InstructionNode*>* GetSSAUses(int predecessor_pos) {
122 return definition_edges_.at(predecessor_pos);
123 }
124
125 void Accept(IRVisitor* v) {
126 v->Visit(this);
127 v->Traverse(this);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700128 }
129
130 private:
131 int register_no_;
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700132 // This vector has one entry for each predecessors, each with a single
133 // element, storing the id of the instruction that defines the register
134 // corresponding to this phi function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700135 std::vector<std::vector<InstructionNode*>*> definition_edges_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700136};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700138// This class corresponds to a basic block in traditional compiler IRs.
139// The dataflow analysis relies on this class both during execution and
140// for storing its results.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700141class Region : public SeaNode {
142 public:
Brian Carlstrom1db91132013-07-12 18:05:20 -0700143 explicit Region():
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700144 SeaNode(), successors_(), predecessors_(), reaching_defs_size_(0),
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700145 rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {
146 string_id_ = "cluster_" + string_id_;
147 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700148 // Adds @instruction as an instruction node child in the current region.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700149 void AddChild(sea_ir::InstructionNode* instruction);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700150 // Returns the last instruction node child of the current region.
151 // This child has the CFG successors pointing to the new regions.
152 SeaNode* GetLastChild() const;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700153 // Returns all the child instructions of this region, in program order.
154 std::vector<InstructionNode*>* GetInstructions() {
155 return &instructions_;
156 }
Dragos Sbirlea64479192013-08-01 15:38:43 -0700157
Brian Carlstrom7940e442013-07-12 13:46:57 -0700158 // Computes Downward Exposed Definitions for the current node.
159 void ComputeDownExposedDefs();
160 const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700161 // Performs one iteration of the reaching definitions algorithm
162 // and returns true if the reaching definitions set changed.
163 bool UpdateReachingDefs();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700164 // Returns the set of reaching definitions for the current region.
165 std::map<int, std::set<sea_ir::InstructionNode*>* >* GetReachingDefs();
166
Brian Carlstrom1db91132013-07-12 18:05:20 -0700167 void SetRPO(int rpo) {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700168 rpo_number_ = rpo;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700169 }
170
171 int GetRPO() {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700172 return rpo_number_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700173 }
174
175 void SetIDominator(Region* dom) {
176 idom_ = dom;
177 }
178
179 Region* GetIDominator() const {
180 return idom_;
181 }
182
183 void AddToIDominatedSet(Region* dominated) {
184 idominated_set_.insert(dominated);
185 }
186
187 const std::set<Region*>* GetIDominatedSet() {
188 return &idominated_set_;
189 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700190 // Adds @df_reg to the dominance frontier of the current region.
191 void AddToDominanceFrontier(Region* df_reg) {
192 df_.insert(df_reg);
193 }
194 // Returns the dominance frontier of the current region.
195 // Preconditions: SeaGraph.ComputeDominanceFrontier()
196 std::set<Region*>* GetDominanceFrontier() {
197 return &df_;
198 }
199 // Returns true if the region contains a phi function for @reg_no.
200 bool ContainsPhiFor(int reg_no) {
201 return (phi_set_.end() != phi_set_.find(reg_no));
202 }
203 // Returns the phi-functions from the region.
204 std::vector<PhiInstructionNode*>* GetPhiNodes() {
205 return &phi_instructions_;
206 }
207 // Adds a phi-function for @reg_no to this region.
208 // Note: The insertion order does not matter, as phi-functions
209 // are conceptually executed at the same time.
210 bool InsertPhiFor(int reg_no);
211 // Sets the phi-function uses to be as defined in @scoped_table for predecessor @@predecessor.
212 void SetPhiDefinitionsForUses(const utils::ScopedHashtable<int, InstructionNode*>* scoped_table,
213 Region* predecessor);
214
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700215 void Accept(IRVisitor* v) {
216 v->Visit(this);
217 v->Traverse(this);
218 }
219
220 void AddSuccessor(Region* successor) {
221 DCHECK(successor) << "Tried to add NULL successor to SEA node.";
222 successors_.push_back(successor);
223 return;
224 }
225 void AddPredecessor(Region* predecessor) {
226 DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
227 predecessors_.push_back(predecessor);
228 }
229
230 std::vector<sea_ir::Region*>* GetSuccessors() {
231 return &successors_;
232 }
233 std::vector<sea_ir::Region*>* GetPredecessors() {
234 return &predecessors_;
235 }
236
Brian Carlstrom7940e442013-07-12 13:46:57 -0700237 private:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700238 std::vector<sea_ir::Region*> successors_; // CFG successor nodes (regions)
239 std::vector<sea_ir::Region*> predecessors_; // CFG predecessor nodes (instructions/regions)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700240 std::vector<sea_ir::InstructionNode*> instructions_;
241 std::map<int, sea_ir::InstructionNode*> de_defs_;
242 std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs_;
243 int reaching_defs_size_;
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700244 int rpo_number_; // reverse postorder number of the region
Brian Carlstrom1db91132013-07-12 18:05:20 -0700245 // Immediate dominator node.
246 Region* idom_;
247 // The set of nodes immediately dominated by the region.
248 std::set<Region*> idominated_set_;
249 // Records the dominance frontier.
250 std::set<Region*> df_;
251 // Records the set of register numbers that have phi nodes in this region.
252 std::set<int> phi_set_;
253 std::vector<PhiInstructionNode*> phi_instructions_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700254};
255
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700256// A SeaGraph instance corresponds to a source code function.
257// Its main point is to encapsulate the SEA IR representation of it
258// and acts as starting point for visitors (ex: during code generation).
259class SeaGraph: IVisitable {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700260 public:
Dragos Sbirleaa3519a42013-08-07 14:41:55 -0700261 static SeaGraph* GetGraph(const art::DexFile&);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700262
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700263 void CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
264 uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700265 // Returns all regions corresponding to this SeaGraph.
266 std::vector<Region*>* GetRegions() {
267 return &regions_;
268 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700269 // Recursively computes the reverse postorder value for @crt_bb and successors.
270 static void ComputeRPO(Region* crt_bb, int& crt_rpo);
271 // Returns the "lowest common ancestor" of @i and @j in the dominator tree.
272 static Region* Intersect(Region* i, Region* j);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700273 // Returns the vector of parameters of the function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700274 std::vector<SignatureNode*>* GetParameterNodes() {
275 return &parameters_;
276 }
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700277
278 const art::DexFile* GetDexFile() const {
279 return &dex_file_;
280 }
281
Dragos Sbirlea64479192013-08-01 15:38:43 -0700282 virtual void Accept(IRVisitor* visitor) {
283 visitor->Initialize(this);
284 visitor->Visit(this);
285 visitor->Traverse(this);
286 }
287
288 TypeInference* ti_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700289 uint32_t class_def_idx_;
290 uint32_t method_idx_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700291 uint32_t method_access_flags_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700292
Dragos Sbirlea597e46b2013-08-07 18:15:44 -0700293 protected:
Dragos Sbirlea64479192013-08-01 15:38:43 -0700294 explicit SeaGraph(const art::DexFile& df);
Dragos Sbirlea597e46b2013-08-07 18:15:44 -0700295 virtual ~SeaGraph() { }
296
297 private:
298 FRIEND_TEST(RegionsTest, Basics);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700299 // Registers @childReg as a region belonging to the SeaGraph instance.
300 void AddRegion(Region* childReg);
301 // Returns new region and registers it with the SeaGraph instance.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700302 Region* GetNewRegion();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700303 // Adds a (formal) parameter node to the vector of parameters of the function.
304 void AddParameterNode(SignatureNode* parameterNode) {
305 parameters_.push_back(parameterNode);
306 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700307 // Adds a CFG edge from @src node to @dst node.
308 void AddEdge(Region* src, Region* dst) const;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700309 // Builds the non-SSA sea-ir representation of the function @code_item from @dex_file
310 // with class id @class_def_idx and method id @method_idx.
311 void BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700312 const art::DexFile& dex_file, uint32_t class_def_idx,
313 uint32_t method_idx, uint32_t method_access_flags);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700314 // Computes immediate dominators for each region.
315 // Precondition: ComputeMethodSeaGraph()
316 void ComputeIDominators();
317 // Computes Downward Exposed Definitions for all regions in the graph.
318 void ComputeDownExposedDefs();
319 // Computes the reaching definitions set following the equations from
320 // Cooper & Torczon, "Engineering a Compiler", second edition, page 491.
321 // Precondition: ComputeDEDefs()
322 void ComputeReachingDefs();
323 // Computes the reverse-postorder numbering for the region nodes.
324 // Precondition: ComputeDEDefs()
325 void ComputeRPO();
326 // Computes the dominance frontier for all regions in the graph,
327 // following the algorithm from
328 // Cooper & Torczon, "Engineering a Compiler", second edition, page 499.
329 // Precondition: ComputeIDominators()
330 void ComputeDominanceFrontier();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700331 // Converts the IR to semi-pruned SSA form.
Brian Carlstrom1db91132013-07-12 18:05:20 -0700332 void ConvertToSSA();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700333 // Performs the renaming phase of the SSA transformation during ConvertToSSA() execution.
334 void RenameAsSSA();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700335 // Identifies the definitions corresponding to uses for region @node
336 // by using the scoped hashtable of names @ scoped_table.
337 void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700338 // Generate LLVM IR for the method.
339 // Precondition: ConvertToSSA().
340 void GenerateLLVM();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700341
Brian Carlstrom7940e442013-07-12 13:46:57 -0700342 static SeaGraph graph_;
343 std::vector<Region*> regions_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700344 std::vector<SignatureNode*> parameters_;
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700345 const art::DexFile& dex_file_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700346 const art::DexFile::CodeItem* code_item_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700347};
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700348} // namespace sea_ir
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -0700349#endif // ART_COMPILER_SEA_IR_IR_SEA_H_