blob: 3e1728f755a4e9aa0d25be9544a1878fdc3696d5 [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 */
buzbee5b537102012-01-17 17:33:47 -080023STATIC void 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 */
buzbee67bf8852011-08-17 17:51:35 -070030 oatInsertGrowableList(&cUnit->dfsOrder, block->id);
31
buzbee5b537102012-01-17 17:33:47 -080032 if (block->fallThrough) recordDFSOrders(cUnit, block->fallThrough);
33 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070034 if (block->successorBlockList.blockListType != kNotUsed) {
35 GrowableListIterator iterator;
36 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
37 &iterator);
38 while (true) {
39 SuccessorBlockInfo *successorBlockInfo =
40 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
41 if (successorBlockInfo == NULL) break;
42 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080043 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070044 }
45 }
buzbee5b537102012-01-17 17:33:47 -080046
47 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
48 block->dfsId = cUnit->dfsPostOrder.numUsed;
49 oatInsertGrowableList(&cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070050 return;
51}
52
buzbee5b537102012-01-17 17:33:47 -080053/* Sort the blocks by the Depth-First-Search */
54STATIC void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070055{
buzbee5b537102012-01-17 17:33:47 -080056 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070057 if (cUnit->dfsOrder.elemList == NULL) {
buzbee5abfa3e2012-01-31 17:01:43 -080058 oatInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks, kListDfsOrder);
buzbee67bf8852011-08-17 17:51:35 -070059 } else {
60 /* Just reset the used length on the counter */
61 cUnit->dfsOrder.numUsed = 0;
62 }
63
buzbee5b537102012-01-17 17:33:47 -080064 /* Initialize or reset the DFS postOrder list */
65 if (cUnit->dfsPostOrder.elemList == NULL) {
buzbee5abfa3e2012-01-31 17:01:43 -080066 oatInitGrowableList(&cUnit->dfsPostOrder, cUnit->numBlocks,
67 kListDfsPostOrder);
buzbee5b537102012-01-17 17:33:47 -080068 } else {
69 /* Just reset the used length on the counter */
70 cUnit->dfsPostOrder.numUsed = 0;
71 }
72
buzbee67bf8852011-08-17 17:51:35 -070073 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
74 kAllNodes,
75 false /* isIterative */);
76
buzbee5b537102012-01-17 17:33:47 -080077 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070078 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
79}
80
81/*
82 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
83 * register idx is defined in BasicBlock bb.
84 */
buzbeeed3e9302011-09-23 17:34:19 -070085STATIC bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070086{
87 if (bb->dataFlowInfo == NULL) return false;
88
89 ArenaBitVectorIterator iterator;
90
91 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
92 while (true) {
93 int idx = oatBitVectorIteratorNext(&iterator);
94 if (idx == -1) break;
95 /* Block bb defines register idx */
96 oatSetBit(cUnit->defBlockMatrix[idx], bb->id);
97 }
98 return true;
99}
100
buzbeeed3e9302011-09-23 17:34:19 -0700101STATIC void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700102{
103 int numRegisters = cUnit->numDalvikRegisters;
104 /* Allocate numDalvikRegisters bit vector pointers */
105 cUnit->defBlockMatrix = (ArenaBitVector **)
buzbee5abfa3e2012-01-31 17:01:43 -0800106 oatNew(sizeof(ArenaBitVector *) * numRegisters, true,
107 kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700108 int i;
109
110 /* Initialize numRegister vectors with numBlocks bits each */
111 for (i = 0; i < numRegisters; i++) {
buzbee5abfa3e2012-01-31 17:01:43 -0800112 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit->numBlocks, false,
113 kBitMapBMatrix);
buzbee67bf8852011-08-17 17:51:35 -0700114 }
115 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
116 kAllNodes,
117 false /* isIterative */);
118 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
119 kAllNodes,
120 false /* isIterative */);
121
122 /*
123 * Also set the incoming parameters as defs in the entry block.
124 * Only need to handle the parameters for the outer method.
125 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800126 int numRegs = cUnit->numDalvikRegisters;
127 int inReg = numRegs - cUnit->numIns;
128 for (; inReg < numRegs; inReg++) {
129 oatSetBit(cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700130 }
131}
132
133/* Compute the post-order traversal of the CFG */
buzbeeed3e9302011-09-23 17:34:19 -0700134STATIC void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700135{
136 ArenaBitVectorIterator bvIterator;
137 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
138 GrowableList* blockList = &cUnit->blockList;
139
140 /* Iterate through the dominated blocks first */
141 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800142 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700143 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
144 if (bbIdx == -1) break;
145 BasicBlock* dominatedBB =
146 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
147 computeDomPostOrderTraversal(cUnit, dominatedBB);
148 }
149
150 /* Enter the current block id */
151 oatInsertGrowableList(&cUnit->domPostOrderTraversal, bb->id);
152
153 /* hacky loop detection */
154 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
155 cUnit->hasLoop = true;
156 }
157}
158
buzbeeed3e9302011-09-23 17:34:19 -0700159STATIC void checkForDominanceFrontier(BasicBlock* domBB,
buzbee67bf8852011-08-17 17:51:35 -0700160 const BasicBlock* succBB)
161{
162 /*
163 * TODO - evaluate whether phi will ever need to be inserted into exit
164 * blocks.
165 */
166 if (succBB->iDom != domBB &&
167 succBB->blockType == kDalvikByteCode &&
168 succBB->hidden == false) {
169 oatSetBit(domBB->domFrontier, succBB->id);
170 }
171}
172
173/* Worker function to compute the dominance frontier */
buzbeeed3e9302011-09-23 17:34:19 -0700174STATIC bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700175{
176 GrowableList* blockList = &cUnit->blockList;
177
178 /* Calculate DF_local */
179 if (bb->taken) {
180 checkForDominanceFrontier(bb, bb->taken);
181 }
182 if (bb->fallThrough) {
183 checkForDominanceFrontier(bb, bb->fallThrough);
184 }
185 if (bb->successorBlockList.blockListType != kNotUsed) {
186 GrowableListIterator iterator;
187 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
188 &iterator);
189 while (true) {
190 SuccessorBlockInfo *successorBlockInfo =
191 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
192 if (successorBlockInfo == NULL) break;
193 BasicBlock* succBB = successorBlockInfo->block;
194 checkForDominanceFrontier(bb, succBB);
195 }
196 }
197
198 /* Calculate DF_up */
199 ArenaBitVectorIterator bvIterator;
200 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
201 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800202 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700203 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
204 if (dominatedIdx == -1) break;
205 BasicBlock* dominatedBB = (BasicBlock* )
206 oatGrowableListGetElement(blockList, dominatedIdx);
207 ArenaBitVectorIterator dfIterator;
208 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
209 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800210 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700211 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
212 if (dfUpIdx == -1) break;
213 BasicBlock* dfUpBlock = (BasicBlock* )
214 oatGrowableListGetElement(blockList, dfUpIdx);
215 checkForDominanceFrontier(bb, dfUpBlock);
216 }
217 }
218
219 return true;
220}
221
222/* Worker function for initializing domination-related data structures */
buzbeeed3e9302011-09-23 17:34:19 -0700223STATIC bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700224{
225 int numTotalBlocks = cUnit->blockList.numUsed;
226
227 if (bb->dominators == NULL ) {
228 bb->dominators = oatAllocBitVector(numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800229 false /* expandable */,
230 kBitMapDominators);
buzbee67bf8852011-08-17 17:51:35 -0700231 bb->iDominated = oatAllocBitVector(numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800232 false /* expandable */,
233 kBitMapIDominated);
buzbee67bf8852011-08-17 17:51:35 -0700234 bb->domFrontier = oatAllocBitVector(numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800235 false /* expandable */,
236 kBitMapDomFrontier);
buzbee67bf8852011-08-17 17:51:35 -0700237 } else {
238 oatClearAllBits(bb->dominators);
239 oatClearAllBits(bb->iDominated);
240 oatClearAllBits(bb->domFrontier);
241 }
242 /* Set all bits in the dominator vector */
243 oatSetInitialBits(bb->dominators, numTotalBlocks);
244
245 return true;
246}
247
buzbee5b537102012-01-17 17:33:47 -0800248/*
249 * Worker function to compute each block's dominators. This implementation
250 * is only used when kDebugVerifyDataflow is active and should compute
251 * the same dominator sets as computeBlockDominators.
252 */
253STATIC bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700254{
255 GrowableList* blockList = &cUnit->blockList;
256 int numTotalBlocks = blockList->numUsed;
257 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
buzbee5abfa3e2012-01-31 17:01:43 -0800258 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700259
260 /*
261 * The dominator of the entry block has been preset to itself and we need
262 * to skip the calculation here.
263 */
264 if (bb == cUnit->entryBlock) return false;
265
266 oatSetInitialBits(tempBlockV, numTotalBlocks);
267
268 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800269 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700270 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800271 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
272 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700273 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700274 if (predBB->dominators != NULL) {
275 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
276 }
buzbee67bf8852011-08-17 17:51:35 -0700277 }
278 oatSetBit(tempBlockV, bb->id);
279 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
280 oatCopyBitVector(bb->dominators, tempBlockV);
281 return true;
282 }
283 return false;
284}
285
buzbee5b537102012-01-17 17:33:47 -0800286/*
287 * Worker function to compute the idom. This implementation is only
288 * used when kDebugVerifyDataflow is active and should compute the
289 * same iDom as computeBlockIDom.
290 */
291STATIC bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700292{
293 GrowableList* blockList = &cUnit->blockList;
294 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
295 ArenaBitVectorIterator bvIterator;
296 BasicBlock* iDom;
297
298 if (bb == cUnit->entryBlock) return false;
299
300 oatCopyBitVector(tempBlockV, bb->dominators);
301 oatClearBit(tempBlockV, bb->id);
302 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
303
304 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700305 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700306 if (oatCountSetBits(tempBlockV) == 1) {
307 iDom = (BasicBlock* ) oatGrowableListGetElement(
308 blockList, oatBitVectorIteratorNext(&bvIterator));
309 bb->iDom = iDom;
310 } else {
311 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700312 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700313 while (true) {
314 int nextDom = oatBitVectorIteratorNext(&bvIterator);
315 if (nextDom == -1) break;
316 BasicBlock* nextDomBB = (BasicBlock* )
317 oatGrowableListGetElement(blockList, nextDom);
318 /* iDom dominates nextDom - set new iDom */
319 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
320 iDomIdx = nextDom;
321 }
322
323 }
324 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
325 /* Set the immediate dominator block for bb */
326 bb->iDom = iDom;
327 }
328 /* Add bb to the iDominated set of the immediate dominator block */
329 oatSetBit(iDom->iDominated, bb->id);
330 return true;
331}
332
buzbee5b537102012-01-17 17:33:47 -0800333/*
334 * Walk through the ordered iDom list until we reach common parent.
335 * Given the ordering of iDomList, this common parent represents the
336 * last element of the intersection of block1 and block2 dominators.
337 */
338int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
339{
340 while (block1 != block2) {
341 while (block1 < block2) {
342 block1 = cUnit->iDomList[block1];
343 DCHECK_NE(block1, NOTVISITED);
344 }
345 while (block2 < block1) {
346 block2 = cUnit->iDomList[block2];
347 DCHECK_NE(block2, NOTVISITED);
348 }
349 }
350 return block1;
351}
352
353/* Worker function to compute each block's immediate dominator */
354STATIC bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
355{
buzbee5abfa3e2012-01-31 17:01:43 -0800356 GrowableListIterator iter;
buzbee5b537102012-01-17 17:33:47 -0800357 int idom = -1;
358
359 /* Special-case entry block */
360 if (bb == cUnit->entryBlock) {
361 return false;
362 }
363
364 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800365 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee5b537102012-01-17 17:33:47 -0800366
367 /* Find the first processed predecessor */
368 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800369 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
370 CHECK(predBB != NULL);
buzbee5b537102012-01-17 17:33:47 -0800371 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
372 idom = predBB->dfsId;
373 break;
374 }
375 }
376
377 /* Scan the rest of the predecessors */
378 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800379 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
380 if (!predBB) break;
buzbee5b537102012-01-17 17:33:47 -0800381 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
382 continue;
383 } else {
384 idom = findCommonParent(cUnit, predBB->dfsId, idom);
385 }
386 }
387
388 DCHECK_NE(idom, NOTVISITED);
389
390 /* Did something change? */
391 if (cUnit->iDomList[bb->dfsId] != idom) {
392 cUnit->iDomList[bb->dfsId] = idom;
393 return true;
394 }
395 return false;
396}
397
398/* Worker function to compute each block's domintors */
399STATIC bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
400{
401 if (bb == cUnit->entryBlock) {
402 oatClearAllBits(bb->dominators);
403 } else {
404 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
405 }
406 oatSetBit(bb->dominators, bb->id);
407 return false;
408}
409
410STATIC bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
411{
412 if (bb != cUnit->entryBlock) {
413 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
414 DCHECK_NE(iDomDFSIdx, NOTVISITED);
415 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
416 BasicBlock* iDom = (BasicBlock*)
417 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
418 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
419 DCHECK_EQ(bb->iDom->id, iDom->id);
420 }
421 bb->iDom = iDom;
422 /* Add bb to the iDominated set of the immediate dominator block */
423 oatSetBit(iDom->iDominated, bb->id);
424 }
425 return false;
426}
427
buzbee67bf8852011-08-17 17:51:35 -0700428/* Compute dominators, immediate dominator, and dominance fronter */
buzbeeed3e9302011-09-23 17:34:19 -0700429STATIC void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700430{
431 int numReachableBlocks = cUnit->numReachableBlocks;
432 int numTotalBlocks = cUnit->blockList.numUsed;
433
434 /* Initialize domination-related data structures */
435 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
436 kReachableNodes,
437 false /* isIterative */);
438
buzbee5b537102012-01-17 17:33:47 -0800439 /* Initalize & Clear iDomList */
440 if (cUnit->iDomList == NULL) {
buzbee5abfa3e2012-01-31 17:01:43 -0800441 cUnit->iDomList = (int*)oatNew(sizeof(int) * numReachableBlocks, false,
442 kAllocDFInfo);
buzbee5b537102012-01-17 17:33:47 -0800443 }
444 for (int i = 0; i < numReachableBlocks; i++) {
445 cUnit->iDomList[i] = NOTVISITED;
446 }
447
448 /* For post-order, last block is entry block. Set its iDom to istelf */
449 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
450 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
451
452 /* Compute the immediate dominators */
453 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
454 kReversePostOrderTraversal,
455 true /* isIterative */);
456
buzbee67bf8852011-08-17 17:51:35 -0700457 /* Set the dominator for the root node */
458 oatClearAllBits(cUnit->entryBlock->dominators);
459 oatSetBit(cUnit->entryBlock->dominators, cUnit->entryBlock->id);
460
461 if (cUnit->tempBlockV == NULL) {
462 cUnit->tempBlockV = oatAllocBitVector(numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800463 false /* expandable */,
464 kBitMapTmpBlockV);
buzbee67bf8852011-08-17 17:51:35 -0700465 } else {
466 oatClearAllBits(cUnit->tempBlockV);
467 }
buzbee67bf8852011-08-17 17:51:35 -0700468 cUnit->entryBlock->iDom = NULL;
buzbee5b537102012-01-17 17:33:47 -0800469
470 /* For testing, compute sets using alternate mechanism */
471 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
472 // Use alternate mechanism to compute dominators for comparison
473 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
474 kPreOrderDFSTraversal,
475 true /* isIterative */);
476
477 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
478 kReachableNodes,
479 false /* isIterative */);
480 }
481
482 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
483 kReachableNodes,
484 false /* isIterative */);
485
486 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
487 kReversePostOrderTraversal,
488 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700489
490 /*
491 * Now go ahead and compute the post order traversal based on the
492 * iDominated sets.
493 */
494 if (cUnit->domPostOrderTraversal.elemList == NULL) {
buzbee5abfa3e2012-01-31 17:01:43 -0800495 oatInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks,
496 kListDomPostOrderTraversal);
buzbee67bf8852011-08-17 17:51:35 -0700497 } else {
498 cUnit->domPostOrderTraversal.numUsed = 0;
499 }
500
501 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700502 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700503 (unsigned) cUnit->numReachableBlocks);
504
505 /* Now compute the dominance frontier for each block */
506 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
507 kPostOrderDOMTraversal,
508 false /* isIterative */);
509}
510
511/*
512 * Perform dest U= src1 ^ ~src2
513 * This is probably not general enough to be placed in BitVector.[ch].
514 */
buzbeeed3e9302011-09-23 17:34:19 -0700515STATIC void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700516 const ArenaBitVector* src1,
517 const ArenaBitVector* src2)
518{
519 if (dest->storageSize != src1->storageSize ||
520 dest->storageSize != src2->storageSize ||
521 dest->expandable != src1->expandable ||
522 dest->expandable != src2->expandable) {
523 LOG(FATAL) << "Incompatible set properties";
524 }
525
526 unsigned int idx;
527 for (idx = 0; idx < dest->storageSize; idx++) {
528 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
529 }
530}
531
532/*
533 * Iterate through all successor blocks and propagate up the live-in sets.
534 * The calculated result is used for phi-node pruning - where we only need to
535 * insert a phi node if the variable is live-in to the block.
536 */
buzbeeed3e9302011-09-23 17:34:19 -0700537STATIC bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700538{
539 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
540
541 if (bb->dataFlowInfo == NULL) return false;
542 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
543 if (bb->taken && bb->taken->dataFlowInfo)
544 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
545 bb->dataFlowInfo->defV);
546 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
547 computeSuccLiveIn(tempDalvikRegisterV,
548 bb->fallThrough->dataFlowInfo->liveInV,
549 bb->dataFlowInfo->defV);
550 if (bb->successorBlockList.blockListType != kNotUsed) {
551 GrowableListIterator iterator;
552 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
553 &iterator);
554 while (true) {
555 SuccessorBlockInfo *successorBlockInfo =
556 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
557 if (successorBlockInfo == NULL) break;
558 BasicBlock* succBB = successorBlockInfo->block;
559 if (succBB->dataFlowInfo) {
560 computeSuccLiveIn(tempDalvikRegisterV,
561 succBB->dataFlowInfo->liveInV,
562 bb->dataFlowInfo->defV);
563 }
564 }
565 }
566 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
567 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
568 return true;
569 }
570 return false;
571}
572
573/* Insert phi nodes to for each variable to the dominance frontiers */
buzbeeed3e9302011-09-23 17:34:19 -0700574STATIC void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700575{
576 int dalvikReg;
577 const GrowableList* blockList = &cUnit->blockList;
578 ArenaBitVector* phiBlocks =
buzbee5abfa3e2012-01-31 17:01:43 -0800579 oatAllocBitVector(cUnit->numBlocks, false, kBitMapPhi);
buzbee67bf8852011-08-17 17:51:35 -0700580 ArenaBitVector* tmpBlocks =
buzbee5abfa3e2012-01-31 17:01:43 -0800581 oatAllocBitVector(cUnit->numBlocks, false, kBitMapTmpBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700582 ArenaBitVector* inputBlocks =
buzbee5abfa3e2012-01-31 17:01:43 -0800583 oatAllocBitVector(cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700584
585 cUnit->tempDalvikRegisterV =
buzbee5abfa3e2012-01-31 17:01:43 -0800586 oatAllocBitVector(cUnit->numDalvikRegisters, false,
587 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700588
589 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
590 kPostOrderDFSTraversal,
591 true /* isIterative */);
592
593 /* Iterate through each Dalvik register */
594 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
595 bool change;
596 ArenaBitVectorIterator iterator;
597
598 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
599 oatClearAllBits(phiBlocks);
600
601 /* Calculate the phi blocks for each Dalvik register */
602 do {
603 change = false;
604 oatClearAllBits(tmpBlocks);
605 oatBitVectorIteratorInit(inputBlocks, &iterator);
606
607 while (true) {
608 int idx = oatBitVectorIteratorNext(&iterator);
609 if (idx == -1) break;
610 BasicBlock* defBB =
611 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
612
613 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800614 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700615 if (defBB->domFrontier != NULL) {
616 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
617 }
buzbee67bf8852011-08-17 17:51:35 -0700618 }
619 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
620 change = true;
621 oatCopyBitVector(phiBlocks, tmpBlocks);
622
623 /*
624 * Iterate through the original blocks plus the new ones in
625 * the dominance frontier.
626 */
627 oatCopyBitVector(inputBlocks, phiBlocks);
628 oatUnifyBitVectors(inputBlocks, inputBlocks,
629 cUnit->defBlockMatrix[dalvikReg]);
630 }
631 } while (change);
632
633 /*
634 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
635 * register is in the live-in set.
636 */
637 oatBitVectorIteratorInit(phiBlocks, &iterator);
638 while (true) {
639 int idx = oatBitVectorIteratorNext(&iterator);
640 if (idx == -1) break;
641 BasicBlock* phiBB =
642 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
643 /* Variable will be clobbered before being used - no need for phi */
644 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
buzbee5abfa3e2012-01-31 17:01:43 -0800645 MIR *phi = (MIR *) oatNew(sizeof(MIR), true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700646 phi->dalvikInsn.opcode = (Opcode)kMirOpPhi;
647 phi->dalvikInsn.vA = dalvikReg;
648 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700649 phi->meta.phiNext = cUnit->phiList;
650 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700651 oatPrependMIR(phiBB, phi);
652 }
653 }
654}
655
656/*
657 * Worker function to insert phi-operands with latest SSA names from
658 * predecessor blocks
659 */
buzbeeed3e9302011-09-23 17:34:19 -0700660STATIC bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700661{
662 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
buzbee5abfa3e2012-01-31 17:01:43 -0800663 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700664 MIR *mir;
665
666 /* Phi nodes are at the beginning of each block */
667 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
668 if (mir->dalvikInsn.opcode != (Opcode)kMirOpPhi)
669 return true;
670 int ssaReg = mir->ssaRep->defs[0];
671 int encodedDalvikValue =
672 (int) oatGrowableListGetElement(cUnit->ssaToDalvikMap, ssaReg);
673 int dalvikReg = DECODE_REG(encodedDalvikValue);
674
675 oatClearAllBits(ssaRegV);
676
677 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800678 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700679 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800680 BasicBlock* predBB =
681 (BasicBlock*)oatGrowableListIteratorNext(&iter);
682 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700683 int encodedSSAValue =
684 predBB->dataFlowInfo->dalvikToSSAMap[dalvikReg];
685 int ssaReg = DECODE_REG(encodedSSAValue);
686 oatSetBit(ssaRegV, ssaReg);
687 }
688
689 /* Count the number of SSA registers for a Dalvik register */
690 int numUses = oatCountSetBits(ssaRegV);
691 mir->ssaRep->numUses = numUses;
692 mir->ssaRep->uses =
buzbee5abfa3e2012-01-31 17:01:43 -0800693 (int *) oatNew(sizeof(int) * numUses, false, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700694 mir->ssaRep->fpUse =
buzbee5abfa3e2012-01-31 17:01:43 -0800695 (bool *) oatNew(sizeof(bool) * numUses, true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700696
697 ArenaBitVectorIterator phiIterator;
698
699 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
700 int *usePtr = mir->ssaRep->uses;
701
702 /* Set the uses array for the phi node */
703 while (true) {
704 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
705 if (ssaRegIdx == -1) break;
706 *usePtr++ = ssaRegIdx;
707 }
708 }
709
710 return true;
711}
712
buzbeeed3e9302011-09-23 17:34:19 -0700713STATIC void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700714{
715
716 if (block->visited || block->hidden) return;
717 block->visited = true;
718
719 /* Process this block */
720 oatDoSSAConversion(cUnit, block);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800721 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700722
723 /* Save SSA map snapshot */
buzbee5abfa3e2012-01-31 17:01:43 -0800724 int* savedSSAMap = (int*)oatNew(mapSize, false, kAllocDalvikToSSAMap);
buzbeef0cde542011-09-13 14:55:02 -0700725 memcpy(savedSSAMap, cUnit->dalvikToSSAMap, mapSize);
726
727 if (block->fallThrough) {
728 doDFSPreOrderSSARename(cUnit, block->fallThrough);
729 /* Restore SSA map snapshot */
730 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
731 }
732 if (block->taken) {
733 doDFSPreOrderSSARename(cUnit, block->taken);
734 /* Restore SSA map snapshot */
735 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
736 }
737 if (block->successorBlockList.blockListType != kNotUsed) {
738 GrowableListIterator iterator;
739 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
740 &iterator);
741 while (true) {
742 SuccessorBlockInfo *successorBlockInfo =
743 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
744 if (successorBlockInfo == NULL) break;
745 BasicBlock* succBB = successorBlockInfo->block;
746 doDFSPreOrderSSARename(cUnit, succBB);
747 /* Restore SSA map snapshot */
748 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
749 }
750 }
751 cUnit->dalvikToSSAMap = savedSSAMap;
752 return;
753}
754
buzbee67bf8852011-08-17 17:51:35 -0700755/* Perform SSA transformation for the whole method */
756void oatMethodSSATransformation(CompilationUnit* cUnit)
757{
758 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800759 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700760
buzbee99ba9642012-01-25 14:23:14 -0800761 if (!cUnit->disableDataflow) {
762 /* Compute the dominator info */
763 computeDominators(cUnit);
764 }
buzbee67bf8852011-08-17 17:51:35 -0700765
766 /* Allocate data structures in preparation for SSA conversion */
767 oatInitializeSSAConversion(cUnit);
768
buzbee99ba9642012-01-25 14:23:14 -0800769 if (!cUnit->disableDataflow) {
770 /* Find out the "Dalvik reg def x block" relation */
771 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700772
buzbee99ba9642012-01-25 14:23:14 -0800773 /* Insert phi nodes to dominance frontiers for all variables */
774 insertPhiNodes(cUnit);
775 }
buzbee67bf8852011-08-17 17:51:35 -0700776
777 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700778 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
779 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700780 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700781 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700782
buzbee99ba9642012-01-25 14:23:14 -0800783 if (!cUnit->disableDataflow) {
784 /*
785 * Shared temp bit vector used by each block to count the number of defs
786 * from all the predecessor blocks.
787 */
buzbee5abfa3e2012-01-31 17:01:43 -0800788 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit->numSSARegs, false,
789 kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700790
buzbee99ba9642012-01-25 14:23:14 -0800791 /* Insert phi-operands with latest SSA names from predecessor blocks */
792 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
793 kReachableNodes,
794 false /* isIterative */);
795 }
buzbee67bf8852011-08-17 17:51:35 -0700796}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800797
798} // namespace art