blob: e689f6a2478f8a8ccfed6666696c1bc963aeb250 [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
25inline BasicBlock* needsVisit(BasicBlock* bb) {
26 if (bb != NULL) {
27 if (bb->visited || bb->hidden) {
28 bb = NULL;
29 }
30 }
31 return bb;
32}
33
34BasicBlock* nextUnvisitedSuccessor(BasicBlock* bb)
35{
36 BasicBlock* res = needsVisit(bb->fallThrough);
37 if (res == NULL) {
38 res = needsVisit(bb->taken);
39 if (res == NULL) {
40 if (bb->successorBlockList.blockListType != kNotUsed) {
41 GrowableListIterator iterator;
42 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
43 &iterator);
44 while (true) {
45 SuccessorBlockInfo *sbi = (SuccessorBlockInfo*)
46 oatGrowableListIteratorNext(&iterator);
47 if (sbi == NULL) break;
48 res = needsVisit(sbi->block);
49 if (res != NULL) break;
50 }
51 }
52 }
53 }
54 return res;
55}
56
57void markPreOrder(CompilationUnit* cUnit, BasicBlock* block)
58{
59 block->visited = true;
buzbeee5f01222012-06-14 15:19:35 -070060 /* Enqueue the preOrder block id */
61 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
62}
63
buzbee31a4a6f2012-02-28 15:36:15 -080064void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
buzbee67bf8852011-08-17 17:51:35 -070065{
buzbeee5f01222012-06-14 15:19:35 -070066 std::vector<BasicBlock*> succ;
67 markPreOrder(cUnit, block);
68 succ.push_back(block);
69 while (!succ.empty()) {
70 BasicBlock* curr = succ.back();
71 BasicBlock* nextSuccessor = nextUnvisitedSuccessor(curr);
72 if (nextSuccessor != NULL) {
73 markPreOrder(cUnit, nextSuccessor);
74 succ.push_back(nextSuccessor);
75 continue;
76 }
77 curr->dfsId = cUnit->dfsPostOrder.numUsed;
78 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, curr->id);
79 succ.pop_back();
80 }
81}
82
83#if defined(TEST_DFS)
84/* Enter the node to the dfsOrder list then visit its successors */
85void recursiveRecordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
86{
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?
92 if ((block->blockType == kDalvikByteCode) &&
93 (block->predecessors->numUsed == 1)) {
94 DCHECK_GE(cUnit->dfsOrder.numUsed, 1U);
95 int prevIdx = cUnit->dfsOrder.numUsed - 1;
96 int prevId = cUnit->dfsOrder.elemList[prevIdx];
97 BasicBlock* predBB = (BasicBlock*)block->predecessors->elemList[0];
Bill Buzbeea114add2012-05-03 15:00:40 -070098 }
buzbee3d661942012-03-14 17:37:27 -070099
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 /* Enqueue the preOrder block id */
101 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -0700102
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 if (block->fallThrough) {
buzbeee5f01222012-06-14 15:19:35 -0700104 recursiveRecordDFSOrders(cUnit, block->fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 }
buzbeee5f01222012-06-14 15:19:35 -0700106 if (block->taken) recursiveRecordDFSOrders(cUnit, block->taken);
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 if (block->successorBlockList.blockListType != kNotUsed) {
108 GrowableListIterator iterator;
109 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
110 &iterator);
111 while (true) {
112 SuccessorBlockInfo *successorBlockInfo =
113 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
114 if (successorBlockInfo == NULL) break;
115 BasicBlock* succBB = successorBlockInfo->block;
buzbeee5f01222012-06-14 15:19:35 -0700116 recursiveRecordDFSOrders(cUnit, succBB);
buzbeee1965672012-03-11 18:39:19 -0700117 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 }
buzbee5b537102012-01-17 17:33:47 -0800119
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
121 block->dfsId = cUnit->dfsPostOrder.numUsed;
122 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
123 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 */
buzbee31a4a6f2012-02-28 15:36:15 -0800128void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700129{
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 /* Initialize or reset the DFS preOrder list */
131 if (cUnit->dfsOrder.elemList == NULL) {
132 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
133 kListDfsOrder);
134 } else {
135 /* Just reset the used length on the counter */
136 cUnit->dfsOrder.numUsed = 0;
137 }
buzbee67bf8852011-08-17 17:51:35 -0700138
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 /* Initialize or reset the DFS postOrder list */
140 if (cUnit->dfsPostOrder.elemList == NULL) {
141 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
142 kListDfsPostOrder);
143 } else {
144 /* Just reset the used length on the counter */
145 cUnit->dfsPostOrder.numUsed = 0;
146 }
buzbee5b537102012-01-17 17:33:47 -0800147
buzbeee5f01222012-06-14 15:19:35 -0700148#if defined(TEST_DFS)
149 // Reset visited flags
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
151 kAllNodes, false /* isIterative */);
buzbeee5f01222012-06-14 15:19:35 -0700152 // Record pre and post order dfs
153 recursiveRecordDFSOrders(cUnit, cUnit->entryBlock);
154 // Copy the results for later comparison and reset the lists
155 GrowableList recursiveDfsOrder;
156 GrowableList recursiveDfsPostOrder;
157 oatInitGrowableList(cUnit, &recursiveDfsOrder, cUnit->dfsOrder.numUsed,
158 kListDfsOrder);
159 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
160 oatInsertGrowableList(cUnit, &recursiveDfsOrder,
161 cUnit->dfsOrder.elemList[i]);
162 }
163 cUnit->dfsOrder.numUsed = 0;
164 oatInitGrowableList(cUnit, &recursiveDfsPostOrder,
165 cUnit->dfsPostOrder.numUsed, kListDfsOrder);
166 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
167 oatInsertGrowableList(cUnit, &recursiveDfsPostOrder,
168 cUnit->dfsPostOrder.elemList[i]);
169 }
170 cUnit->dfsPostOrder.numUsed = 0;
171#endif
buzbee67bf8852011-08-17 17:51:35 -0700172
buzbeee5f01222012-06-14 15:19:35 -0700173 // Reset visited flags from all nodes
174 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
175 kAllNodes, false /* isIterative */);
176 // Record dfs orders
Bill Buzbeea114add2012-05-03 15:00:40 -0700177 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbeee5f01222012-06-14 15:19:35 -0700178
179#if defined(TEST_DFS)
180 bool mismatch = false;
181 mismatch |= (cUnit->dfsOrder.numUsed != recursiveDfsOrder.numUsed);
182 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
183 mismatch |= (cUnit->dfsOrder.elemList[i] !=
184 recursiveDfsOrder.elemList[i]);
185 }
186 mismatch |= (cUnit->dfsPostOrder.numUsed != recursiveDfsPostOrder.numUsed);
187 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
188 mismatch |= (cUnit->dfsPostOrder.elemList[i] !=
189 recursiveDfsPostOrder.elemList[i]);
190 }
191 if (mismatch) {
192 LOG(INFO) << "Mismatch for "
193 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
buzbeee5f01222012-06-14 15:19:35 -0700194 LOG(INFO) << "New dfs";
195 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
196 LOG(INFO) << i << " - " << cUnit->dfsOrder.elemList[i];
197 }
198 LOG(INFO) << "Recursive dfs";
199 for (unsigned int i = 0; i < recursiveDfsOrder.numUsed; i++) {
200 LOG(INFO) << i << " - " << recursiveDfsOrder.elemList[i];
201 }
202 LOG(INFO) << "New post dfs";
203 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
204 LOG(INFO) << i << " - " << cUnit->dfsPostOrder.elemList[i];
205 }
206 LOG(INFO) << "Recursive post dfs";
207 for (unsigned int i = 0; i < recursiveDfsPostOrder.numUsed; i++) {
208 LOG(INFO) << i << " - " << recursiveDfsPostOrder.elemList[i];
209 }
210 }
211 CHECK_EQ(cUnit->dfsOrder.numUsed, recursiveDfsOrder.numUsed);
212 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
213 CHECK_EQ(cUnit->dfsOrder.elemList[i], recursiveDfsOrder.elemList[i]);
214 }
215 CHECK_EQ(cUnit->dfsPostOrder.numUsed, recursiveDfsPostOrder.numUsed);
216 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
217 CHECK_EQ(cUnit->dfsPostOrder.elemList[i],
218 recursiveDfsPostOrder.elemList[i]);
219 }
220#endif
221
Bill Buzbeea114add2012-05-03 15:00:40 -0700222 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
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 */
buzbee31a4a6f2012-02-28 15:36:15 -0800229bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700230{
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 if (bb->dataFlowInfo == 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
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
236 while (true) {
237 int idx = oatBitVectorIteratorNext(&iterator);
238 if (idx == -1) break;
239 /* Block bb defines register idx */
240 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
241 }
242 return true;
buzbee67bf8852011-08-17 17:51:35 -0700243}
244
buzbee31a4a6f2012-02-28 15:36:15 -0800245void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700246{
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 int numRegisters = cUnit->numDalvikRegisters;
248 /* Allocate numDalvikRegisters bit vector pointers */
249 cUnit->defBlockMatrix = (ArenaBitVector **)
250 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
251 kAllocDFInfo);
252 int i;
buzbee67bf8852011-08-17 17:51:35 -0700253
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 /* Initialize numRegister vectors with numBlocks bits each */
255 for (i = 0; i < numRegisters; i++) {
256 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
257 false, kBitMapBMatrix);
258 }
259 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
260 kAllNodes, false /* isIterative */);
261 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
262 kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700263
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 /*
265 * Also set the incoming parameters as defs in the entry block.
266 * Only need to handle the parameters for the outer method.
267 */
268 int numRegs = cUnit->numDalvikRegisters;
269 int inReg = numRegs - cUnit->numIns;
270 for (; inReg < numRegs; inReg++) {
271 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
272 }
buzbee67bf8852011-08-17 17:51:35 -0700273}
274
275/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800276void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700277{
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 ArenaBitVectorIterator bvIterator;
279 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
280 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700281
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 /* Iterate through the dominated blocks first */
283 while (true) {
284 //TUNING: hot call to oatBitVectorIteratorNext
285 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
286 if (bbIdx == -1) break;
287 BasicBlock* dominatedBB =
288 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
289 computeDomPostOrderTraversal(cUnit, dominatedBB);
290 }
buzbee67bf8852011-08-17 17:51:35 -0700291
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 /* Enter the current block id */
293 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700294
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 /* hacky loop detection */
296 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
297 cUnit->hasLoop = true;
298 }
buzbee67bf8852011-08-17 17:51:35 -0700299}
300
buzbee31a4a6f2012-02-28 15:36:15 -0800301void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700303{
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 /*
305 * TODO - evaluate whether phi will ever need to be inserted into exit
306 * blocks.
307 */
308 if (succBB->iDom != domBB &&
309 succBB->blockType == kDalvikByteCode &&
310 succBB->hidden == false) {
311 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
312 }
buzbee67bf8852011-08-17 17:51:35 -0700313}
314
315/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800316bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700317{
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700319
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 /* Calculate DF_local */
321 if (bb->taken) {
322 checkForDominanceFrontier(cUnit, bb, bb->taken);
323 }
324 if (bb->fallThrough) {
325 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
326 }
327 if (bb->successorBlockList.blockListType != kNotUsed) {
328 GrowableListIterator iterator;
329 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
330 &iterator);
331 while (true) {
332 SuccessorBlockInfo *successorBlockInfo =
333 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
334 if (successorBlockInfo == NULL) break;
335 BasicBlock* succBB = successorBlockInfo->block;
336 checkForDominanceFrontier(cUnit, bb, succBB);
337 }
338 }
buzbee67bf8852011-08-17 17:51:35 -0700339
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 /* Calculate DF_up */
341 ArenaBitVectorIterator bvIterator;
342 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
343 while (true) {
344 //TUNING: hot call to oatBitVectorIteratorNext
345 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
346 if (dominatedIdx == -1) break;
347 BasicBlock* dominatedBB = (BasicBlock* )
348 oatGrowableListGetElement(blockList, dominatedIdx);
349 ArenaBitVectorIterator dfIterator;
350 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
buzbee67bf8852011-08-17 17:51:35 -0700351 while (true) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 //TUNING: hot call to oatBitVectorIteratorNext
353 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
354 if (dfUpIdx == -1) break;
355 BasicBlock* dfUpBlock = (BasicBlock* )
356 oatGrowableListGetElement(blockList, dfUpIdx);
357 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700358 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700359 }
buzbee67bf8852011-08-17 17:51:35 -0700360
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 return true;
buzbee67bf8852011-08-17 17:51:35 -0700362}
363
364/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800365bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700366{
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700368
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 if (bb->dominators == NULL ) {
370 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
371 false /* expandable */,
372 kBitMapDominators);
373 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
374 false /* expandable */,
375 kBitMapIDominated);
376 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
377 false /* expandable */,
378 kBitMapDomFrontier);
379 } else {
380 oatClearAllBits(bb->dominators);
381 oatClearAllBits(bb->iDominated);
382 oatClearAllBits(bb->domFrontier);
383 }
384 /* Set all bits in the dominator vector */
385 oatSetInitialBits(bb->dominators, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700386
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 return true;
buzbee67bf8852011-08-17 17:51:35 -0700388}
389
buzbee5b537102012-01-17 17:33:47 -0800390/*
391 * Worker function to compute each block's dominators. This implementation
392 * is only used when kDebugVerifyDataflow is active and should compute
393 * the same dominator sets as computeBlockDominators.
394 */
buzbee31a4a6f2012-02-28 15:36:15 -0800395bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700396{
Bill Buzbeea114add2012-05-03 15:00:40 -0700397 GrowableList* blockList = &cUnit->blockList;
398 int numTotalBlocks = blockList->numUsed;
399 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
400 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700401
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 /*
403 * The dominator of the entry block has been preset to itself and we need
404 * to skip the calculation here.
405 */
406 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700407
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 oatSetInitialBits(tempBlockV, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700409
Bill Buzbeea114add2012-05-03 15:00:40 -0700410 /* Iterate through the predecessors */
411 oatGrowableListIteratorInit(bb->predecessors, &iter);
412 while (true) {
413 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
414 if (!predBB) break;
415 /* tempBlockV = tempBlockV ^ dominators */
416 if (predBB->dominators != NULL) {
417 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
buzbee67bf8852011-08-17 17:51:35 -0700418 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 }
420 oatSetBit(cUnit, tempBlockV, bb->id);
421 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
422 oatCopyBitVector(bb->dominators, tempBlockV);
423 return true;
424 }
425 return false;
buzbee67bf8852011-08-17 17:51:35 -0700426}
427
buzbee5b537102012-01-17 17:33:47 -0800428/*
429 * Worker function to compute the idom. This implementation is only
430 * used when kDebugVerifyDataflow is active and should compute the
431 * same iDom as computeBlockIDom.
432 */
buzbee31a4a6f2012-02-28 15:36:15 -0800433bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700434{
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 GrowableList* blockList = &cUnit->blockList;
436 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
437 ArenaBitVectorIterator bvIterator;
438 BasicBlock* iDom;
buzbee67bf8852011-08-17 17:51:35 -0700439
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700441
Bill Buzbeea114add2012-05-03 15:00:40 -0700442 oatCopyBitVector(tempBlockV, bb->dominators);
443 oatClearBit(tempBlockV, bb->id);
444 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
buzbee67bf8852011-08-17 17:51:35 -0700445
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 /* Should not see any dead block */
447 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
448 if (oatCountSetBits(tempBlockV) == 1) {
449 iDom = (BasicBlock* )
450 oatGrowableListGetElement(blockList,
451 oatBitVectorIteratorNext(&bvIterator));
452 bb->iDom = iDom;
453 } else {
454 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
455 DCHECK_NE(iDomIdx, -1);
456 while (true) {
457 int nextDom = oatBitVectorIteratorNext(&bvIterator);
458 if (nextDom == -1) break;
459 BasicBlock* nextDomBB = (BasicBlock* )
460 oatGrowableListGetElement(blockList, nextDom);
461 /* iDom dominates nextDom - set new iDom */
462 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
463 iDomIdx = nextDom;
464 }
buzbee67bf8852011-08-17 17:51:35 -0700465
buzbee67bf8852011-08-17 17:51:35 -0700466 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
468 /* Set the immediate dominator block for bb */
469 bb->iDom = iDom;
470 }
471 /* Add bb to the iDominated set of the immediate dominator block */
472 oatSetBit(cUnit, iDom->iDominated, bb->id);
473 return true;
buzbee67bf8852011-08-17 17:51:35 -0700474}
475
buzbee5b537102012-01-17 17:33:47 -0800476/*
477 * Walk through the ordered iDom list until we reach common parent.
478 * Given the ordering of iDomList, this common parent represents the
479 * last element of the intersection of block1 and block2 dominators.
480 */
481int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
482{
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 while (block1 != block2) {
484 while (block1 < block2) {
485 block1 = cUnit->iDomList[block1];
486 DCHECK_NE(block1, NOTVISITED);
buzbee5b537102012-01-17 17:33:47 -0800487 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 while (block2 < block1) {
489 block2 = cUnit->iDomList[block2];
490 DCHECK_NE(block2, NOTVISITED);
491 }
492 }
493 return block1;
buzbee5b537102012-01-17 17:33:47 -0800494}
495
496/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800497bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800498{
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 GrowableListIterator iter;
500 int idom = -1;
buzbee5b537102012-01-17 17:33:47 -0800501
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 /* Special-case entry block */
503 if (bb == cUnit->entryBlock) {
buzbee5b537102012-01-17 17:33:47 -0800504 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700505 }
506
507 /* Iterate through the predecessors */
508 oatGrowableListIteratorInit(bb->predecessors, &iter);
509
510 /* Find the first processed predecessor */
511 while (true) {
512 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
513 CHECK(predBB != NULL);
514 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
515 idom = predBB->dfsId;
516 break;
517 }
518 }
519
520 /* Scan the rest of the predecessors */
521 while (true) {
522 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
523 if (!predBB) break;
524 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
525 continue;
526 } else {
527 idom = findCommonParent(cUnit, predBB->dfsId, idom);
528 }
529 }
530
531 DCHECK_NE(idom, NOTVISITED);
532
533 /* Did something change? */
534 if (cUnit->iDomList[bb->dfsId] != idom) {
535 cUnit->iDomList[bb->dfsId] = idom;
536 return true;
537 }
538 return false;
buzbee5b537102012-01-17 17:33:47 -0800539}
540
541/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800542bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800543{
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 if (bb == cUnit->entryBlock) {
545 oatClearAllBits(bb->dominators);
546 } else {
547 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
548 }
549 oatSetBit(cUnit, bb->dominators, bb->id);
550 return false;
buzbee5b537102012-01-17 17:33:47 -0800551}
552
buzbee31a4a6f2012-02-28 15:36:15 -0800553bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800554{
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 if (bb != cUnit->entryBlock) {
556 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
557 DCHECK_NE(iDomDFSIdx, NOTVISITED);
558 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
559 BasicBlock* iDom = (BasicBlock*)
560 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
561 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
562 DCHECK_EQ(bb->iDom->id, iDom->id);
buzbee5b537102012-01-17 17:33:47 -0800563 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700564 bb->iDom = iDom;
565 /* Add bb to the iDominated set of the immediate dominator block */
566 oatSetBit(cUnit, iDom->iDominated, bb->id);
567 }
568 return false;
buzbee5b537102012-01-17 17:33:47 -0800569}
570
buzbee67bf8852011-08-17 17:51:35 -0700571/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800572void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700573{
Bill Buzbeea114add2012-05-03 15:00:40 -0700574 int numReachableBlocks = cUnit->numReachableBlocks;
575 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700576
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 /* Initialize domination-related data structures */
578 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
579 kReachableNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700580
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 /* Initalize & Clear iDomList */
582 if (cUnit->iDomList == NULL) {
583 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
584 false, kAllocDFInfo);
585 }
586 for (int i = 0; i < numReachableBlocks; i++) {
587 cUnit->iDomList[i] = NOTVISITED;
588 }
buzbee5b537102012-01-17 17:33:47 -0800589
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 /* For post-order, last block is entry block. Set its iDom to istelf */
591 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
592 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
buzbee5b537102012-01-17 17:33:47 -0800593
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 /* Compute the immediate dominators */
595 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
596 kReversePostOrderTraversal,
597 true /* isIterative */);
598
599 /* Set the dominator for the root node */
600 oatClearAllBits(cUnit->entryBlock->dominators);
601 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
602
603 if (cUnit->tempBlockV == NULL) {
604 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
605 false /* expandable */,
606 kBitMapTmpBlockV);
607 } else {
608 oatClearAllBits(cUnit->tempBlockV);
609 }
610 cUnit->entryBlock->iDom = NULL;
611
612 /* For testing, compute sets using alternate mechanism */
613 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
614 // Use alternate mechanism to compute dominators for comparison
615 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
616 kPreOrderDFSTraversal,
buzbee5b537102012-01-17 17:33:47 -0800617 true /* isIterative */);
618
Bill Buzbeea114add2012-05-03 15:00:40 -0700619 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
620 kReachableNodes,
621 false /* isIterative */);
622 }
buzbee67bf8852011-08-17 17:51:35 -0700623
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
625 kReachableNodes,
626 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800627
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
629 kReversePostOrderTraversal,
630 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800631
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 /*
633 * Now go ahead and compute the post order traversal based on the
634 * iDominated sets.
635 */
636 if (cUnit->domPostOrderTraversal.elemList == NULL) {
637 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
638 numReachableBlocks, kListDomPostOrderTraversal);
639 } else {
640 cUnit->domPostOrderTraversal.numUsed = 0;
641 }
buzbee5b537102012-01-17 17:33:47 -0800642
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
644 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
645 (unsigned) cUnit->numReachableBlocks);
buzbee5b537102012-01-17 17:33:47 -0800646
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 /* Now compute the dominance frontier for each block */
648 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
649 kPostOrderDOMTraversal,
650 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700651}
652
653/*
654 * Perform dest U= src1 ^ ~src2
655 * This is probably not general enough to be placed in BitVector.[ch].
656 */
buzbee31a4a6f2012-02-28 15:36:15 -0800657void computeSuccLiveIn(ArenaBitVector* dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 const ArenaBitVector* src1,
659 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700660{
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 if (dest->storageSize != src1->storageSize ||
662 dest->storageSize != src2->storageSize ||
663 dest->expandable != src1->expandable ||
664 dest->expandable != src2->expandable) {
665 LOG(FATAL) << "Incompatible set properties";
666 }
buzbee67bf8852011-08-17 17:51:35 -0700667
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 unsigned int idx;
669 for (idx = 0; idx < dest->storageSize; idx++) {
670 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
671 }
buzbee67bf8852011-08-17 17:51:35 -0700672}
673
674/*
675 * Iterate through all successor blocks and propagate up the live-in sets.
676 * The calculated result is used for phi-node pruning - where we only need to
677 * insert a phi node if the variable is live-in to the block.
678 */
buzbee31a4a6f2012-02-28 15:36:15 -0800679bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700680{
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
buzbee67bf8852011-08-17 17:51:35 -0700682
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 if (bb->dataFlowInfo == NULL) return false;
684 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
685 if (bb->taken && bb->taken->dataFlowInfo)
686 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
687 bb->dataFlowInfo->defV);
688 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
689 computeSuccLiveIn(tempDalvikRegisterV,
690 bb->fallThrough->dataFlowInfo->liveInV,
691 bb->dataFlowInfo->defV);
692 if (bb->successorBlockList.blockListType != kNotUsed) {
693 GrowableListIterator iterator;
694 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
695 &iterator);
696 while (true) {
697 SuccessorBlockInfo *successorBlockInfo =
698 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
699 if (successorBlockInfo == NULL) break;
700 BasicBlock* succBB = successorBlockInfo->block;
701 if (succBB->dataFlowInfo) {
buzbee67bf8852011-08-17 17:51:35 -0700702 computeSuccLiveIn(tempDalvikRegisterV,
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 succBB->dataFlowInfo->liveInV,
buzbee67bf8852011-08-17 17:51:35 -0700704 bb->dataFlowInfo->defV);
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 }
buzbee67bf8852011-08-17 17:51:35 -0700706 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 }
708 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
709 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
710 return true;
711 }
712 return false;
buzbee67bf8852011-08-17 17:51:35 -0700713}
714
715/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800716void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700717{
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 int dalvikReg;
719 const GrowableList* blockList = &cUnit->blockList;
720 ArenaBitVector* phiBlocks =
721 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
722 ArenaBitVector* tmpBlocks =
723 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
724 ArenaBitVector* inputBlocks =
725 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700726
Bill Buzbeea114add2012-05-03 15:00:40 -0700727 cUnit->tempDalvikRegisterV =
728 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
729 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700730
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
732 kPostOrderDFSTraversal, true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700733
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 /* Iterate through each Dalvik register */
buzbee2a83e8f2012-07-13 16:42:30 -0700735 for (dalvikReg = cUnit->numDalvikRegisters - 1; dalvikReg >= 0; dalvikReg--) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 bool change;
737 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700738
Bill Buzbeea114add2012-05-03 15:00:40 -0700739 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
740 oatClearAllBits(phiBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700741
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 /* Calculate the phi blocks for each Dalvik register */
743 do {
744 change = false;
745 oatClearAllBits(tmpBlocks);
746 oatBitVectorIteratorInit(inputBlocks, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700747
Bill Buzbeea114add2012-05-03 15:00:40 -0700748 while (true) {
749 int idx = oatBitVectorIteratorNext(&iterator);
750 if (idx == -1) break;
751 BasicBlock* defBB =
752 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
buzbee67bf8852011-08-17 17:51:35 -0700753
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 /* Merge the dominance frontier to tmpBlocks */
755 //TUNING: hot call to oatUnifyBitVectors
756 if (defBB->domFrontier != NULL) {
757 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
758 }
buzbee67bf8852011-08-17 17:51:35 -0700759 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700760 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
761 change = true;
762 oatCopyBitVector(phiBlocks, tmpBlocks);
763
764 /*
765 * Iterate through the original blocks plus the new ones in
766 * the dominance frontier.
767 */
768 oatCopyBitVector(inputBlocks, phiBlocks);
769 oatUnifyBitVectors(inputBlocks, inputBlocks,
770 cUnit->defBlockMatrix[dalvikReg]);
771 }
772 } while (change);
773
774 /*
775 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
776 * register is in the live-in set.
777 */
778 oatBitVectorIteratorInit(phiBlocks, &iterator);
779 while (true) {
780 int idx = oatBitVectorIteratorNext(&iterator);
781 if (idx == -1) break;
782 BasicBlock* phiBB =
783 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
784 /* Variable will be clobbered before being used - no need for phi */
785 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
786 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
787 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
788 phi->dalvikInsn.vA = dalvikReg;
789 phi->offset = phiBB->startOffset;
790 phi->meta.phiNext = cUnit->phiList;
791 cUnit->phiList = phi;
792 oatPrependMIR(phiBB, phi);
buzbee67bf8852011-08-17 17:51:35 -0700793 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700794 }
buzbee67bf8852011-08-17 17:51:35 -0700795}
796
797/*
798 * Worker function to insert phi-operands with latest SSA names from
799 * predecessor blocks
800 */
buzbee31a4a6f2012-02-28 15:36:15 -0800801bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700802{
Bill Buzbeea114add2012-05-03 15:00:40 -0700803 GrowableListIterator iter;
804 MIR *mir;
buzbee6969d502012-06-15 16:40:31 -0700805 std::vector<int> uses;
806 std::vector<int> incomingArc;
buzbee67bf8852011-08-17 17:51:35 -0700807
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 /* Phi nodes are at the beginning of each block */
809 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
810 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
811 return true;
812 int ssaReg = mir->ssaRep->defs[0];
813 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
814 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700815
buzbee6969d502012-06-15 16:40:31 -0700816 uses.clear();
817 incomingArc.clear();
buzbee67bf8852011-08-17 17:51:35 -0700818
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 /* Iterate through the predecessors */
820 oatGrowableListIteratorInit(bb->predecessors, &iter);
821 while (true) {
822 BasicBlock* predBB =
823 (BasicBlock*)oatGrowableListIteratorNext(&iter);
824 if (!predBB) break;
825 int ssaReg = predBB->dataFlowInfo->vRegToSSAMap[vReg];
buzbee6969d502012-06-15 16:40:31 -0700826 uses.push_back(ssaReg);
827 incomingArc.push_back(predBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700828 }
829
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 /* Count the number of SSA registers for a Dalvik register */
buzbee6969d502012-06-15 16:40:31 -0700831 int numUses = uses.size();
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 mir->ssaRep->numUses = numUses;
833 mir->ssaRep->uses =
buzbee2cfc6392012-05-07 14:51:40 -0700834 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 mir->ssaRep->fpUse =
buzbee2cfc6392012-05-07 14:51:40 -0700836 (bool*) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
837 int* incoming =
838 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
839 // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
840 mir->dalvikInsn.vB = (intptr_t) incoming;
Bill Buzbeea114add2012-05-03 15:00:40 -0700841
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 /* Set the uses array for the phi node */
buzbee6969d502012-06-15 16:40:31 -0700843 int *usePtr = mir->ssaRep->uses;
844 for (int i = 0; i < numUses; i++) {
845 *usePtr++ = uses[i];
846 *incoming++ = incomingArc[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 }
848 }
849
850 return true;
buzbee67bf8852011-08-17 17:51:35 -0700851}
852
buzbee31a4a6f2012-02-28 15:36:15 -0800853void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700854{
855
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 if (block->visited || block->hidden) return;
857 block->visited = true;
buzbeef0cde542011-09-13 14:55:02 -0700858
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 /* Process this block */
860 oatDoSSAConversion(cUnit, block);
861 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700862
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 /* Save SSA map snapshot */
864 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
865 kAllocDalvikToSSAMap);
866 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700867
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 if (block->fallThrough) {
869 doDFSPreOrderSSARename(cUnit, block->fallThrough);
870 /* Restore SSA map snapshot */
871 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
872 }
873 if (block->taken) {
874 doDFSPreOrderSSARename(cUnit, block->taken);
875 /* Restore SSA map snapshot */
876 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
877 }
878 if (block->successorBlockList.blockListType != kNotUsed) {
879 GrowableListIterator iterator;
880 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
881 &iterator);
882 while (true) {
883 SuccessorBlockInfo *successorBlockInfo =
884 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
885 if (successorBlockInfo == NULL) break;
886 BasicBlock* succBB = successorBlockInfo->block;
887 doDFSPreOrderSSARename(cUnit, succBB);
888 /* Restore SSA map snapshot */
889 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700890 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 }
892 cUnit->vRegToSSAMap = savedSSAMap;
893 return;
buzbeef0cde542011-09-13 14:55:02 -0700894}
895
buzbee67bf8852011-08-17 17:51:35 -0700896/* Perform SSA transformation for the whole method */
897void oatMethodSSATransformation(CompilationUnit* cUnit)
898{
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 /* Compute the DFS order */
900 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700901
Bill Buzbeea114add2012-05-03 15:00:40 -0700902 if (!cUnit->disableDataflow) {
903 /* Compute the dominator info */
904 computeDominators(cUnit);
905 }
buzbee67bf8852011-08-17 17:51:35 -0700906
Bill Buzbeea114add2012-05-03 15:00:40 -0700907 /* Allocate data structures in preparation for SSA conversion */
908 oatInitializeSSAConversion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700909
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 if (!cUnit->disableDataflow) {
911 /* Find out the "Dalvik reg def x block" relation */
912 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700913
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 /* Insert phi nodes to dominance frontiers for all variables */
915 insertPhiNodes(cUnit);
916 }
buzbee67bf8852011-08-17 17:51:35 -0700917
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 /* Rename register names by local defs and phi nodes */
919 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
920 kAllNodes, false /* isIterative */);
921 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700922
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 if (!cUnit->disableDataflow) {
924 /*
925 * Shared temp bit vector used by each block to count the number of defs
926 * from all the predecessor blocks.
927 */
928 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
929 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700930
buzbee2cfc6392012-05-07 14:51:40 -0700931 cUnit->tempSSABlockIdV =
932 (int*)oatNew(cUnit, sizeof(int) * cUnit->numSSARegs, false,
933 kAllocDFInfo);
934
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 /* Insert phi-operands with latest SSA names from predecessor blocks */
936 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
937 kReachableNodes, false /* isIterative */);
938 }
buzbee67bf8852011-08-17 17:51:35 -0700939}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800940
941} // namespace art