blob: bd5f83bdb4f3288adebadf9a7fd75cdf1230b76c [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
17#include "Dalvik.h"
18#include "Dataflow.h"
19
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080020namespace art {
21
buzbee67bf8852011-08-17 17:51:35 -070022/* Enter the node to the dfsOrder list then visit its successors */
buzbee31a4a6f2012-02-28 15:36:15 -080023void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
buzbee67bf8852011-08-17 17:51:35 -070024{
25
26 if (block->visited || block->hidden) return;
27 block->visited = true;
28
buzbee5b537102012-01-17 17:33:47 -080029 /* Enqueue the preOrder block id */
buzbeeba938cb2012-02-03 14:47:55 -080030 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070031
buzbeee1965672012-03-11 18:39:19 -070032 if (block->fallThrough) {
buzbee72289e62012-03-14 13:28:50 -070033#if 0
34 // Temporary bug workaround
buzbeee1965672012-03-11 18:39:19 -070035 block->fallThrough->fallThroughTarget = true;
buzbee72289e62012-03-14 13:28:50 -070036#endif
buzbeee1965672012-03-11 18:39:19 -070037 recordDFSOrders(cUnit, block->fallThrough);
38 }
buzbee5b537102012-01-17 17:33:47 -080039 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070040 if (block->successorBlockList.blockListType != kNotUsed) {
41 GrowableListIterator iterator;
42 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
43 &iterator);
44 while (true) {
45 SuccessorBlockInfo *successorBlockInfo =
46 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
47 if (successorBlockInfo == NULL) break;
48 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080049 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070050 }
51 }
buzbee5b537102012-01-17 17:33:47 -080052
53 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
54 block->dfsId = cUnit->dfsPostOrder.numUsed;
buzbeeba938cb2012-02-03 14:47:55 -080055 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070056 return;
57}
58
buzbee5b537102012-01-17 17:33:47 -080059/* Sort the blocks by the Depth-First-Search */
buzbee31a4a6f2012-02-28 15:36:15 -080060void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070061{
buzbee5b537102012-01-17 17:33:47 -080062 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070063 if (cUnit->dfsOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080064 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
65 kListDfsOrder);
buzbee67bf8852011-08-17 17:51:35 -070066 } else {
67 /* Just reset the used length on the counter */
68 cUnit->dfsOrder.numUsed = 0;
69 }
70
buzbee5b537102012-01-17 17:33:47 -080071 /* Initialize or reset the DFS postOrder list */
72 if (cUnit->dfsPostOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080073 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -080074 kListDfsPostOrder);
buzbee5b537102012-01-17 17:33:47 -080075 } else {
76 /* Just reset the used length on the counter */
77 cUnit->dfsPostOrder.numUsed = 0;
78 }
79
buzbee67bf8852011-08-17 17:51:35 -070080 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
81 kAllNodes,
82 false /* isIterative */);
83
buzbee5b537102012-01-17 17:33:47 -080084 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070085 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
86}
87
88/*
89 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
90 * register idx is defined in BasicBlock bb.
91 */
buzbee31a4a6f2012-02-28 15:36:15 -080092bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070093{
94 if (bb->dataFlowInfo == NULL) return false;
95
96 ArenaBitVectorIterator iterator;
97
98 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
99 while (true) {
100 int idx = oatBitVectorIteratorNext(&iterator);
101 if (idx == -1) break;
102 /* Block bb defines register idx */
buzbeeba938cb2012-02-03 14:47:55 -0800103 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700104 }
105 return true;
106}
107
buzbee31a4a6f2012-02-28 15:36:15 -0800108void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700109{
110 int numRegisters = cUnit->numDalvikRegisters;
111 /* Allocate numDalvikRegisters bit vector pointers */
112 cUnit->defBlockMatrix = (ArenaBitVector **)
buzbeeba938cb2012-02-03 14:47:55 -0800113 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
buzbee5abfa3e2012-01-31 17:01:43 -0800114 kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700115 int i;
116
117 /* Initialize numRegister vectors with numBlocks bits each */
118 for (i = 0; i < numRegisters; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800119 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
120 false, kBitMapBMatrix);
buzbee67bf8852011-08-17 17:51:35 -0700121 }
122 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
123 kAllNodes,
124 false /* isIterative */);
125 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
126 kAllNodes,
127 false /* isIterative */);
128
129 /*
130 * Also set the incoming parameters as defs in the entry block.
131 * Only need to handle the parameters for the outer method.
132 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800133 int numRegs = cUnit->numDalvikRegisters;
134 int inReg = numRegs - cUnit->numIns;
135 for (; inReg < numRegs; inReg++) {
buzbeeba938cb2012-02-03 14:47:55 -0800136 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700137 }
138}
139
140/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800141void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700142{
143 ArenaBitVectorIterator bvIterator;
144 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
145 GrowableList* blockList = &cUnit->blockList;
146
147 /* Iterate through the dominated blocks first */
148 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800149 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700150 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
151 if (bbIdx == -1) break;
152 BasicBlock* dominatedBB =
153 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
154 computeDomPostOrderTraversal(cUnit, dominatedBB);
155 }
156
157 /* Enter the current block id */
buzbeeba938cb2012-02-03 14:47:55 -0800158 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700159
160 /* hacky loop detection */
161 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
162 cUnit->hasLoop = true;
163 }
164}
165
buzbee31a4a6f2012-02-28 15:36:15 -0800166void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
167 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700168{
169 /*
170 * TODO - evaluate whether phi will ever need to be inserted into exit
171 * blocks.
172 */
173 if (succBB->iDom != domBB &&
174 succBB->blockType == kDalvikByteCode &&
175 succBB->hidden == false) {
buzbeeba938cb2012-02-03 14:47:55 -0800176 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700177 }
178}
179
180/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800181bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700182{
183 GrowableList* blockList = &cUnit->blockList;
184
185 /* Calculate DF_local */
186 if (bb->taken) {
buzbeeba938cb2012-02-03 14:47:55 -0800187 checkForDominanceFrontier(cUnit, bb, bb->taken);
buzbee67bf8852011-08-17 17:51:35 -0700188 }
189 if (bb->fallThrough) {
buzbeeba938cb2012-02-03 14:47:55 -0800190 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
buzbee67bf8852011-08-17 17:51:35 -0700191 }
192 if (bb->successorBlockList.blockListType != kNotUsed) {
193 GrowableListIterator iterator;
194 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
195 &iterator);
196 while (true) {
197 SuccessorBlockInfo *successorBlockInfo =
198 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
199 if (successorBlockInfo == NULL) break;
200 BasicBlock* succBB = successorBlockInfo->block;
buzbeeba938cb2012-02-03 14:47:55 -0800201 checkForDominanceFrontier(cUnit, bb, succBB);
buzbee67bf8852011-08-17 17:51:35 -0700202 }
203 }
204
205 /* Calculate DF_up */
206 ArenaBitVectorIterator bvIterator;
207 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
208 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800209 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700210 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
211 if (dominatedIdx == -1) break;
212 BasicBlock* dominatedBB = (BasicBlock* )
213 oatGrowableListGetElement(blockList, dominatedIdx);
214 ArenaBitVectorIterator dfIterator;
215 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
216 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800217 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700218 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
219 if (dfUpIdx == -1) break;
220 BasicBlock* dfUpBlock = (BasicBlock* )
221 oatGrowableListGetElement(blockList, dfUpIdx);
buzbeeba938cb2012-02-03 14:47:55 -0800222 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700223 }
224 }
225
226 return true;
227}
228
229/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800230bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700231{
232 int numTotalBlocks = cUnit->blockList.numUsed;
233
234 if (bb->dominators == NULL ) {
buzbeeba938cb2012-02-03 14:47:55 -0800235 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800236 false /* expandable */,
237 kBitMapDominators);
buzbeeba938cb2012-02-03 14:47:55 -0800238 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800239 false /* expandable */,
240 kBitMapIDominated);
buzbeeba938cb2012-02-03 14:47:55 -0800241 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800242 false /* expandable */,
243 kBitMapDomFrontier);
buzbee67bf8852011-08-17 17:51:35 -0700244 } else {
245 oatClearAllBits(bb->dominators);
246 oatClearAllBits(bb->iDominated);
247 oatClearAllBits(bb->domFrontier);
248 }
249 /* Set all bits in the dominator vector */
250 oatSetInitialBits(bb->dominators, numTotalBlocks);
251
252 return true;
253}
254
buzbee5b537102012-01-17 17:33:47 -0800255/*
256 * Worker function to compute each block's dominators. This implementation
257 * is only used when kDebugVerifyDataflow is active and should compute
258 * the same dominator sets as computeBlockDominators.
259 */
buzbee31a4a6f2012-02-28 15:36:15 -0800260bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700261{
262 GrowableList* blockList = &cUnit->blockList;
263 int numTotalBlocks = blockList->numUsed;
264 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
buzbee5abfa3e2012-01-31 17:01:43 -0800265 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700266
267 /*
268 * The dominator of the entry block has been preset to itself and we need
269 * to skip the calculation here.
270 */
271 if (bb == cUnit->entryBlock) return false;
272
273 oatSetInitialBits(tempBlockV, numTotalBlocks);
274
275 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800276 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700277 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800278 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
279 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700280 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700281 if (predBB->dominators != NULL) {
282 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
283 }
buzbee67bf8852011-08-17 17:51:35 -0700284 }
buzbeeba938cb2012-02-03 14:47:55 -0800285 oatSetBit(cUnit, tempBlockV, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700286 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
287 oatCopyBitVector(bb->dominators, tempBlockV);
288 return true;
289 }
290 return false;
291}
292
buzbee5b537102012-01-17 17:33:47 -0800293/*
294 * Worker function to compute the idom. This implementation is only
295 * used when kDebugVerifyDataflow is active and should compute the
296 * same iDom as computeBlockIDom.
297 */
buzbee31a4a6f2012-02-28 15:36:15 -0800298bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700299{
300 GrowableList* blockList = &cUnit->blockList;
301 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
302 ArenaBitVectorIterator bvIterator;
303 BasicBlock* iDom;
304
305 if (bb == cUnit->entryBlock) return false;
306
307 oatCopyBitVector(tempBlockV, bb->dominators);
308 oatClearBit(tempBlockV, bb->id);
309 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
310
311 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700312 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700313 if (oatCountSetBits(tempBlockV) == 1) {
314 iDom = (BasicBlock* ) oatGrowableListGetElement(
315 blockList, oatBitVectorIteratorNext(&bvIterator));
316 bb->iDom = iDom;
317 } else {
318 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700319 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700320 while (true) {
321 int nextDom = oatBitVectorIteratorNext(&bvIterator);
322 if (nextDom == -1) break;
323 BasicBlock* nextDomBB = (BasicBlock* )
324 oatGrowableListGetElement(blockList, nextDom);
325 /* iDom dominates nextDom - set new iDom */
326 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
327 iDomIdx = nextDom;
328 }
329
330 }
331 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
332 /* Set the immediate dominator block for bb */
333 bb->iDom = iDom;
334 }
335 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800336 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700337 return true;
338}
339
buzbee5b537102012-01-17 17:33:47 -0800340/*
341 * Walk through the ordered iDom list until we reach common parent.
342 * Given the ordering of iDomList, this common parent represents the
343 * last element of the intersection of block1 and block2 dominators.
344 */
345int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
346{
347 while (block1 != block2) {
348 while (block1 < block2) {
349 block1 = cUnit->iDomList[block1];
350 DCHECK_NE(block1, NOTVISITED);
351 }
352 while (block2 < block1) {
353 block2 = cUnit->iDomList[block2];
354 DCHECK_NE(block2, NOTVISITED);
355 }
356 }
357 return block1;
358}
359
360/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800361bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800362{
buzbee5abfa3e2012-01-31 17:01:43 -0800363 GrowableListIterator iter;
buzbee5b537102012-01-17 17:33:47 -0800364 int idom = -1;
365
366 /* Special-case entry block */
367 if (bb == cUnit->entryBlock) {
368 return false;
369 }
370
371 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800372 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee5b537102012-01-17 17:33:47 -0800373
374 /* Find the first processed predecessor */
375 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800376 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
377 CHECK(predBB != NULL);
buzbee5b537102012-01-17 17:33:47 -0800378 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
379 idom = predBB->dfsId;
380 break;
381 }
382 }
383
384 /* Scan the rest of the predecessors */
385 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800386 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
387 if (!predBB) break;
buzbee5b537102012-01-17 17:33:47 -0800388 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
389 continue;
390 } else {
391 idom = findCommonParent(cUnit, predBB->dfsId, idom);
392 }
393 }
394
395 DCHECK_NE(idom, NOTVISITED);
396
397 /* Did something change? */
398 if (cUnit->iDomList[bb->dfsId] != idom) {
399 cUnit->iDomList[bb->dfsId] = idom;
400 return true;
401 }
402 return false;
403}
404
405/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800406bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800407{
408 if (bb == cUnit->entryBlock) {
409 oatClearAllBits(bb->dominators);
410 } else {
411 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
412 }
buzbeeba938cb2012-02-03 14:47:55 -0800413 oatSetBit(cUnit, bb->dominators, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800414 return false;
415}
416
buzbee31a4a6f2012-02-28 15:36:15 -0800417bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800418{
419 if (bb != cUnit->entryBlock) {
420 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
421 DCHECK_NE(iDomDFSIdx, NOTVISITED);
422 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
423 BasicBlock* iDom = (BasicBlock*)
424 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
425 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
426 DCHECK_EQ(bb->iDom->id, iDom->id);
427 }
428 bb->iDom = iDom;
429 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800430 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800431 }
432 return false;
433}
434
buzbee67bf8852011-08-17 17:51:35 -0700435/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800436void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700437{
438 int numReachableBlocks = cUnit->numReachableBlocks;
439 int numTotalBlocks = cUnit->blockList.numUsed;
440
441 /* Initialize domination-related data structures */
442 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
443 kReachableNodes,
444 false /* isIterative */);
445
buzbee5b537102012-01-17 17:33:47 -0800446 /* Initalize & Clear iDomList */
447 if (cUnit->iDomList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800448 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
449 false, kAllocDFInfo);
buzbee5b537102012-01-17 17:33:47 -0800450 }
451 for (int i = 0; i < numReachableBlocks; i++) {
452 cUnit->iDomList[i] = NOTVISITED;
453 }
454
455 /* For post-order, last block is entry block. Set its iDom to istelf */
456 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
457 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
458
459 /* Compute the immediate dominators */
460 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
461 kReversePostOrderTraversal,
462 true /* isIterative */);
463
buzbee67bf8852011-08-17 17:51:35 -0700464 /* Set the dominator for the root node */
465 oatClearAllBits(cUnit->entryBlock->dominators);
buzbeeba938cb2012-02-03 14:47:55 -0800466 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700467
468 if (cUnit->tempBlockV == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800469 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800470 false /* expandable */,
471 kBitMapTmpBlockV);
buzbee67bf8852011-08-17 17:51:35 -0700472 } else {
473 oatClearAllBits(cUnit->tempBlockV);
474 }
buzbee67bf8852011-08-17 17:51:35 -0700475 cUnit->entryBlock->iDom = NULL;
buzbee5b537102012-01-17 17:33:47 -0800476
477 /* For testing, compute sets using alternate mechanism */
478 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
479 // Use alternate mechanism to compute dominators for comparison
480 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
481 kPreOrderDFSTraversal,
482 true /* isIterative */);
483
484 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
485 kReachableNodes,
486 false /* isIterative */);
487 }
488
489 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
490 kReachableNodes,
491 false /* isIterative */);
492
493 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
494 kReversePostOrderTraversal,
495 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700496
497 /*
498 * Now go ahead and compute the post order traversal based on the
499 * iDominated sets.
500 */
501 if (cUnit->domPostOrderTraversal.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800502 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
503 numReachableBlocks, kListDomPostOrderTraversal);
buzbee67bf8852011-08-17 17:51:35 -0700504 } else {
505 cUnit->domPostOrderTraversal.numUsed = 0;
506 }
507
508 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700509 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700510 (unsigned) cUnit->numReachableBlocks);
511
512 /* Now compute the dominance frontier for each block */
513 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
514 kPostOrderDOMTraversal,
515 false /* isIterative */);
516}
517
518/*
519 * Perform dest U= src1 ^ ~src2
520 * This is probably not general enough to be placed in BitVector.[ch].
521 */
buzbee31a4a6f2012-02-28 15:36:15 -0800522void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700523 const ArenaBitVector* src1,
524 const ArenaBitVector* src2)
525{
526 if (dest->storageSize != src1->storageSize ||
527 dest->storageSize != src2->storageSize ||
528 dest->expandable != src1->expandable ||
529 dest->expandable != src2->expandable) {
530 LOG(FATAL) << "Incompatible set properties";
531 }
532
533 unsigned int idx;
534 for (idx = 0; idx < dest->storageSize; idx++) {
535 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
536 }
537}
538
539/*
540 * Iterate through all successor blocks and propagate up the live-in sets.
541 * The calculated result is used for phi-node pruning - where we only need to
542 * insert a phi node if the variable is live-in to the block.
543 */
buzbee31a4a6f2012-02-28 15:36:15 -0800544bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700545{
546 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
547
548 if (bb->dataFlowInfo == NULL) return false;
549 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
550 if (bb->taken && bb->taken->dataFlowInfo)
551 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
552 bb->dataFlowInfo->defV);
553 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
554 computeSuccLiveIn(tempDalvikRegisterV,
555 bb->fallThrough->dataFlowInfo->liveInV,
556 bb->dataFlowInfo->defV);
557 if (bb->successorBlockList.blockListType != kNotUsed) {
558 GrowableListIterator iterator;
559 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
560 &iterator);
561 while (true) {
562 SuccessorBlockInfo *successorBlockInfo =
563 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
564 if (successorBlockInfo == NULL) break;
565 BasicBlock* succBB = successorBlockInfo->block;
566 if (succBB->dataFlowInfo) {
567 computeSuccLiveIn(tempDalvikRegisterV,
568 succBB->dataFlowInfo->liveInV,
569 bb->dataFlowInfo->defV);
570 }
571 }
572 }
573 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
574 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
575 return true;
576 }
577 return false;
578}
579
580/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800581void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700582{
583 int dalvikReg;
584 const GrowableList* blockList = &cUnit->blockList;
585 ArenaBitVector* phiBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800586 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
buzbee67bf8852011-08-17 17:51:35 -0700587 ArenaBitVector* tmpBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800588 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700589 ArenaBitVector* inputBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800590 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700591
592 cUnit->tempDalvikRegisterV =
buzbeeba938cb2012-02-03 14:47:55 -0800593 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
buzbee5abfa3e2012-01-31 17:01:43 -0800594 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700595
596 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
597 kPostOrderDFSTraversal,
598 true /* isIterative */);
599
600 /* Iterate through each Dalvik register */
601 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
602 bool change;
603 ArenaBitVectorIterator iterator;
604
605 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
606 oatClearAllBits(phiBlocks);
607
608 /* Calculate the phi blocks for each Dalvik register */
609 do {
610 change = false;
611 oatClearAllBits(tmpBlocks);
612 oatBitVectorIteratorInit(inputBlocks, &iterator);
613
614 while (true) {
615 int idx = oatBitVectorIteratorNext(&iterator);
616 if (idx == -1) break;
617 BasicBlock* defBB =
618 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
619
620 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800621 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700622 if (defBB->domFrontier != NULL) {
623 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
624 }
buzbee67bf8852011-08-17 17:51:35 -0700625 }
626 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
627 change = true;
628 oatCopyBitVector(phiBlocks, tmpBlocks);
629
630 /*
631 * Iterate through the original blocks plus the new ones in
632 * the dominance frontier.
633 */
634 oatCopyBitVector(inputBlocks, phiBlocks);
635 oatUnifyBitVectors(inputBlocks, inputBlocks,
636 cUnit->defBlockMatrix[dalvikReg]);
637 }
638 } while (change);
639
640 /*
641 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
642 * register is in the live-in set.
643 */
644 oatBitVectorIteratorInit(phiBlocks, &iterator);
645 while (true) {
646 int idx = oatBitVectorIteratorNext(&iterator);
647 if (idx == -1) break;
648 BasicBlock* phiBB =
649 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
650 /* Variable will be clobbered before being used - no need for phi */
651 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
buzbeeba938cb2012-02-03 14:47:55 -0800652 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800653 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
buzbee67bf8852011-08-17 17:51:35 -0700654 phi->dalvikInsn.vA = dalvikReg;
655 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700656 phi->meta.phiNext = cUnit->phiList;
657 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700658 oatPrependMIR(phiBB, phi);
659 }
660 }
661}
662
663/*
664 * Worker function to insert phi-operands with latest SSA names from
665 * predecessor blocks
666 */
buzbee31a4a6f2012-02-28 15:36:15 -0800667bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700668{
669 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
buzbee5abfa3e2012-01-31 17:01:43 -0800670 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700671 MIR *mir;
672
673 /* Phi nodes are at the beginning of each block */
674 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800675 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
buzbee67bf8852011-08-17 17:51:35 -0700676 return true;
677 int ssaReg = mir->ssaRep->defs[0];
buzbeee1965672012-03-11 18:39:19 -0700678 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
679 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700680
681 oatClearAllBits(ssaRegV);
682
683 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800684 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700685 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800686 BasicBlock* predBB =
687 (BasicBlock*)oatGrowableListIteratorNext(&iter);
688 if (!predBB) break;
buzbeee1965672012-03-11 18:39:19 -0700689 int ssaReg =
690 predBB->dataFlowInfo->vRegToSSAMap[vReg];
buzbeeba938cb2012-02-03 14:47:55 -0800691 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700692 }
693
694 /* Count the number of SSA registers for a Dalvik register */
695 int numUses = oatCountSetBits(ssaRegV);
696 mir->ssaRep->numUses = numUses;
697 mir->ssaRep->uses =
buzbeeba938cb2012-02-03 14:47:55 -0800698 (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700699 mir->ssaRep->fpUse =
buzbeeba938cb2012-02-03 14:47:55 -0800700 (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700701
702 ArenaBitVectorIterator phiIterator;
703
704 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
705 int *usePtr = mir->ssaRep->uses;
706
707 /* Set the uses array for the phi node */
708 while (true) {
709 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
710 if (ssaRegIdx == -1) break;
711 *usePtr++ = ssaRegIdx;
712 }
713 }
714
715 return true;
716}
717
buzbee31a4a6f2012-02-28 15:36:15 -0800718void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700719{
720
721 if (block->visited || block->hidden) return;
722 block->visited = true;
723
724 /* Process this block */
725 oatDoSSAConversion(cUnit, block);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800726 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700727
728 /* Save SSA map snapshot */
buzbeeba938cb2012-02-03 14:47:55 -0800729 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
730 kAllocDalvikToSSAMap);
buzbeee1965672012-03-11 18:39:19 -0700731 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700732
733 if (block->fallThrough) {
734 doDFSPreOrderSSARename(cUnit, block->fallThrough);
735 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700736 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700737 }
738 if (block->taken) {
739 doDFSPreOrderSSARename(cUnit, block->taken);
740 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700741 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700742 }
743 if (block->successorBlockList.blockListType != kNotUsed) {
744 GrowableListIterator iterator;
745 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
746 &iterator);
747 while (true) {
748 SuccessorBlockInfo *successorBlockInfo =
749 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
750 if (successorBlockInfo == NULL) break;
751 BasicBlock* succBB = successorBlockInfo->block;
752 doDFSPreOrderSSARename(cUnit, succBB);
753 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700754 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700755 }
756 }
buzbeee1965672012-03-11 18:39:19 -0700757 cUnit->vRegToSSAMap = savedSSAMap;
buzbeef0cde542011-09-13 14:55:02 -0700758 return;
759}
760
buzbee67bf8852011-08-17 17:51:35 -0700761/* Perform SSA transformation for the whole method */
762void oatMethodSSATransformation(CompilationUnit* cUnit)
763{
764 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800765 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700766
buzbee99ba9642012-01-25 14:23:14 -0800767 if (!cUnit->disableDataflow) {
768 /* Compute the dominator info */
769 computeDominators(cUnit);
770 }
buzbee67bf8852011-08-17 17:51:35 -0700771
772 /* Allocate data structures in preparation for SSA conversion */
773 oatInitializeSSAConversion(cUnit);
774
buzbee99ba9642012-01-25 14:23:14 -0800775 if (!cUnit->disableDataflow) {
776 /* Find out the "Dalvik reg def x block" relation */
777 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700778
buzbee99ba9642012-01-25 14:23:14 -0800779 /* Insert phi nodes to dominance frontiers for all variables */
780 insertPhiNodes(cUnit);
781 }
buzbee67bf8852011-08-17 17:51:35 -0700782
783 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700784 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
785 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700786 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700787 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700788
buzbee99ba9642012-01-25 14:23:14 -0800789 if (!cUnit->disableDataflow) {
790 /*
791 * Shared temp bit vector used by each block to count the number of defs
792 * from all the predecessor blocks.
793 */
buzbeeba938cb2012-02-03 14:47:55 -0800794 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
795 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700796
buzbee99ba9642012-01-25 14:23:14 -0800797 /* Insert phi-operands with latest SSA names from predecessor blocks */
798 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
799 kReachableNodes,
800 false /* isIterative */);
801 }
buzbee67bf8852011-08-17 17:51:35 -0700802}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800803
804} // namespace art