blob: 26b16be019514f1fa8ad85aa15577938d5d154a6 [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 Sbirleabd136a22013-08-13 18:07:04 -070040class CodeGenData;
Dragos Sbirleae2245322013-07-29 14:16:14 -070041
Brian Carlstrom7940e442013-07-12 13:46:57 -070042class Region;
Brian Carlstrom1db91132013-07-12 18:05:20 -070043class InstructionNode;
44class PhiInstructionNode;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070045class SignatureNode;
Brian Carlstrom7940e442013-07-12 13:46:57 -070046
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070047// A SignatureNode is a declaration of one parameter in the function signature.
48// This class is used to provide place-holder definitions to which instructions
49// can return from the GetSSAUses() calls, instead of having missing SSA edges.
Brian Carlstrom1db91132013-07-12 18:05:20 -070050class SignatureNode: public InstructionNode {
51 public:
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070052 // Creates a new signature node representing the initial definition of the
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070053 // register @register_no which is the @signature_position-th argument to the method.
54 explicit SignatureNode(unsigned int register_no, unsigned int signature_position):
55 InstructionNode(NULL), register_no_(register_no), position_(signature_position) { }
Brian Carlstrom7940e442013-07-12 13:46:57 -070056
Brian Carlstrom1db91132013-07-12 18:05:20 -070057 int GetResultRegister() const {
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070058 return register_no_;
Brian Carlstrom1db91132013-07-12 18:05:20 -070059 }
60
Dragos Sbirlea64479192013-08-01 15:38:43 -070061 unsigned int GetPositionInSignature() const {
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070062 return position_;
63 }
64
Dragos Sbirlea64479192013-08-01 15:38:43 -070065 std::vector<int> GetUses() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070066 return std::vector<int>();
67 }
68
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070069 void Accept(IRVisitor* v) {
70 v->Visit(this);
71 v->Traverse(this);
72 }
73
Brian Carlstrom1db91132013-07-12 18:05:20 -070074 private:
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070075 const unsigned int register_no_;
Dragos Sbirlea64479192013-08-01 15:38:43 -070076 const unsigned int position_; // The position of this parameter node is
77 // in the function parameter list.
Brian Carlstrom1db91132013-07-12 18:05:20 -070078};
79
Brian Carlstrom1db91132013-07-12 18:05:20 -070080class PhiInstructionNode: public InstructionNode {
81 public:
82 explicit PhiInstructionNode(int register_no):
83 InstructionNode(NULL), register_no_(register_no), definition_edges_() {}
Brian Carlstrom1db91132013-07-12 18:05:20 -070084 // Returns the register on which this phi-function is used.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070085 int GetRegisterNumber() const {
Brian Carlstrom1db91132013-07-12 18:05:20 -070086 return register_no_;
87 }
88
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070089 // Renames the use of @reg_no to refer to the instruction @definition.
Brian Carlstrom1db91132013-07-12 18:05:20 -070090 // Phi-functions are different than normal instructions in that they
91 // have multiple predecessor regions; this is why RenameToSSA has
92 // the additional parameter specifying that @parameter_id is the incoming
93 // edge for @definition, essentially creating SSA form.
94 void RenameToSSA(int reg_no, InstructionNode* definition, unsigned int predecessor_id) {
95 DCHECK(NULL != definition) << "Tried to rename to SSA using a NULL definition for "
96 << StringId() << " register " << reg_no;
97 if (definition_edges_.size() < predecessor_id+1) {
98 definition_edges_.resize(predecessor_id+1, NULL);
99 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700100 if (NULL == definition_edges_.at(predecessor_id)) {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700101 definition_edges_[predecessor_id] = new std::vector<InstructionNode*>();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700102 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700103 definition_edges_[predecessor_id]->push_back(definition);
Dragos Sbirleae2245322013-07-29 14:16:14 -0700104 definition->AddSSAUse(this);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700105 }
106
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700107 // Returns the ordered set of Instructions that define the input operands of this instruction.
108 // Precondition: SeaGraph.ConvertToSSA().
109 std::vector<InstructionNode*> GetSSAProducers() {
110 std::vector<InstructionNode*> producers;
111 for (std::vector<std::vector<InstructionNode*>*>::const_iterator
112 cit = definition_edges_.begin(); cit != definition_edges_.end(); cit++) {
113 producers.insert(producers.end(), (*cit)->begin(), (*cit)->end());
114 }
115 return producers;
116 }
117
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700118 // Returns the instruction that defines the phi register from predecessor
119 // on position @predecessor_pos. Note that the return value is vector<> just
120 // for consistency with the return value of GetSSAUses() on regular instructions,
121 // The returned vector should always have a single element because the IR is SSA.
122 std::vector<InstructionNode*>* GetSSAUses(int predecessor_pos) {
123 return definition_edges_.at(predecessor_pos);
124 }
125
126 void Accept(IRVisitor* v) {
127 v->Visit(this);
128 v->Traverse(this);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700129 }
130
131 private:
132 int register_no_;
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -0700133 // This vector has one entry for each predecessors, each with a single
134 // element, storing the id of the instruction that defines the register
135 // corresponding to this phi function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700136 std::vector<std::vector<InstructionNode*>*> definition_edges_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700137};
Brian Carlstrom7940e442013-07-12 13:46:57 -0700138
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700139// This class corresponds to a basic block in traditional compiler IRs.
140// The dataflow analysis relies on this class both during execution and
141// for storing its results.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700142class Region : public SeaNode {
143 public:
Brian Carlstrom1db91132013-07-12 18:05:20 -0700144 explicit Region():
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700145 SeaNode(), successors_(), predecessors_(), reaching_defs_size_(0),
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700146 rpo_number_(NOT_VISITED), idom_(NULL), idominated_set_(), df_(), phi_set_() {
147 string_id_ = "cluster_" + string_id_;
148 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700149 // Adds @instruction as an instruction node child in the current region.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700150 void AddChild(sea_ir::InstructionNode* instruction);
Brian Carlstrom7940e442013-07-12 13:46:57 -0700151 // Returns the last instruction node child of the current region.
152 // This child has the CFG successors pointing to the new regions.
153 SeaNode* GetLastChild() const;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700154 // Returns all the child instructions of this region, in program order.
155 std::vector<InstructionNode*>* GetInstructions() {
156 return &instructions_;
157 }
Dragos Sbirlea64479192013-08-01 15:38:43 -0700158
Brian Carlstrom7940e442013-07-12 13:46:57 -0700159 // Computes Downward Exposed Definitions for the current node.
160 void ComputeDownExposedDefs();
161 const std::map<int, sea_ir::InstructionNode*>* GetDownExposedDefs() const;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700162 // Performs one iteration of the reaching definitions algorithm
163 // and returns true if the reaching definitions set changed.
164 bool UpdateReachingDefs();
Brian Carlstrom7940e442013-07-12 13:46:57 -0700165 // Returns the set of reaching definitions for the current region.
166 std::map<int, std::set<sea_ir::InstructionNode*>* >* GetReachingDefs();
167
Brian Carlstrom1db91132013-07-12 18:05:20 -0700168 void SetRPO(int rpo) {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700169 rpo_number_ = rpo;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700170 }
171
172 int GetRPO() {
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700173 return rpo_number_;
Brian Carlstrom1db91132013-07-12 18:05:20 -0700174 }
175
176 void SetIDominator(Region* dom) {
177 idom_ = dom;
178 }
179
180 Region* GetIDominator() const {
181 return idom_;
182 }
183
184 void AddToIDominatedSet(Region* dominated) {
185 idominated_set_.insert(dominated);
186 }
187
188 const std::set<Region*>* GetIDominatedSet() {
189 return &idominated_set_;
190 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700191 // Adds @df_reg to the dominance frontier of the current region.
192 void AddToDominanceFrontier(Region* df_reg) {
193 df_.insert(df_reg);
194 }
195 // Returns the dominance frontier of the current region.
196 // Preconditions: SeaGraph.ComputeDominanceFrontier()
197 std::set<Region*>* GetDominanceFrontier() {
198 return &df_;
199 }
200 // Returns true if the region contains a phi function for @reg_no.
201 bool ContainsPhiFor(int reg_no) {
202 return (phi_set_.end() != phi_set_.find(reg_no));
203 }
204 // Returns the phi-functions from the region.
205 std::vector<PhiInstructionNode*>* GetPhiNodes() {
206 return &phi_instructions_;
207 }
208 // Adds a phi-function for @reg_no to this region.
209 // Note: The insertion order does not matter, as phi-functions
210 // are conceptually executed at the same time.
211 bool InsertPhiFor(int reg_no);
212 // Sets the phi-function uses to be as defined in @scoped_table for predecessor @@predecessor.
213 void SetPhiDefinitionsForUses(const utils::ScopedHashtable<int, InstructionNode*>* scoped_table,
214 Region* predecessor);
215
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700216 void Accept(IRVisitor* v) {
217 v->Visit(this);
218 v->Traverse(this);
219 }
220
221 void AddSuccessor(Region* successor) {
222 DCHECK(successor) << "Tried to add NULL successor to SEA node.";
223 successors_.push_back(successor);
224 return;
225 }
226 void AddPredecessor(Region* predecessor) {
227 DCHECK(predecessor) << "Tried to add NULL predecessor to SEA node.";
228 predecessors_.push_back(predecessor);
229 }
230
231 std::vector<sea_ir::Region*>* GetSuccessors() {
232 return &successors_;
233 }
234 std::vector<sea_ir::Region*>* GetPredecessors() {
235 return &predecessors_;
236 }
237
Brian Carlstrom7940e442013-07-12 13:46:57 -0700238 private:
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700239 std::vector<sea_ir::Region*> successors_; // CFG successor nodes (regions)
240 std::vector<sea_ir::Region*> predecessors_; // CFG predecessor nodes (instructions/regions)
Brian Carlstrom7940e442013-07-12 13:46:57 -0700241 std::vector<sea_ir::InstructionNode*> instructions_;
242 std::map<int, sea_ir::InstructionNode*> de_defs_;
243 std::map<int, std::set<sea_ir::InstructionNode*>* > reaching_defs_;
244 int reaching_defs_size_;
Dragos Sbirlea81f79a62013-07-23 14:31:47 -0700245 int rpo_number_; // reverse postorder number of the region
Brian Carlstrom1db91132013-07-12 18:05:20 -0700246 // Immediate dominator node.
247 Region* idom_;
248 // The set of nodes immediately dominated by the region.
249 std::set<Region*> idominated_set_;
250 // Records the dominance frontier.
251 std::set<Region*> df_;
252 // Records the set of register numbers that have phi nodes in this region.
253 std::set<int> phi_set_;
254 std::vector<PhiInstructionNode*> phi_instructions_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700255};
256
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700257// A SeaGraph instance corresponds to a source code function.
258// Its main point is to encapsulate the SEA IR representation of it
259// and acts as starting point for visitors (ex: during code generation).
260class SeaGraph: IVisitable {
Brian Carlstrom7940e442013-07-12 13:46:57 -0700261 public:
Dragos Sbirleaa3519a42013-08-07 14:41:55 -0700262 static SeaGraph* GetGraph(const art::DexFile&);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700263
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700264 CodeGenData* CompileMethod(const std::string& function_name,
Ian Rogersee39a102013-09-19 02:56:49 -0700265 const art::DexFile::CodeItem* code_item, uint16_t class_def_idx,
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700266 uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700267 // Returns all regions corresponding to this SeaGraph.
268 std::vector<Region*>* GetRegions() {
269 return &regions_;
270 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700271 // Recursively computes the reverse postorder value for @crt_bb and successors.
272 static void ComputeRPO(Region* crt_bb, int& crt_rpo);
273 // Returns the "lowest common ancestor" of @i and @j in the dominator tree.
274 static Region* Intersect(Region* i, Region* j);
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700275 // Returns the vector of parameters of the function.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700276 std::vector<SignatureNode*>* GetParameterNodes() {
277 return &parameters_;
278 }
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700279
280 const art::DexFile* GetDexFile() const {
281 return &dex_file_;
282 }
283
Dragos Sbirlea64479192013-08-01 15:38:43 -0700284 virtual void Accept(IRVisitor* visitor) {
285 visitor->Initialize(this);
286 visitor->Visit(this);
287 visitor->Traverse(this);
288 }
289
290 TypeInference* ti_;
Ian Rogersee39a102013-09-19 02:56:49 -0700291 uint16_t class_def_idx_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700292 uint32_t method_idx_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700293 uint32_t method_access_flags_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700294
Dragos Sbirlea597e46b2013-08-07 18:15:44 -0700295 protected:
Dragos Sbirlea64479192013-08-01 15:38:43 -0700296 explicit SeaGraph(const art::DexFile& df);
Dragos Sbirlea597e46b2013-08-07 18:15:44 -0700297 virtual ~SeaGraph() { }
298
299 private:
300 FRIEND_TEST(RegionsTest, Basics);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700301 // Registers @childReg as a region belonging to the SeaGraph instance.
302 void AddRegion(Region* childReg);
303 // Returns new region and registers it with the SeaGraph instance.
Brian Carlstrom7940e442013-07-12 13:46:57 -0700304 Region* GetNewRegion();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700305 // Adds a (formal) parameter node to the vector of parameters of the function.
306 void AddParameterNode(SignatureNode* parameterNode) {
307 parameters_.push_back(parameterNode);
308 }
Brian Carlstrom1db91132013-07-12 18:05:20 -0700309 // Adds a CFG edge from @src node to @dst node.
310 void AddEdge(Region* src, Region* dst) const;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700311 // Builds the non-SSA sea-ir representation of the function @code_item from @dex_file
312 // with class id @class_def_idx and method id @method_idx.
313 void BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item,
Ian Rogersee39a102013-09-19 02:56:49 -0700314 const art::DexFile& dex_file, uint16_t class_def_idx,
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700315 uint32_t method_idx, uint32_t method_access_flags);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700316 // Computes immediate dominators for each region.
317 // Precondition: ComputeMethodSeaGraph()
318 void ComputeIDominators();
319 // Computes Downward Exposed Definitions for all regions in the graph.
320 void ComputeDownExposedDefs();
321 // Computes the reaching definitions set following the equations from
322 // Cooper & Torczon, "Engineering a Compiler", second edition, page 491.
323 // Precondition: ComputeDEDefs()
324 void ComputeReachingDefs();
325 // Computes the reverse-postorder numbering for the region nodes.
326 // Precondition: ComputeDEDefs()
327 void ComputeRPO();
328 // Computes the dominance frontier for all regions in the graph,
329 // following the algorithm from
330 // Cooper & Torczon, "Engineering a Compiler", second edition, page 499.
331 // Precondition: ComputeIDominators()
332 void ComputeDominanceFrontier();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700333 // Converts the IR to semi-pruned SSA form.
Brian Carlstrom1db91132013-07-12 18:05:20 -0700334 void ConvertToSSA();
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700335 // Performs the renaming phase of the SSA transformation during ConvertToSSA() execution.
336 void RenameAsSSA();
Brian Carlstrom1db91132013-07-12 18:05:20 -0700337 // Identifies the definitions corresponding to uses for region @node
338 // by using the scoped hashtable of names @ scoped_table.
339 void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700340 // Generate LLVM IR for the method.
341 // Precondition: ConvertToSSA().
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700342 CodeGenData* GenerateLLVM(const std::string& function_name, const art::DexFile& dex_file);
343 // Inserts one SignatureNode for each argument of the function in
344 void InsertSignatureNodes(const art::DexFile::CodeItem* code_item, Region* r);
Brian Carlstrom1db91132013-07-12 18:05:20 -0700345
Brian Carlstrom7940e442013-07-12 13:46:57 -0700346 static SeaGraph graph_;
347 std::vector<Region*> regions_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700348 std::vector<SignatureNode*> parameters_;
Dragos Sbirlea6bee4452013-07-26 12:05:03 -0700349 const art::DexFile& dex_file_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -0700350 const art::DexFile::CodeItem* code_item_;
Brian Carlstrom7940e442013-07-12 13:46:57 -0700351};
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700352} // namespace sea_ir
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -0700353#endif // ART_COMPILER_SEA_IR_IR_SEA_H_