blob: 5d787c46a0b5b042a5d5c6fd4ce4db78845fb631 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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
buzbeeeaf09bc2012-11-15 14:51:41 -080017#include "compiler_internals.h"
buzbeeefc63692012-11-14 16:31:52 -080018#include "dataflow.h"
buzbee67bf8852011-08-17 17:51:35 -070019
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080020namespace art {
21
buzbeee5f01222012-06-14 15:19:35 -070022// Make sure iterative dfs recording matches old recursive version
23//#define TEST_DFS
24
buzbeeaad94382012-11-21 07:40:50 -080025static BasicBlock* NeedsVisit(BasicBlock* bb) {
buzbeee5f01222012-06-14 15:19:35 -070026 if (bb != NULL) {
27 if (bb->visited || bb->hidden) {
28 bb = NULL;
29 }
30 }
31 return bb;
32}
33
buzbee52a77fc2012-11-20 19:50:46 -080034static BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb)
buzbeee5f01222012-06-14 15:19:35 -070035{
buzbeefa57c472012-11-21 12:06:18 -080036 BasicBlock* res = NeedsVisit(bb->fall_through);
buzbeee5f01222012-06-14 15:19:35 -070037 if (res == NULL) {
buzbee52a77fc2012-11-20 19:50:46 -080038 res = NeedsVisit(bb->taken);
buzbeee5f01222012-06-14 15:19:35 -070039 if (res == NULL) {
buzbeefa57c472012-11-21 12:06:18 -080040 if (bb->successor_block_list.block_list_type != kNotUsed) {
buzbeee5f01222012-06-14 15:19:35 -070041 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -080042 GrowableListIteratorInit(&bb->successor_block_list.blocks,
buzbeee5f01222012-06-14 15:19:35 -070043 &iterator);
44 while (true) {
buzbeecbd6d442012-11-17 14:11:25 -080045 SuccessorBlockInfo *sbi = reinterpret_cast<SuccessorBlockInfo*>
buzbee52a77fc2012-11-20 19:50:46 -080046 (GrowableListIteratorNext(&iterator));
buzbeee5f01222012-06-14 15:19:35 -070047 if (sbi == NULL) break;
buzbee52a77fc2012-11-20 19:50:46 -080048 res = NeedsVisit(sbi->block);
buzbeee5f01222012-06-14 15:19:35 -070049 if (res != NULL) break;
50 }
51 }
52 }
53 }
54 return res;
55}
56
buzbeefa57c472012-11-21 12:06:18 -080057static void MarkPreOrder(CompilationUnit* cu, BasicBlock* block)
buzbeee5f01222012-06-14 15:19:35 -070058{
59 block->visited = true;
buzbeefa57c472012-11-21 12:06:18 -080060 /* Enqueue the pre_order block id */
61 InsertGrowableList(cu, &cu->dfs_order, block->id);
buzbeee5f01222012-06-14 15:19:35 -070062}
63
buzbeefa57c472012-11-21 12:06:18 -080064static void RecordDFSOrders(CompilationUnit* cu, BasicBlock* block)
buzbee67bf8852011-08-17 17:51:35 -070065{
buzbeee5f01222012-06-14 15:19:35 -070066 std::vector<BasicBlock*> succ;
buzbeefa57c472012-11-21 12:06:18 -080067 MarkPreOrder(cu, block);
buzbeee5f01222012-06-14 15:19:35 -070068 succ.push_back(block);
69 while (!succ.empty()) {
70 BasicBlock* curr = succ.back();
buzbeefa57c472012-11-21 12:06:18 -080071 BasicBlock* next_successor = NextUnvisitedSuccessor(curr);
72 if (next_successor != NULL) {
73 MarkPreOrder(cu, next_successor);
74 succ.push_back(next_successor);
buzbeee5f01222012-06-14 15:19:35 -070075 continue;
76 }
buzbeefa57c472012-11-21 12:06:18 -080077 curr->dfs_id = cu->dfs_post_order.num_used;
78 InsertGrowableList(cu, &cu->dfs_post_order, curr->id);
buzbeee5f01222012-06-14 15:19:35 -070079 succ.pop_back();
80 }
81}
82
83#if defined(TEST_DFS)
buzbeefa57c472012-11-21 12:06:18 -080084/* Enter the node to the dfs_order list then visit its successors */
85static void RecursiveRecordDFSOrders(CompilationUnit* cu, BasicBlock* block)
buzbeee5f01222012-06-14 15:19:35 -070086{
buzbee67bf8852011-08-17 17:51:35 -070087
Bill Buzbeea114add2012-05-03 15:00:40 -070088 if (block->visited || block->hidden) return;
89 block->visited = true;
buzbee67bf8852011-08-17 17:51:35 -070090
Bill Buzbeea114add2012-05-03 15:00:40 -070091 // Can this block be reached only via previous block fallthrough?
buzbeefa57c472012-11-21 12:06:18 -080092 if ((block->block_type == kDalvikByteCode) &&
93 (block->predecessors->num_used == 1)) {
94 DCHECK_GE(cu->dfs_order.num_used, 1U);
95 int prev_idx = cu->dfs_order.num_used - 1;
96 int prev_id = cu->dfs_order.elem_list[prev_idx];
97 BasicBlock* pred_bb = (BasicBlock*)block->predecessors->elem_list[0];
Bill Buzbeea114add2012-05-03 15:00:40 -070098 }
buzbee3d661942012-03-14 17:37:27 -070099
buzbeefa57c472012-11-21 12:06:18 -0800100 /* Enqueue the pre_order block id */
101 InsertGrowableList(cu, &cu->dfs_order, block->id);
buzbee67bf8852011-08-17 17:51:35 -0700102
buzbeefa57c472012-11-21 12:06:18 -0800103 if (block->fall_through) {
104 RecursiveRecordDFSOrders(cu, block->fall_through);
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 }
buzbeefa57c472012-11-21 12:06:18 -0800106 if (block->taken) RecursiveRecordDFSOrders(cu, block->taken);
107 if (block->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700108 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800109 GrowableListIteratorInit(&block->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 &iterator);
111 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800112 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800113 (SuccessorBlockInfo *) GrowableListIteratorNext(&iterator);
buzbeefa57c472012-11-21 12:06:18 -0800114 if (successor_block_info == NULL) break;
115 BasicBlock* succ_bb = successor_block_info->block;
116 RecursiveRecordDFSOrders(cu, succ_bb);
buzbeee1965672012-03-11 18:39:19 -0700117 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 }
buzbee5b537102012-01-17 17:33:47 -0800119
buzbeefa57c472012-11-21 12:06:18 -0800120 /* Record postorder in basic block and enqueue normal id in dfs_post_order */
121 block->dfs_id = cu->dfs_post_order.num_used;
122 InsertGrowableList(cu, &cu->dfs_post_order, block->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700123 return;
buzbee67bf8852011-08-17 17:51:35 -0700124}
buzbeee5f01222012-06-14 15:19:35 -0700125#endif
buzbee67bf8852011-08-17 17:51:35 -0700126
buzbee5b537102012-01-17 17:33:47 -0800127/* Sort the blocks by the Depth-First-Search */
buzbeefa57c472012-11-21 12:06:18 -0800128static void ComputeDFSOrders(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700129{
buzbeefa57c472012-11-21 12:06:18 -0800130 /* Initialize or reset the DFS pre_order list */
131 if (cu->dfs_order.elem_list == NULL) {
132 CompilerInitGrowableList(cu, &cu->dfs_order, cu->num_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 kListDfsOrder);
134 } else {
135 /* Just reset the used length on the counter */
buzbeefa57c472012-11-21 12:06:18 -0800136 cu->dfs_order.num_used = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 }
buzbee67bf8852011-08-17 17:51:35 -0700138
buzbeefa57c472012-11-21 12:06:18 -0800139 /* Initialize or reset the DFS post_order list */
140 if (cu->dfs_post_order.elem_list == NULL) {
141 CompilerInitGrowableList(cu, &cu->dfs_post_order, cu->num_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 kListDfsPostOrder);
143 } else {
144 /* Just reset the used length on the counter */
buzbeefa57c472012-11-21 12:06:18 -0800145 cu->dfs_post_order.num_used = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbee5b537102012-01-17 17:33:47 -0800147
buzbeee5f01222012-06-14 15:19:35 -0700148#if defined(TEST_DFS)
149 // Reset visited flags
buzbeefa57c472012-11-21 12:06:18 -0800150 DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
151 kAllNodes, false /* is_iterative */);
buzbeee5f01222012-06-14 15:19:35 -0700152 // Record pre and post order dfs
buzbeefa57c472012-11-21 12:06:18 -0800153 RecursiveRecordDFSOrders(cu, cu->entry_block);
buzbeee5f01222012-06-14 15:19:35 -0700154 // Copy the results for later comparison and reset the lists
buzbeefa57c472012-11-21 12:06:18 -0800155 GrowableList recursive_dfs_order;
156 GrowableList recursive_dfs_post_order;
157 CompilerInitGrowableList(cu, &recursive_dfs_order, cu->dfs_order.num_used,
buzbeee5f01222012-06-14 15:19:35 -0700158 kListDfsOrder);
buzbeefa57c472012-11-21 12:06:18 -0800159 for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
160 InsertGrowableList(cu, &recursive_dfs_order,
161 cu->dfs_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700162 }
buzbeefa57c472012-11-21 12:06:18 -0800163 cu->dfs_order.num_used = 0;
164 CompilerInitGrowableList(cu, &recursive_dfs_post_order,
165 cu->dfs_post_order.num_used, kListDfsOrder);
166 for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
167 InsertGrowableList(cu, &recursive_dfs_post_order,
168 cu->dfs_post_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700169 }
buzbeefa57c472012-11-21 12:06:18 -0800170 cu->dfs_post_order.num_used = 0;
buzbeee5f01222012-06-14 15:19:35 -0700171#endif
buzbee67bf8852011-08-17 17:51:35 -0700172
buzbeee5f01222012-06-14 15:19:35 -0700173 // Reset visited flags from all nodes
buzbeefa57c472012-11-21 12:06:18 -0800174 DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
175 kAllNodes, false /* is_iterative */);
buzbeee5f01222012-06-14 15:19:35 -0700176 // Record dfs orders
buzbeefa57c472012-11-21 12:06:18 -0800177 RecordDFSOrders(cu, cu->entry_block);
buzbeee5f01222012-06-14 15:19:35 -0700178
179#if defined(TEST_DFS)
180 bool mismatch = false;
buzbeefa57c472012-11-21 12:06:18 -0800181 mismatch |= (cu->dfs_order.num_used != recursive_dfs_order.num_used);
182 for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
183 mismatch |= (cu->dfs_order.elem_list[i] !=
184 recursive_dfs_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700185 }
buzbeefa57c472012-11-21 12:06:18 -0800186 mismatch |= (cu->dfs_post_order.num_used != recursive_dfs_post_order.num_used);
187 for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
188 mismatch |= (cu->dfs_post_order.elem_list[i] !=
189 recursive_dfs_post_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700190 }
191 if (mismatch) {
192 LOG(INFO) << "Mismatch for "
buzbeefa57c472012-11-21 12:06:18 -0800193 << PrettyMethod(cu->method_idx, *cu->dex_file);
buzbeee5f01222012-06-14 15:19:35 -0700194 LOG(INFO) << "New dfs";
buzbeefa57c472012-11-21 12:06:18 -0800195 for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
196 LOG(INFO) << i << " - " << cu->dfs_order.elem_list[i];
buzbeee5f01222012-06-14 15:19:35 -0700197 }
198 LOG(INFO) << "Recursive dfs";
buzbeefa57c472012-11-21 12:06:18 -0800199 for (unsigned int i = 0; i < recursive_dfs_order.num_used; i++) {
200 LOG(INFO) << i << " - " << recursive_dfs_order.elem_list[i];
buzbeee5f01222012-06-14 15:19:35 -0700201 }
202 LOG(INFO) << "New post dfs";
buzbeefa57c472012-11-21 12:06:18 -0800203 for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
204 LOG(INFO) << i << " - " << cu->dfs_post_order.elem_list[i];
buzbeee5f01222012-06-14 15:19:35 -0700205 }
206 LOG(INFO) << "Recursive post dfs";
buzbeefa57c472012-11-21 12:06:18 -0800207 for (unsigned int i = 0; i < recursive_dfs_post_order.num_used; i++) {
208 LOG(INFO) << i << " - " << recursive_dfs_post_order.elem_list[i];
buzbeee5f01222012-06-14 15:19:35 -0700209 }
210 }
buzbeefa57c472012-11-21 12:06:18 -0800211 CHECK_EQ(cu->dfs_order.num_used, recursive_dfs_order.num_used);
212 for (unsigned int i = 0; i < cu->dfs_order.num_used; i++) {
213 CHECK_EQ(cu->dfs_order.elem_list[i], recursive_dfs_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700214 }
buzbeefa57c472012-11-21 12:06:18 -0800215 CHECK_EQ(cu->dfs_post_order.num_used, recursive_dfs_post_order.num_used);
216 for (unsigned int i = 0; i < cu->dfs_post_order.num_used; i++) {
217 CHECK_EQ(cu->dfs_post_order.elem_list[i],
218 recursive_dfs_post_order.elem_list[i]);
buzbeee5f01222012-06-14 15:19:35 -0700219 }
220#endif
221
buzbeefa57c472012-11-21 12:06:18 -0800222 cu->num_reachable_blocks = cu->dfs_order.num_used;
buzbee67bf8852011-08-17 17:51:35 -0700223}
224
225/*
226 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
227 * register idx is defined in BasicBlock bb.
228 */
buzbeefa57c472012-11-21 12:06:18 -0800229static bool FillDefBlockMatrix(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700230{
buzbeefa57c472012-11-21 12:06:18 -0800231 if (bb->data_flow_info == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -0700232
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700234
buzbeefa57c472012-11-21 12:06:18 -0800235 BitVectorIteratorInit(bb->data_flow_info->def_v, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800237 int idx = BitVectorIteratorNext(&iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 if (idx == -1) break;
239 /* Block bb defines register idx */
buzbeefa57c472012-11-21 12:06:18 -0800240 SetBit(cu, cu->def_block_matrix[idx], bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 }
242 return true;
buzbee67bf8852011-08-17 17:51:35 -0700243}
244
buzbeefa57c472012-11-21 12:06:18 -0800245static void ComputeDefBlockMatrix(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700246{
buzbeefa57c472012-11-21 12:06:18 -0800247 int num_registers = cu->num_dalvik_registers;
248 /* Allocate num_dalvik_registers bit vector pointers */
249 cu->def_block_matrix = static_cast<ArenaBitVector**>
250 (NewMem(cu, sizeof(ArenaBitVector *) * num_registers, true, kAllocDFInfo));
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 int i;
buzbee67bf8852011-08-17 17:51:35 -0700252
buzbeefa57c472012-11-21 12:06:18 -0800253 /* Initialize num_register vectors with num_blocks bits each */
254 for (i = 0; i < num_registers; i++) {
255 cu->def_block_matrix[i] = AllocBitVector(cu, cu->num_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 false, kBitMapBMatrix);
257 }
buzbeefa57c472012-11-21 12:06:18 -0800258 DataFlowAnalysisDispatcher(cu, FindLocalLiveIn,
259 kAllNodes, false /* is_iterative */);
260 DataFlowAnalysisDispatcher(cu, FillDefBlockMatrix,
261 kAllNodes, false /* is_iterative */);
buzbee67bf8852011-08-17 17:51:35 -0700262
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 /*
264 * Also set the incoming parameters as defs in the entry block.
265 * Only need to handle the parameters for the outer method.
266 */
buzbeefa57c472012-11-21 12:06:18 -0800267 int num_regs = cu->num_dalvik_registers;
268 int in_reg = num_regs - cu->num_ins;
269 for (; in_reg < num_regs; in_reg++) {
270 SetBit(cu, cu->def_block_matrix[in_reg], cu->entry_block->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 }
buzbee67bf8852011-08-17 17:51:35 -0700272}
273
274/* Compute the post-order traversal of the CFG */
buzbeefa57c472012-11-21 12:06:18 -0800275static void ComputeDomPostOrderTraversal(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700276{
buzbeefa57c472012-11-21 12:06:18 -0800277 ArenaBitVectorIterator bv_iterator;
278 BitVectorIteratorInit(bb->i_dominated, &bv_iterator);
279 GrowableList* block_list = &cu->block_list;
buzbee67bf8852011-08-17 17:51:35 -0700280
Bill Buzbeea114add2012-05-03 15:00:40 -0700281 /* Iterate through the dominated blocks first */
282 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800283 //TUNING: hot call to BitVectorIteratorNext
buzbeefa57c472012-11-21 12:06:18 -0800284 int bb_idx = BitVectorIteratorNext(&bv_iterator);
285 if (bb_idx == -1) break;
286 BasicBlock* dominated_bb =
287 reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, bb_idx));
288 ComputeDomPostOrderTraversal(cu, dominated_bb);
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 }
buzbee67bf8852011-08-17 17:51:35 -0700290
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 /* Enter the current block id */
buzbeefa57c472012-11-21 12:06:18 -0800292 InsertGrowableList(cu, &cu->dom_post_order_traversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700293
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 /* hacky loop detection */
buzbee52a77fc2012-11-20 19:50:46 -0800295 if (bb->taken && IsBitSet(bb->dominators, bb->taken->id)) {
buzbeefa57c472012-11-21 12:06:18 -0800296 cu->has_loop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 }
buzbee67bf8852011-08-17 17:51:35 -0700298}
299
buzbeefa57c472012-11-21 12:06:18 -0800300static void CheckForDominanceFrontier(CompilationUnit* cu, BasicBlock* dom_bb,
301 const BasicBlock* succ_bb)
buzbee67bf8852011-08-17 17:51:35 -0700302{
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 /*
304 * TODO - evaluate whether phi will ever need to be inserted into exit
305 * blocks.
306 */
buzbeefa57c472012-11-21 12:06:18 -0800307 if (succ_bb->i_dom != dom_bb &&
308 succ_bb->block_type == kDalvikByteCode &&
309 succ_bb->hidden == false) {
310 SetBit(cu, dom_bb->dom_frontier, succ_bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700311 }
buzbee67bf8852011-08-17 17:51:35 -0700312}
313
314/* Worker function to compute the dominance frontier */
buzbeefa57c472012-11-21 12:06:18 -0800315static bool ComputeDominanceFrontier(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700316{
buzbeefa57c472012-11-21 12:06:18 -0800317 GrowableList* block_list = &cu->block_list;
buzbee67bf8852011-08-17 17:51:35 -0700318
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 /* Calculate DF_local */
320 if (bb->taken) {
buzbeefa57c472012-11-21 12:06:18 -0800321 CheckForDominanceFrontier(cu, bb, bb->taken);
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 }
buzbeefa57c472012-11-21 12:06:18 -0800323 if (bb->fall_through) {
324 CheckForDominanceFrontier(cu, bb, bb->fall_through);
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 }
buzbeefa57c472012-11-21 12:06:18 -0800326 if (bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800328 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 &iterator);
330 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800331 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800332 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800333 if (successor_block_info == NULL) break;
334 BasicBlock* succ_bb = successor_block_info->block;
335 CheckForDominanceFrontier(cu, bb, succ_bb);
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 }
337 }
buzbee67bf8852011-08-17 17:51:35 -0700338
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 /* Calculate DF_up */
buzbeefa57c472012-11-21 12:06:18 -0800340 ArenaBitVectorIterator bv_iterator;
341 BitVectorIteratorInit(bb->i_dominated, &bv_iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800343 //TUNING: hot call to BitVectorIteratorNext
buzbeefa57c472012-11-21 12:06:18 -0800344 int dominated_idx = BitVectorIteratorNext(&bv_iterator);
345 if (dominated_idx == -1) break;
346 BasicBlock* dominated_bb =
347 reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, dominated_idx));
348 ArenaBitVectorIterator df_iterator;
349 BitVectorIteratorInit(dominated_bb->dom_frontier, &df_iterator);
buzbee67bf8852011-08-17 17:51:35 -0700350 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800351 //TUNING: hot call to BitVectorIteratorNext
buzbeefa57c472012-11-21 12:06:18 -0800352 int df_up_idx = BitVectorIteratorNext(&df_iterator);
353 if (df_up_idx == -1) break;
354 BasicBlock* df_up_block =
355 reinterpret_cast<BasicBlock*>( GrowableListGetElement(block_list, df_up_idx));
356 CheckForDominanceFrontier(cu, bb, df_up_block);
buzbee67bf8852011-08-17 17:51:35 -0700357 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 }
buzbee67bf8852011-08-17 17:51:35 -0700359
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 return true;
buzbee67bf8852011-08-17 17:51:35 -0700361}
362
363/* Worker function for initializing domination-related data structures */
buzbeefa57c472012-11-21 12:06:18 -0800364static bool InitializeDominationInfo(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700365{
buzbeefa57c472012-11-21 12:06:18 -0800366 int num_total_blocks = cu->block_list.num_used;
buzbee67bf8852011-08-17 17:51:35 -0700367
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 if (bb->dominators == NULL ) {
buzbeefa57c472012-11-21 12:06:18 -0800369 bb->dominators = AllocBitVector(cu, num_total_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 false /* expandable */,
371 kBitMapDominators);
buzbeefa57c472012-11-21 12:06:18 -0800372 bb->i_dominated = AllocBitVector(cu, num_total_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 false /* expandable */,
374 kBitMapIDominated);
buzbeefa57c472012-11-21 12:06:18 -0800375 bb->dom_frontier = AllocBitVector(cu, num_total_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700376 false /* expandable */,
377 kBitMapDomFrontier);
378 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800379 ClearAllBits(bb->dominators);
buzbeefa57c472012-11-21 12:06:18 -0800380 ClearAllBits(bb->i_dominated);
381 ClearAllBits(bb->dom_frontier);
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 }
383 /* Set all bits in the dominator vector */
buzbeefa57c472012-11-21 12:06:18 -0800384 SetInitialBits(bb->dominators, num_total_blocks);
buzbee67bf8852011-08-17 17:51:35 -0700385
Bill Buzbeea114add2012-05-03 15:00:40 -0700386 return true;
buzbee67bf8852011-08-17 17:51:35 -0700387}
388
buzbee5b537102012-01-17 17:33:47 -0800389/*
390 * Worker function to compute each block's dominators. This implementation
391 * is only used when kDebugVerifyDataflow is active and should compute
buzbee52a77fc2012-11-20 19:50:46 -0800392 * the same dominator sets as ComputeBlockDominiators.
buzbee5b537102012-01-17 17:33:47 -0800393 */
buzbeefa57c472012-11-21 12:06:18 -0800394static bool SlowComputeBlockDominators(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700395{
buzbeefa57c472012-11-21 12:06:18 -0800396 GrowableList* block_list = &cu->block_list;
397 int num_total_blocks = block_list->num_used;
398 ArenaBitVector* temp_block_v = cu->temp_block_v;
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700400
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 /*
402 * The dominator of the entry block has been preset to itself and we need
403 * to skip the calculation here.
404 */
buzbeefa57c472012-11-21 12:06:18 -0800405 if (bb == cu->entry_block) return false;
buzbee67bf8852011-08-17 17:51:35 -0700406
buzbeefa57c472012-11-21 12:06:18 -0800407 SetInitialBits(temp_block_v, num_total_blocks);
buzbee67bf8852011-08-17 17:51:35 -0700408
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 /* Iterate through the predecessors */
buzbee52a77fc2012-11-20 19:50:46 -0800410 GrowableListIteratorInit(bb->predecessors, &iter);
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800412 BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
413 if (!pred_bb) break;
414 /* temp_block_v = temp_block_v ^ dominators */
415 if (pred_bb->dominators != NULL) {
416 IntersectBitVectors(temp_block_v, temp_block_v, pred_bb->dominators);
buzbee67bf8852011-08-17 17:51:35 -0700417 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 }
buzbeefa57c472012-11-21 12:06:18 -0800419 SetBit(cu, temp_block_v, bb->id);
420 if (CompareBitVectors(temp_block_v, bb->dominators)) {
421 CopyBitVector(bb->dominators, temp_block_v);
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 return true;
423 }
424 return false;
buzbee67bf8852011-08-17 17:51:35 -0700425}
426
buzbee5b537102012-01-17 17:33:47 -0800427/*
428 * Worker function to compute the idom. This implementation is only
429 * used when kDebugVerifyDataflow is active and should compute the
buzbeefa57c472012-11-21 12:06:18 -0800430 * same i_dom as ComputeblockIDom.
buzbee5b537102012-01-17 17:33:47 -0800431 */
buzbeefa57c472012-11-21 12:06:18 -0800432static bool SlowComputeBlockIDom(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700433{
buzbeefa57c472012-11-21 12:06:18 -0800434 GrowableList* block_list = &cu->block_list;
435 ArenaBitVector* temp_block_v = cu->temp_block_v;
436 ArenaBitVectorIterator bv_iterator;
437 BasicBlock* i_dom;
buzbee67bf8852011-08-17 17:51:35 -0700438
buzbeefa57c472012-11-21 12:06:18 -0800439 if (bb == cu->entry_block) return false;
buzbee67bf8852011-08-17 17:51:35 -0700440
buzbeefa57c472012-11-21 12:06:18 -0800441 CopyBitVector(temp_block_v, bb->dominators);
442 ClearBit(temp_block_v, bb->id);
443 BitVectorIteratorInit(temp_block_v, &bv_iterator);
buzbee67bf8852011-08-17 17:51:35 -0700444
Bill Buzbeea114add2012-05-03 15:00:40 -0700445 /* Should not see any dead block */
buzbeefa57c472012-11-21 12:06:18 -0800446 DCHECK_NE(CountSetBits(temp_block_v), 0);
447 if (CountSetBits(temp_block_v) == 1) {
448 i_dom = reinterpret_cast<BasicBlock*>
449 (GrowableListGetElement(block_list, BitVectorIteratorNext(&bv_iterator)));
450 bb->i_dom = i_dom;
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 } else {
buzbeefa57c472012-11-21 12:06:18 -0800452 int i_dom_idx = BitVectorIteratorNext(&bv_iterator);
453 DCHECK_NE(i_dom_idx, -1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800455 int next_dom = BitVectorIteratorNext(&bv_iterator);
456 if (next_dom == -1) break;
457 BasicBlock* next_dom_bb =
458 reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, next_dom));
459 /* i_dom dominates next_dom - set new i_dom */
460 if (IsBitSet(next_dom_bb->dominators, i_dom_idx)) {
461 i_dom_idx = next_dom;
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 }
buzbee67bf8852011-08-17 17:51:35 -0700463
buzbee67bf8852011-08-17 17:51:35 -0700464 }
buzbeefa57c472012-11-21 12:06:18 -0800465 i_dom = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, i_dom_idx));
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 /* Set the immediate dominator block for bb */
buzbeefa57c472012-11-21 12:06:18 -0800467 bb->i_dom = i_dom;
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 }
buzbeefa57c472012-11-21 12:06:18 -0800469 /* Add bb to the i_dominated set of the immediate dominator block */
470 SetBit(cu, i_dom->i_dominated, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 return true;
buzbee67bf8852011-08-17 17:51:35 -0700472}
473
buzbee5b537102012-01-17 17:33:47 -0800474/*
buzbeefa57c472012-11-21 12:06:18 -0800475 * Walk through the ordered i_dom list until we reach common parent.
476 * Given the ordering of i_dom_list, this common parent represents the
buzbee5b537102012-01-17 17:33:47 -0800477 * last element of the intersection of block1 and block2 dominators.
478 */
buzbeefa57c472012-11-21 12:06:18 -0800479static int FindCommonParent(CompilationUnit *cu, int block1, int block2)
buzbee5b537102012-01-17 17:33:47 -0800480{
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 while (block1 != block2) {
482 while (block1 < block2) {
buzbeefa57c472012-11-21 12:06:18 -0800483 block1 = cu->i_dom_list[block1];
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 DCHECK_NE(block1, NOTVISITED);
buzbee5b537102012-01-17 17:33:47 -0800485 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 while (block2 < block1) {
buzbeefa57c472012-11-21 12:06:18 -0800487 block2 = cu->i_dom_list[block2];
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 DCHECK_NE(block2, NOTVISITED);
489 }
490 }
491 return block1;
buzbee5b537102012-01-17 17:33:47 -0800492}
493
494/* Worker function to compute each block's immediate dominator */
buzbeefa57c472012-11-21 12:06:18 -0800495static bool ComputeblockIDom(CompilationUnit* cu, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800496{
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 GrowableListIterator iter;
498 int idom = -1;
buzbee5b537102012-01-17 17:33:47 -0800499
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 /* Special-case entry block */
buzbeefa57c472012-11-21 12:06:18 -0800501 if (bb == cu->entry_block) {
buzbee5b537102012-01-17 17:33:47 -0800502 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 }
504
505 /* Iterate through the predecessors */
buzbee52a77fc2012-11-20 19:50:46 -0800506 GrowableListIteratorInit(bb->predecessors, &iter);
Bill Buzbeea114add2012-05-03 15:00:40 -0700507
508 /* Find the first processed predecessor */
509 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800510 BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
511 CHECK(pred_bb != NULL);
512 if (cu->i_dom_list[pred_bb->dfs_id] != NOTVISITED) {
513 idom = pred_bb->dfs_id;
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 }
516 }
517
518 /* Scan the rest of the predecessors */
519 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800520 BasicBlock* pred_bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
521 if (!pred_bb) break;
522 if (cu->i_dom_list[pred_bb->dfs_id] == NOTVISITED) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 continue;
524 } else {
buzbeefa57c472012-11-21 12:06:18 -0800525 idom = FindCommonParent(cu, pred_bb->dfs_id, idom);
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 }
527 }
528
529 DCHECK_NE(idom, NOTVISITED);
530
531 /* Did something change? */
buzbeefa57c472012-11-21 12:06:18 -0800532 if (cu->i_dom_list[bb->dfs_id] != idom) {
533 cu->i_dom_list[bb->dfs_id] = idom;
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 return true;
535 }
536 return false;
buzbee5b537102012-01-17 17:33:47 -0800537}
538
539/* Worker function to compute each block's domintors */
buzbeefa57c472012-11-21 12:06:18 -0800540static bool ComputeBlockDominiators(CompilationUnit* cu, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800541{
buzbeefa57c472012-11-21 12:06:18 -0800542 if (bb == cu->entry_block) {
buzbee52a77fc2012-11-20 19:50:46 -0800543 ClearAllBits(bb->dominators);
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 } else {
buzbeefa57c472012-11-21 12:06:18 -0800545 CopyBitVector(bb->dominators, bb->i_dom->dominators);
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 }
buzbeefa57c472012-11-21 12:06:18 -0800547 SetBit(cu, bb->dominators, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 return false;
buzbee5b537102012-01-17 17:33:47 -0800549}
550
buzbeefa57c472012-11-21 12:06:18 -0800551static bool SetDominators(CompilationUnit* cu, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800552{
buzbeefa57c472012-11-21 12:06:18 -0800553 if (bb != cu->entry_block) {
554 int idom_dfs_idx = cu->i_dom_list[bb->dfs_id];
555 DCHECK_NE(idom_dfs_idx, NOTVISITED);
556 int i_dom_idx = cu->dfs_post_order.elem_list[idom_dfs_idx];
557 BasicBlock* i_dom =
558 reinterpret_cast<BasicBlock*>(GrowableListGetElement(&cu->block_list, i_dom_idx));
559 if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
560 DCHECK_EQ(bb->i_dom->id, i_dom->id);
buzbee5b537102012-01-17 17:33:47 -0800561 }
buzbeefa57c472012-11-21 12:06:18 -0800562 bb->i_dom = i_dom;
563 /* Add bb to the i_dominated set of the immediate dominator block */
564 SetBit(cu, i_dom->i_dominated, bb->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 }
566 return false;
buzbee5b537102012-01-17 17:33:47 -0800567}
568
buzbee67bf8852011-08-17 17:51:35 -0700569/* Compute dominators, immediate dominator, and dominance fronter */
buzbeefa57c472012-11-21 12:06:18 -0800570static void ComputeDominators(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700571{
buzbeefa57c472012-11-21 12:06:18 -0800572 int num_reachable_blocks = cu->num_reachable_blocks;
573 int num_total_blocks = cu->block_list.num_used;
buzbee67bf8852011-08-17 17:51:35 -0700574
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 /* Initialize domination-related data structures */
buzbeefa57c472012-11-21 12:06:18 -0800576 DataFlowAnalysisDispatcher(cu, InitializeDominationInfo,
577 kReachableNodes, false /* is_iterative */);
buzbee67bf8852011-08-17 17:51:35 -0700578
buzbeefa57c472012-11-21 12:06:18 -0800579 /* Initalize & Clear i_dom_list */
580 if (cu->i_dom_list == NULL) {
581 cu->i_dom_list = static_cast<int*>(NewMem(cu, sizeof(int) * num_reachable_blocks,
buzbeecbd6d442012-11-17 14:11:25 -0800582 false, kAllocDFInfo));
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 }
buzbeefa57c472012-11-21 12:06:18 -0800584 for (int i = 0; i < num_reachable_blocks; i++) {
585 cu->i_dom_list[i] = NOTVISITED;
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 }
buzbee5b537102012-01-17 17:33:47 -0800587
buzbeefa57c472012-11-21 12:06:18 -0800588 /* For post-order, last block is entry block. Set its i_dom to istelf */
589 DCHECK_EQ(cu->entry_block->dfs_id, num_reachable_blocks-1);
590 cu->i_dom_list[cu->entry_block->dfs_id] = cu->entry_block->dfs_id;
buzbee5b537102012-01-17 17:33:47 -0800591
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 /* Compute the immediate dominators */
buzbeefa57c472012-11-21 12:06:18 -0800593 DataFlowAnalysisDispatcher(cu, ComputeblockIDom,
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 kReversePostOrderTraversal,
buzbeefa57c472012-11-21 12:06:18 -0800595 true /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700596
597 /* Set the dominator for the root node */
buzbeefa57c472012-11-21 12:06:18 -0800598 ClearAllBits(cu->entry_block->dominators);
599 SetBit(cu, cu->entry_block->dominators, cu->entry_block->id);
Bill Buzbeea114add2012-05-03 15:00:40 -0700600
buzbeefa57c472012-11-21 12:06:18 -0800601 if (cu->temp_block_v == NULL) {
602 cu->temp_block_v = AllocBitVector(cu, num_total_blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 false /* expandable */,
604 kBitMapTmpBlockV);
605 } else {
buzbeefa57c472012-11-21 12:06:18 -0800606 ClearAllBits(cu->temp_block_v);
Bill Buzbeea114add2012-05-03 15:00:40 -0700607 }
buzbeefa57c472012-11-21 12:06:18 -0800608 cu->entry_block->i_dom = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700609
610 /* For testing, compute sets using alternate mechanism */
buzbeefa57c472012-11-21 12:06:18 -0800611 if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 // Use alternate mechanism to compute dominators for comparison
buzbeefa57c472012-11-21 12:06:18 -0800613 DataFlowAnalysisDispatcher(cu, SlowComputeBlockDominators,
Bill Buzbeea114add2012-05-03 15:00:40 -0700614 kPreOrderDFSTraversal,
buzbeefa57c472012-11-21 12:06:18 -0800615 true /* is_iterative */);
buzbee5b537102012-01-17 17:33:47 -0800616
buzbeefa57c472012-11-21 12:06:18 -0800617 DataFlowAnalysisDispatcher(cu, SlowComputeBlockIDom,
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 kReachableNodes,
buzbeefa57c472012-11-21 12:06:18 -0800619 false /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 }
buzbee67bf8852011-08-17 17:51:35 -0700621
buzbeefa57c472012-11-21 12:06:18 -0800622 DataFlowAnalysisDispatcher(cu, SetDominators,
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 kReachableNodes,
buzbeefa57c472012-11-21 12:06:18 -0800624 false /* is_iterative */);
buzbee5b537102012-01-17 17:33:47 -0800625
buzbeefa57c472012-11-21 12:06:18 -0800626 DataFlowAnalysisDispatcher(cu, ComputeBlockDominiators,
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 kReversePostOrderTraversal,
buzbeefa57c472012-11-21 12:06:18 -0800628 false /* is_iterative */);
buzbee5b537102012-01-17 17:33:47 -0800629
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 /*
631 * Now go ahead and compute the post order traversal based on the
buzbeefa57c472012-11-21 12:06:18 -0800632 * i_dominated sets.
Bill Buzbeea114add2012-05-03 15:00:40 -0700633 */
buzbeefa57c472012-11-21 12:06:18 -0800634 if (cu->dom_post_order_traversal.elem_list == NULL) {
635 CompilerInitGrowableList(cu, &cu->dom_post_order_traversal,
636 num_reachable_blocks, kListDomPostOrderTraversal);
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 } else {
buzbeefa57c472012-11-21 12:06:18 -0800638 cu->dom_post_order_traversal.num_used = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 }
buzbee5b537102012-01-17 17:33:47 -0800640
buzbeefa57c472012-11-21 12:06:18 -0800641 ComputeDomPostOrderTraversal(cu, cu->entry_block);
642 DCHECK_EQ(cu->dom_post_order_traversal.num_used, static_cast<unsigned>(cu->num_reachable_blocks));
buzbee5b537102012-01-17 17:33:47 -0800643
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 /* Now compute the dominance frontier for each block */
buzbeefa57c472012-11-21 12:06:18 -0800645 DataFlowAnalysisDispatcher(cu, ComputeDominanceFrontier,
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 kPostOrderDOMTraversal,
buzbeefa57c472012-11-21 12:06:18 -0800647 false /* is_iterative */);
buzbee67bf8852011-08-17 17:51:35 -0700648}
649
650/*
651 * Perform dest U= src1 ^ ~src2
652 * This is probably not general enough to be placed in BitVector.[ch].
653 */
buzbee52a77fc2012-11-20 19:50:46 -0800654static void ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1,
655 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700656{
buzbeefa57c472012-11-21 12:06:18 -0800657 if (dest->storage_size != src1->storage_size ||
658 dest->storage_size != src2->storage_size ||
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 dest->expandable != src1->expandable ||
660 dest->expandable != src2->expandable) {
661 LOG(FATAL) << "Incompatible set properties";
662 }
buzbee67bf8852011-08-17 17:51:35 -0700663
Bill Buzbeea114add2012-05-03 15:00:40 -0700664 unsigned int idx;
buzbeefa57c472012-11-21 12:06:18 -0800665 for (idx = 0; idx < dest->storage_size; idx++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
667 }
buzbee67bf8852011-08-17 17:51:35 -0700668}
669
670/*
671 * Iterate through all successor blocks and propagate up the live-in sets.
672 * The calculated result is used for phi-node pruning - where we only need to
673 * insert a phi node if the variable is live-in to the block.
674 */
buzbeefa57c472012-11-21 12:06:18 -0800675static bool ComputeBlockLiveIns(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700676{
buzbeefa57c472012-11-21 12:06:18 -0800677 ArenaBitVector* temp_dalvik_register_v = cu->temp_dalvik_register_v;
buzbee67bf8852011-08-17 17:51:35 -0700678
buzbeefa57c472012-11-21 12:06:18 -0800679 if (bb->data_flow_info == NULL) return false;
680 CopyBitVector(temp_dalvik_register_v, bb->data_flow_info->live_in_v);
681 if (bb->taken && bb->taken->data_flow_info)
682 ComputeSuccLineIn(temp_dalvik_register_v, bb->taken->data_flow_info->live_in_v,
683 bb->data_flow_info->def_v);
684 if (bb->fall_through && bb->fall_through->data_flow_info)
685 ComputeSuccLineIn(temp_dalvik_register_v,
686 bb->fall_through->data_flow_info->live_in_v,
687 bb->data_flow_info->def_v);
688 if (bb->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800690 GrowableListIteratorInit(&bb->successor_block_list.blocks,
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 &iterator);
692 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800693 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800694 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800695 if (successor_block_info == NULL) break;
696 BasicBlock* succ_bb = successor_block_info->block;
697 if (succ_bb->data_flow_info) {
698 ComputeSuccLineIn(temp_dalvik_register_v,
699 succ_bb->data_flow_info->live_in_v,
700 bb->data_flow_info->def_v);
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 }
buzbee67bf8852011-08-17 17:51:35 -0700702 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 }
buzbeefa57c472012-11-21 12:06:18 -0800704 if (CompareBitVectors(temp_dalvik_register_v, bb->data_flow_info->live_in_v)) {
705 CopyBitVector(bb->data_flow_info->live_in_v, temp_dalvik_register_v);
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 return true;
707 }
708 return false;
buzbee67bf8852011-08-17 17:51:35 -0700709}
710
711/* Insert phi nodes to for each variable to the dominance frontiers */
buzbeefa57c472012-11-21 12:06:18 -0800712static void InsertPhiNodes(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700713{
buzbeefa57c472012-11-21 12:06:18 -0800714 int dalvik_reg;
715 const GrowableList* block_list = &cu->block_list;
716 ArenaBitVector* phi_blocks =
717 AllocBitVector(cu, cu->num_blocks, false, kBitMapPhi);
718 ArenaBitVector* tmp_blocks =
719 AllocBitVector(cu, cu->num_blocks, false, kBitMapTmpBlocks);
720 ArenaBitVector* input_blocks =
721 AllocBitVector(cu, cu->num_blocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700722
buzbeefa57c472012-11-21 12:06:18 -0800723 cu->temp_dalvik_register_v =
724 AllocBitVector(cu, cu->num_dalvik_registers, false,
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700726
buzbeefa57c472012-11-21 12:06:18 -0800727 DataFlowAnalysisDispatcher(cu, ComputeBlockLiveIns,
728 kPostOrderDFSTraversal, true /* is_iterative */);
buzbee67bf8852011-08-17 17:51:35 -0700729
Bill Buzbeea114add2012-05-03 15:00:40 -0700730 /* Iterate through each Dalvik register */
buzbeefa57c472012-11-21 12:06:18 -0800731 for (dalvik_reg = cu->num_dalvik_registers - 1; dalvik_reg >= 0; dalvik_reg--) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700732 bool change;
733 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700734
buzbeefa57c472012-11-21 12:06:18 -0800735 CopyBitVector(input_blocks, cu->def_block_matrix[dalvik_reg]);
736 ClearAllBits(phi_blocks);
buzbee67bf8852011-08-17 17:51:35 -0700737
Bill Buzbeea114add2012-05-03 15:00:40 -0700738 /* Calculate the phi blocks for each Dalvik register */
739 do {
740 change = false;
buzbeefa57c472012-11-21 12:06:18 -0800741 ClearAllBits(tmp_blocks);
742 BitVectorIteratorInit(input_blocks, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700743
Bill Buzbeea114add2012-05-03 15:00:40 -0700744 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800745 int idx = BitVectorIteratorNext(&iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 if (idx == -1) break;
buzbeefa57c472012-11-21 12:06:18 -0800747 BasicBlock* def_bb =
748 reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, idx));
buzbee67bf8852011-08-17 17:51:35 -0700749
buzbeefa57c472012-11-21 12:06:18 -0800750 /* Merge the dominance frontier to tmp_blocks */
buzbee52a77fc2012-11-20 19:50:46 -0800751 //TUNING: hot call to UnifyBitVetors
buzbeefa57c472012-11-21 12:06:18 -0800752 if (def_bb->dom_frontier != NULL) {
753 UnifyBitVetors(tmp_blocks, tmp_blocks, def_bb->dom_frontier);
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 }
buzbee67bf8852011-08-17 17:51:35 -0700755 }
buzbeefa57c472012-11-21 12:06:18 -0800756 if (CompareBitVectors(phi_blocks, tmp_blocks)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 change = true;
buzbeefa57c472012-11-21 12:06:18 -0800758 CopyBitVector(phi_blocks, tmp_blocks);
Bill Buzbeea114add2012-05-03 15:00:40 -0700759
760 /*
761 * Iterate through the original blocks plus the new ones in
762 * the dominance frontier.
763 */
buzbeefa57c472012-11-21 12:06:18 -0800764 CopyBitVector(input_blocks, phi_blocks);
765 UnifyBitVetors(input_blocks, input_blocks,
766 cu->def_block_matrix[dalvik_reg]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700767 }
768 } while (change);
769
770 /*
buzbeefa57c472012-11-21 12:06:18 -0800771 * Insert a phi node for dalvik_reg in the phi_blocks if the Dalvik
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 * register is in the live-in set.
773 */
buzbeefa57c472012-11-21 12:06:18 -0800774 BitVectorIteratorInit(phi_blocks, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 while (true) {
buzbee52a77fc2012-11-20 19:50:46 -0800776 int idx = BitVectorIteratorNext(&iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700777 if (idx == -1) break;
buzbeefa57c472012-11-21 12:06:18 -0800778 BasicBlock* phi_bb =
779 reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, idx));
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 /* Variable will be clobbered before being used - no need for phi */
buzbeefa57c472012-11-21 12:06:18 -0800781 if (!IsBitSet(phi_bb->data_flow_info->live_in_v, dalvik_reg)) continue;
782 MIR *phi = static_cast<MIR*>(NewMem(cu, sizeof(MIR), true, kAllocDFInfo));
buzbeecbd6d442012-11-17 14:11:25 -0800783 phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi);
buzbeefa57c472012-11-21 12:06:18 -0800784 phi->dalvikInsn.vA = dalvik_reg;
785 phi->offset = phi_bb->start_offset;
buzbeefa57c472012-11-21 12:06:18 -0800786 PrependMIR(phi_bb, phi);
buzbee67bf8852011-08-17 17:51:35 -0700787 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700788 }
buzbee67bf8852011-08-17 17:51:35 -0700789}
790
791/*
792 * Worker function to insert phi-operands with latest SSA names from
793 * predecessor blocks
794 */
buzbeefa57c472012-11-21 12:06:18 -0800795static bool InsertPhiNodeOperands(CompilationUnit* cu, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700796{
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 GrowableListIterator iter;
798 MIR *mir;
buzbee6969d502012-06-15 16:40:31 -0700799 std::vector<int> uses;
buzbeefa57c472012-11-21 12:06:18 -0800800 std::vector<int> incoming_arc;
buzbee67bf8852011-08-17 17:51:35 -0700801
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 /* Phi nodes are at the beginning of each block */
buzbee28c9a832012-11-21 15:39:13 -0800803 for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
buzbeecbd6d442012-11-17 14:11:25 -0800804 if (mir->dalvikInsn.opcode != static_cast<Instruction::Code>(kMirOpPhi))
Bill Buzbeea114add2012-05-03 15:00:40 -0700805 return true;
buzbeefa57c472012-11-21 12:06:18 -0800806 int ssa_reg = mir->ssa_rep->defs[0];
807 DCHECK_GE(ssa_reg, 0); // Shouldn't see compiler temps here
808 int v_reg = SRegToVReg(cu, ssa_reg);
buzbee67bf8852011-08-17 17:51:35 -0700809
buzbee6969d502012-06-15 16:40:31 -0700810 uses.clear();
buzbeefa57c472012-11-21 12:06:18 -0800811 incoming_arc.clear();
buzbee67bf8852011-08-17 17:51:35 -0700812
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 /* Iterate through the predecessors */
buzbee52a77fc2012-11-20 19:50:46 -0800814 GrowableListIteratorInit(bb->predecessors, &iter);
Bill Buzbeea114add2012-05-03 15:00:40 -0700815 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800816 BasicBlock* pred_bb =
buzbee52a77fc2012-11-20 19:50:46 -0800817 reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iter));
buzbeefa57c472012-11-21 12:06:18 -0800818 if (!pred_bb) break;
819 int ssa_reg = pred_bb->data_flow_info->vreg_to_ssa_map[v_reg];
820 uses.push_back(ssa_reg);
821 incoming_arc.push_back(pred_bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700822 }
823
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 /* Count the number of SSA registers for a Dalvik register */
buzbeefa57c472012-11-21 12:06:18 -0800825 int num_uses = uses.size();
826 mir->ssa_rep->num_uses = num_uses;
827 mir->ssa_rep->uses =
828 static_cast<int*>(NewMem(cu, sizeof(int) * num_uses, false, kAllocDFInfo));
829 mir->ssa_rep->fp_use =
830 static_cast<bool*>(NewMem(cu, sizeof(bool) * num_uses, true, kAllocDFInfo));
buzbee2cfc6392012-05-07 14:51:40 -0700831 int* incoming =
buzbeefa57c472012-11-21 12:06:18 -0800832 static_cast<int*>(NewMem(cu, sizeof(int) * num_uses, false, kAllocDFInfo));
buzbee2cfc6392012-05-07 14:51:40 -0700833 // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
buzbeecbd6d442012-11-17 14:11:25 -0800834 mir->dalvikInsn.vB = reinterpret_cast<uintptr_t>(incoming);
Bill Buzbeea114add2012-05-03 15:00:40 -0700835
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 /* Set the uses array for the phi node */
buzbeefa57c472012-11-21 12:06:18 -0800837 int *use_ptr = mir->ssa_rep->uses;
838 for (int i = 0; i < num_uses; i++) {
839 *use_ptr++ = uses[i];
840 *incoming++ = incoming_arc[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700841 }
842 }
843
844 return true;
buzbee67bf8852011-08-17 17:51:35 -0700845}
846
buzbeefa57c472012-11-21 12:06:18 -0800847static void DoDFSPreOrderSSARename(CompilationUnit* cu, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700848{
849
Bill Buzbeea114add2012-05-03 15:00:40 -0700850 if (block->visited || block->hidden) return;
851 block->visited = true;
buzbeef0cde542011-09-13 14:55:02 -0700852
Bill Buzbeea114add2012-05-03 15:00:40 -0700853 /* Process this block */
buzbeefa57c472012-11-21 12:06:18 -0800854 DoSSAConversion(cu, block);
855 int map_size = sizeof(int) * cu->num_dalvik_registers;
buzbeef0cde542011-09-13 14:55:02 -0700856
Bill Buzbeea114add2012-05-03 15:00:40 -0700857 /* Save SSA map snapshot */
buzbeefa57c472012-11-21 12:06:18 -0800858 int* saved_ssa_map = static_cast<int*>(NewMem(cu, map_size, false, kAllocDalvikToSSAMap));
859 memcpy(saved_ssa_map, cu->vreg_to_ssa_map, map_size);
buzbeef0cde542011-09-13 14:55:02 -0700860
buzbeefa57c472012-11-21 12:06:18 -0800861 if (block->fall_through) {
862 DoDFSPreOrderSSARename(cu, block->fall_through);
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 /* Restore SSA map snapshot */
buzbeefa57c472012-11-21 12:06:18 -0800864 memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
Bill Buzbeea114add2012-05-03 15:00:40 -0700865 }
866 if (block->taken) {
buzbeefa57c472012-11-21 12:06:18 -0800867 DoDFSPreOrderSSARename(cu, block->taken);
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 /* Restore SSA map snapshot */
buzbeefa57c472012-11-21 12:06:18 -0800869 memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 }
buzbeefa57c472012-11-21 12:06:18 -0800871 if (block->successor_block_list.block_list_type != kNotUsed) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 GrowableListIterator iterator;
buzbeefa57c472012-11-21 12:06:18 -0800873 GrowableListIteratorInit(&block->successor_block_list.blocks, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 while (true) {
buzbeefa57c472012-11-21 12:06:18 -0800875 SuccessorBlockInfo *successor_block_info =
buzbee52a77fc2012-11-20 19:50:46 -0800876 reinterpret_cast<SuccessorBlockInfo*>(GrowableListIteratorNext(&iterator));
buzbeefa57c472012-11-21 12:06:18 -0800877 if (successor_block_info == NULL) break;
878 BasicBlock* succ_bb = successor_block_info->block;
879 DoDFSPreOrderSSARename(cu, succ_bb);
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 /* Restore SSA map snapshot */
buzbeefa57c472012-11-21 12:06:18 -0800881 memcpy(cu->vreg_to_ssa_map, saved_ssa_map, map_size);
buzbeef0cde542011-09-13 14:55:02 -0700882 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 }
buzbeefa57c472012-11-21 12:06:18 -0800884 cu->vreg_to_ssa_map = saved_ssa_map;
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 return;
buzbeef0cde542011-09-13 14:55:02 -0700886}
887
buzbee67bf8852011-08-17 17:51:35 -0700888/* Perform SSA transformation for the whole method */
buzbeefa57c472012-11-21 12:06:18 -0800889void SSATransformation(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700890{
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 /* Compute the DFS order */
buzbeefa57c472012-11-21 12:06:18 -0800892 ComputeDFSOrders(cu);
buzbee67bf8852011-08-17 17:51:35 -0700893
buzbeefa57c472012-11-21 12:06:18 -0800894 if (!cu->disable_dataflow) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700895 /* Compute the dominator info */
buzbeefa57c472012-11-21 12:06:18 -0800896 ComputeDominators(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700897 }
buzbee67bf8852011-08-17 17:51:35 -0700898
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 /* Allocate data structures in preparation for SSA conversion */
buzbeefa57c472012-11-21 12:06:18 -0800900 CompilerInitializeSSAConversion(cu);
buzbee67bf8852011-08-17 17:51:35 -0700901
buzbeefa57c472012-11-21 12:06:18 -0800902 if (!cu->disable_dataflow) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 /* Find out the "Dalvik reg def x block" relation */
buzbeefa57c472012-11-21 12:06:18 -0800904 ComputeDefBlockMatrix(cu);
buzbee67bf8852011-08-17 17:51:35 -0700905
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 /* Insert phi nodes to dominance frontiers for all variables */
buzbeefa57c472012-11-21 12:06:18 -0800907 InsertPhiNodes(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 }
buzbee67bf8852011-08-17 17:51:35 -0700909
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 /* Rename register names by local defs and phi nodes */
buzbeefa57c472012-11-21 12:06:18 -0800911 DataFlowAnalysisDispatcher(cu, ClearVisitedFlag,
912 kAllNodes, false /* is_iterative */);
913 DoDFSPreOrderSSARename(cu, cu->entry_block);
buzbee67bf8852011-08-17 17:51:35 -0700914
buzbeefa57c472012-11-21 12:06:18 -0800915 if (!cu->disable_dataflow) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 /*
917 * Shared temp bit vector used by each block to count the number of defs
918 * from all the predecessor blocks.
919 */
buzbeefa57c472012-11-21 12:06:18 -0800920 cu->temp_ssa_register_v = AllocBitVector(cu, cu->num_ssa_regs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700922
buzbeefa57c472012-11-21 12:06:18 -0800923 cu->temp_ssa_block_id_v =
924 static_cast<int*>(NewMem(cu, sizeof(int) * cu->num_ssa_regs, false, kAllocDFInfo));
buzbee2cfc6392012-05-07 14:51:40 -0700925
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 /* Insert phi-operands with latest SSA names from predecessor blocks */
buzbeefa57c472012-11-21 12:06:18 -0800927 DataFlowAnalysisDispatcher(cu, InsertPhiNodeOperands,
928 kReachableNodes, false /* is_iterative */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 }
buzbee67bf8852011-08-17 17:51:35 -0700930}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800931
932} // namespace art