blob: 2daa533a7b2cd4d67324bac34962425acb330fb4 [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) {
33 block->fallThrough->fallThroughTarget = true;
34 recordDFSOrders(cUnit, block->fallThrough);
35 }
buzbee5b537102012-01-17 17:33:47 -080036 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070037 if (block->successorBlockList.blockListType != kNotUsed) {
38 GrowableListIterator iterator;
39 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
40 &iterator);
41 while (true) {
42 SuccessorBlockInfo *successorBlockInfo =
43 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
44 if (successorBlockInfo == NULL) break;
45 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080046 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070047 }
48 }
buzbee5b537102012-01-17 17:33:47 -080049
50 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
51 block->dfsId = cUnit->dfsPostOrder.numUsed;
buzbeeba938cb2012-02-03 14:47:55 -080052 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070053 return;
54}
55
buzbee5b537102012-01-17 17:33:47 -080056/* Sort the blocks by the Depth-First-Search */
buzbee31a4a6f2012-02-28 15:36:15 -080057void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070058{
buzbee5b537102012-01-17 17:33:47 -080059 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070060 if (cUnit->dfsOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080061 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
62 kListDfsOrder);
buzbee67bf8852011-08-17 17:51:35 -070063 } else {
64 /* Just reset the used length on the counter */
65 cUnit->dfsOrder.numUsed = 0;
66 }
67
buzbee5b537102012-01-17 17:33:47 -080068 /* Initialize or reset the DFS postOrder list */
69 if (cUnit->dfsPostOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080070 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -080071 kListDfsPostOrder);
buzbee5b537102012-01-17 17:33:47 -080072 } else {
73 /* Just reset the used length on the counter */
74 cUnit->dfsPostOrder.numUsed = 0;
75 }
76
buzbee67bf8852011-08-17 17:51:35 -070077 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
78 kAllNodes,
79 false /* isIterative */);
80
buzbee5b537102012-01-17 17:33:47 -080081 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070082 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
83}
84
85/*
86 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
87 * register idx is defined in BasicBlock bb.
88 */
buzbee31a4a6f2012-02-28 15:36:15 -080089bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070090{
91 if (bb->dataFlowInfo == NULL) return false;
92
93 ArenaBitVectorIterator iterator;
94
95 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
96 while (true) {
97 int idx = oatBitVectorIteratorNext(&iterator);
98 if (idx == -1) break;
99 /* Block bb defines register idx */
buzbeeba938cb2012-02-03 14:47:55 -0800100 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700101 }
102 return true;
103}
104
buzbee31a4a6f2012-02-28 15:36:15 -0800105void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700106{
107 int numRegisters = cUnit->numDalvikRegisters;
108 /* Allocate numDalvikRegisters bit vector pointers */
109 cUnit->defBlockMatrix = (ArenaBitVector **)
buzbeeba938cb2012-02-03 14:47:55 -0800110 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
buzbee5abfa3e2012-01-31 17:01:43 -0800111 kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700112 int i;
113
114 /* Initialize numRegister vectors with numBlocks bits each */
115 for (i = 0; i < numRegisters; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800116 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
117 false, kBitMapBMatrix);
buzbee67bf8852011-08-17 17:51:35 -0700118 }
119 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
120 kAllNodes,
121 false /* isIterative */);
122 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
123 kAllNodes,
124 false /* isIterative */);
125
126 /*
127 * Also set the incoming parameters as defs in the entry block.
128 * Only need to handle the parameters for the outer method.
129 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800130 int numRegs = cUnit->numDalvikRegisters;
131 int inReg = numRegs - cUnit->numIns;
132 for (; inReg < numRegs; inReg++) {
buzbeeba938cb2012-02-03 14:47:55 -0800133 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700134 }
135}
136
137/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800138void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700139{
140 ArenaBitVectorIterator bvIterator;
141 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
142 GrowableList* blockList = &cUnit->blockList;
143
144 /* Iterate through the dominated blocks first */
145 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800146 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700147 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
148 if (bbIdx == -1) break;
149 BasicBlock* dominatedBB =
150 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
151 computeDomPostOrderTraversal(cUnit, dominatedBB);
152 }
153
154 /* Enter the current block id */
buzbeeba938cb2012-02-03 14:47:55 -0800155 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700156
157 /* hacky loop detection */
158 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
159 cUnit->hasLoop = true;
160 }
161}
162
buzbee31a4a6f2012-02-28 15:36:15 -0800163void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
164 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700165{
166 /*
167 * TODO - evaluate whether phi will ever need to be inserted into exit
168 * blocks.
169 */
170 if (succBB->iDom != domBB &&
171 succBB->blockType == kDalvikByteCode &&
172 succBB->hidden == false) {
buzbeeba938cb2012-02-03 14:47:55 -0800173 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700174 }
175}
176
177/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800178bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700179{
180 GrowableList* blockList = &cUnit->blockList;
181
182 /* Calculate DF_local */
183 if (bb->taken) {
buzbeeba938cb2012-02-03 14:47:55 -0800184 checkForDominanceFrontier(cUnit, bb, bb->taken);
buzbee67bf8852011-08-17 17:51:35 -0700185 }
186 if (bb->fallThrough) {
buzbeeba938cb2012-02-03 14:47:55 -0800187 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
buzbee67bf8852011-08-17 17:51:35 -0700188 }
189 if (bb->successorBlockList.blockListType != kNotUsed) {
190 GrowableListIterator iterator;
191 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
192 &iterator);
193 while (true) {
194 SuccessorBlockInfo *successorBlockInfo =
195 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
196 if (successorBlockInfo == NULL) break;
197 BasicBlock* succBB = successorBlockInfo->block;
buzbeeba938cb2012-02-03 14:47:55 -0800198 checkForDominanceFrontier(cUnit, bb, succBB);
buzbee67bf8852011-08-17 17:51:35 -0700199 }
200 }
201
202 /* Calculate DF_up */
203 ArenaBitVectorIterator bvIterator;
204 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
205 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800206 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700207 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
208 if (dominatedIdx == -1) break;
209 BasicBlock* dominatedBB = (BasicBlock* )
210 oatGrowableListGetElement(blockList, dominatedIdx);
211 ArenaBitVectorIterator dfIterator;
212 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
213 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800214 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700215 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
216 if (dfUpIdx == -1) break;
217 BasicBlock* dfUpBlock = (BasicBlock* )
218 oatGrowableListGetElement(blockList, dfUpIdx);
buzbeeba938cb2012-02-03 14:47:55 -0800219 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700220 }
221 }
222
223 return true;
224}
225
226/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800227bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700228{
229 int numTotalBlocks = cUnit->blockList.numUsed;
230
231 if (bb->dominators == NULL ) {
buzbeeba938cb2012-02-03 14:47:55 -0800232 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800233 false /* expandable */,
234 kBitMapDominators);
buzbeeba938cb2012-02-03 14:47:55 -0800235 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800236 false /* expandable */,
237 kBitMapIDominated);
buzbeeba938cb2012-02-03 14:47:55 -0800238 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800239 false /* expandable */,
240 kBitMapDomFrontier);
buzbee67bf8852011-08-17 17:51:35 -0700241 } else {
242 oatClearAllBits(bb->dominators);
243 oatClearAllBits(bb->iDominated);
244 oatClearAllBits(bb->domFrontier);
245 }
246 /* Set all bits in the dominator vector */
247 oatSetInitialBits(bb->dominators, numTotalBlocks);
248
249 return true;
250}
251
buzbee5b537102012-01-17 17:33:47 -0800252/*
253 * Worker function to compute each block's dominators. This implementation
254 * is only used when kDebugVerifyDataflow is active and should compute
255 * the same dominator sets as computeBlockDominators.
256 */
buzbee31a4a6f2012-02-28 15:36:15 -0800257bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700258{
259 GrowableList* blockList = &cUnit->blockList;
260 int numTotalBlocks = blockList->numUsed;
261 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
buzbee5abfa3e2012-01-31 17:01:43 -0800262 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700263
264 /*
265 * The dominator of the entry block has been preset to itself and we need
266 * to skip the calculation here.
267 */
268 if (bb == cUnit->entryBlock) return false;
269
270 oatSetInitialBits(tempBlockV, numTotalBlocks);
271
272 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800273 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700274 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800275 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
276 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700277 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700278 if (predBB->dominators != NULL) {
279 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
280 }
buzbee67bf8852011-08-17 17:51:35 -0700281 }
buzbeeba938cb2012-02-03 14:47:55 -0800282 oatSetBit(cUnit, tempBlockV, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700283 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
284 oatCopyBitVector(bb->dominators, tempBlockV);
285 return true;
286 }
287 return false;
288}
289
buzbee5b537102012-01-17 17:33:47 -0800290/*
291 * Worker function to compute the idom. This implementation is only
292 * used when kDebugVerifyDataflow is active and should compute the
293 * same iDom as computeBlockIDom.
294 */
buzbee31a4a6f2012-02-28 15:36:15 -0800295bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700296{
297 GrowableList* blockList = &cUnit->blockList;
298 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
299 ArenaBitVectorIterator bvIterator;
300 BasicBlock* iDom;
301
302 if (bb == cUnit->entryBlock) return false;
303
304 oatCopyBitVector(tempBlockV, bb->dominators);
305 oatClearBit(tempBlockV, bb->id);
306 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
307
308 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700309 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700310 if (oatCountSetBits(tempBlockV) == 1) {
311 iDom = (BasicBlock* ) oatGrowableListGetElement(
312 blockList, oatBitVectorIteratorNext(&bvIterator));
313 bb->iDom = iDom;
314 } else {
315 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700316 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700317 while (true) {
318 int nextDom = oatBitVectorIteratorNext(&bvIterator);
319 if (nextDom == -1) break;
320 BasicBlock* nextDomBB = (BasicBlock* )
321 oatGrowableListGetElement(blockList, nextDom);
322 /* iDom dominates nextDom - set new iDom */
323 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
324 iDomIdx = nextDom;
325 }
326
327 }
328 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
329 /* Set the immediate dominator block for bb */
330 bb->iDom = iDom;
331 }
332 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800333 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700334 return true;
335}
336
buzbee5b537102012-01-17 17:33:47 -0800337/*
338 * Walk through the ordered iDom list until we reach common parent.
339 * Given the ordering of iDomList, this common parent represents the
340 * last element of the intersection of block1 and block2 dominators.
341 */
342int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
343{
344 while (block1 != block2) {
345 while (block1 < block2) {
346 block1 = cUnit->iDomList[block1];
347 DCHECK_NE(block1, NOTVISITED);
348 }
349 while (block2 < block1) {
350 block2 = cUnit->iDomList[block2];
351 DCHECK_NE(block2, NOTVISITED);
352 }
353 }
354 return block1;
355}
356
357/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800358bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800359{
buzbee5abfa3e2012-01-31 17:01:43 -0800360 GrowableListIterator iter;
buzbee5b537102012-01-17 17:33:47 -0800361 int idom = -1;
362
363 /* Special-case entry block */
364 if (bb == cUnit->entryBlock) {
365 return false;
366 }
367
368 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800369 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee5b537102012-01-17 17:33:47 -0800370
371 /* Find the first processed predecessor */
372 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800373 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
374 CHECK(predBB != NULL);
buzbee5b537102012-01-17 17:33:47 -0800375 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
376 idom = predBB->dfsId;
377 break;
378 }
379 }
380
381 /* Scan the rest of the predecessors */
382 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800383 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
384 if (!predBB) break;
buzbee5b537102012-01-17 17:33:47 -0800385 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
386 continue;
387 } else {
388 idom = findCommonParent(cUnit, predBB->dfsId, idom);
389 }
390 }
391
392 DCHECK_NE(idom, NOTVISITED);
393
394 /* Did something change? */
395 if (cUnit->iDomList[bb->dfsId] != idom) {
396 cUnit->iDomList[bb->dfsId] = idom;
397 return true;
398 }
399 return false;
400}
401
402/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800403bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800404{
405 if (bb == cUnit->entryBlock) {
406 oatClearAllBits(bb->dominators);
407 } else {
408 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
409 }
buzbeeba938cb2012-02-03 14:47:55 -0800410 oatSetBit(cUnit, bb->dominators, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800411 return false;
412}
413
buzbee31a4a6f2012-02-28 15:36:15 -0800414bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800415{
416 if (bb != cUnit->entryBlock) {
417 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
418 DCHECK_NE(iDomDFSIdx, NOTVISITED);
419 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
420 BasicBlock* iDom = (BasicBlock*)
421 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
422 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
423 DCHECK_EQ(bb->iDom->id, iDom->id);
424 }
425 bb->iDom = iDom;
426 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800427 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800428 }
429 return false;
430}
431
buzbee67bf8852011-08-17 17:51:35 -0700432/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800433void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700434{
435 int numReachableBlocks = cUnit->numReachableBlocks;
436 int numTotalBlocks = cUnit->blockList.numUsed;
437
438 /* Initialize domination-related data structures */
439 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
440 kReachableNodes,
441 false /* isIterative */);
442
buzbee5b537102012-01-17 17:33:47 -0800443 /* Initalize & Clear iDomList */
444 if (cUnit->iDomList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800445 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
446 false, kAllocDFInfo);
buzbee5b537102012-01-17 17:33:47 -0800447 }
448 for (int i = 0; i < numReachableBlocks; i++) {
449 cUnit->iDomList[i] = NOTVISITED;
450 }
451
452 /* For post-order, last block is entry block. Set its iDom to istelf */
453 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
454 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
455
456 /* Compute the immediate dominators */
457 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
458 kReversePostOrderTraversal,
459 true /* isIterative */);
460
buzbee67bf8852011-08-17 17:51:35 -0700461 /* Set the dominator for the root node */
462 oatClearAllBits(cUnit->entryBlock->dominators);
buzbeeba938cb2012-02-03 14:47:55 -0800463 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700464
465 if (cUnit->tempBlockV == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800466 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800467 false /* expandable */,
468 kBitMapTmpBlockV);
buzbee67bf8852011-08-17 17:51:35 -0700469 } else {
470 oatClearAllBits(cUnit->tempBlockV);
471 }
buzbee67bf8852011-08-17 17:51:35 -0700472 cUnit->entryBlock->iDom = NULL;
buzbee5b537102012-01-17 17:33:47 -0800473
474 /* For testing, compute sets using alternate mechanism */
475 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
476 // Use alternate mechanism to compute dominators for comparison
477 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
478 kPreOrderDFSTraversal,
479 true /* isIterative */);
480
481 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
482 kReachableNodes,
483 false /* isIterative */);
484 }
485
486 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
487 kReachableNodes,
488 false /* isIterative */);
489
490 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
491 kReversePostOrderTraversal,
492 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700493
494 /*
495 * Now go ahead and compute the post order traversal based on the
496 * iDominated sets.
497 */
498 if (cUnit->domPostOrderTraversal.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800499 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
500 numReachableBlocks, kListDomPostOrderTraversal);
buzbee67bf8852011-08-17 17:51:35 -0700501 } else {
502 cUnit->domPostOrderTraversal.numUsed = 0;
503 }
504
505 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700506 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700507 (unsigned) cUnit->numReachableBlocks);
508
509 /* Now compute the dominance frontier for each block */
510 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
511 kPostOrderDOMTraversal,
512 false /* isIterative */);
513}
514
515/*
516 * Perform dest U= src1 ^ ~src2
517 * This is probably not general enough to be placed in BitVector.[ch].
518 */
buzbee31a4a6f2012-02-28 15:36:15 -0800519void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700520 const ArenaBitVector* src1,
521 const ArenaBitVector* src2)
522{
523 if (dest->storageSize != src1->storageSize ||
524 dest->storageSize != src2->storageSize ||
525 dest->expandable != src1->expandable ||
526 dest->expandable != src2->expandable) {
527 LOG(FATAL) << "Incompatible set properties";
528 }
529
530 unsigned int idx;
531 for (idx = 0; idx < dest->storageSize; idx++) {
532 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
533 }
534}
535
536/*
537 * Iterate through all successor blocks and propagate up the live-in sets.
538 * The calculated result is used for phi-node pruning - where we only need to
539 * insert a phi node if the variable is live-in to the block.
540 */
buzbee31a4a6f2012-02-28 15:36:15 -0800541bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700542{
543 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
544
545 if (bb->dataFlowInfo == NULL) return false;
546 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
547 if (bb->taken && bb->taken->dataFlowInfo)
548 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
549 bb->dataFlowInfo->defV);
550 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
551 computeSuccLiveIn(tempDalvikRegisterV,
552 bb->fallThrough->dataFlowInfo->liveInV,
553 bb->dataFlowInfo->defV);
554 if (bb->successorBlockList.blockListType != kNotUsed) {
555 GrowableListIterator iterator;
556 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
557 &iterator);
558 while (true) {
559 SuccessorBlockInfo *successorBlockInfo =
560 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
561 if (successorBlockInfo == NULL) break;
562 BasicBlock* succBB = successorBlockInfo->block;
563 if (succBB->dataFlowInfo) {
564 computeSuccLiveIn(tempDalvikRegisterV,
565 succBB->dataFlowInfo->liveInV,
566 bb->dataFlowInfo->defV);
567 }
568 }
569 }
570 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
571 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
572 return true;
573 }
574 return false;
575}
576
577/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800578void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700579{
580 int dalvikReg;
581 const GrowableList* blockList = &cUnit->blockList;
582 ArenaBitVector* phiBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800583 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
buzbee67bf8852011-08-17 17:51:35 -0700584 ArenaBitVector* tmpBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800585 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700586 ArenaBitVector* inputBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800587 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700588
589 cUnit->tempDalvikRegisterV =
buzbeeba938cb2012-02-03 14:47:55 -0800590 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
buzbee5abfa3e2012-01-31 17:01:43 -0800591 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700592
593 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
594 kPostOrderDFSTraversal,
595 true /* isIterative */);
596
597 /* Iterate through each Dalvik register */
598 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
599 bool change;
600 ArenaBitVectorIterator iterator;
601
602 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
603 oatClearAllBits(phiBlocks);
604
605 /* Calculate the phi blocks for each Dalvik register */
606 do {
607 change = false;
608 oatClearAllBits(tmpBlocks);
609 oatBitVectorIteratorInit(inputBlocks, &iterator);
610
611 while (true) {
612 int idx = oatBitVectorIteratorNext(&iterator);
613 if (idx == -1) break;
614 BasicBlock* defBB =
615 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
616
617 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800618 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700619 if (defBB->domFrontier != NULL) {
620 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
621 }
buzbee67bf8852011-08-17 17:51:35 -0700622 }
623 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
624 change = true;
625 oatCopyBitVector(phiBlocks, tmpBlocks);
626
627 /*
628 * Iterate through the original blocks plus the new ones in
629 * the dominance frontier.
630 */
631 oatCopyBitVector(inputBlocks, phiBlocks);
632 oatUnifyBitVectors(inputBlocks, inputBlocks,
633 cUnit->defBlockMatrix[dalvikReg]);
634 }
635 } while (change);
636
637 /*
638 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
639 * register is in the live-in set.
640 */
641 oatBitVectorIteratorInit(phiBlocks, &iterator);
642 while (true) {
643 int idx = oatBitVectorIteratorNext(&iterator);
644 if (idx == -1) break;
645 BasicBlock* phiBB =
646 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
647 /* Variable will be clobbered before being used - no need for phi */
648 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
buzbeeba938cb2012-02-03 14:47:55 -0800649 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800650 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
buzbee67bf8852011-08-17 17:51:35 -0700651 phi->dalvikInsn.vA = dalvikReg;
652 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700653 phi->meta.phiNext = cUnit->phiList;
654 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700655 oatPrependMIR(phiBB, phi);
656 }
657 }
658}
659
660/*
661 * Worker function to insert phi-operands with latest SSA names from
662 * predecessor blocks
663 */
buzbee31a4a6f2012-02-28 15:36:15 -0800664bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700665{
666 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
buzbee5abfa3e2012-01-31 17:01:43 -0800667 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700668 MIR *mir;
669
670 /* Phi nodes are at the beginning of each block */
671 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800672 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
buzbee67bf8852011-08-17 17:51:35 -0700673 return true;
674 int ssaReg = mir->ssaRep->defs[0];
buzbeee1965672012-03-11 18:39:19 -0700675 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
676 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700677
678 oatClearAllBits(ssaRegV);
679
680 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800681 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700682 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800683 BasicBlock* predBB =
684 (BasicBlock*)oatGrowableListIteratorNext(&iter);
685 if (!predBB) break;
buzbeee1965672012-03-11 18:39:19 -0700686 int ssaReg =
687 predBB->dataFlowInfo->vRegToSSAMap[vReg];
buzbeeba938cb2012-02-03 14:47:55 -0800688 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700689 }
690
691 /* Count the number of SSA registers for a Dalvik register */
692 int numUses = oatCountSetBits(ssaRegV);
693 mir->ssaRep->numUses = numUses;
694 mir->ssaRep->uses =
buzbeeba938cb2012-02-03 14:47:55 -0800695 (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700696 mir->ssaRep->fpUse =
buzbeeba938cb2012-02-03 14:47:55 -0800697 (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700698
699 ArenaBitVectorIterator phiIterator;
700
701 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
702 int *usePtr = mir->ssaRep->uses;
703
704 /* Set the uses array for the phi node */
705 while (true) {
706 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
707 if (ssaRegIdx == -1) break;
708 *usePtr++ = ssaRegIdx;
709 }
710 }
711
712 return true;
713}
714
buzbee31a4a6f2012-02-28 15:36:15 -0800715void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700716{
717
718 if (block->visited || block->hidden) return;
719 block->visited = true;
720
721 /* Process this block */
722 oatDoSSAConversion(cUnit, block);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800723 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700724
725 /* Save SSA map snapshot */
buzbeeba938cb2012-02-03 14:47:55 -0800726 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
727 kAllocDalvikToSSAMap);
buzbeee1965672012-03-11 18:39:19 -0700728 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700729
730 if (block->fallThrough) {
731 doDFSPreOrderSSARename(cUnit, block->fallThrough);
732 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700733 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700734 }
735 if (block->taken) {
736 doDFSPreOrderSSARename(cUnit, block->taken);
737 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700738 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700739 }
740 if (block->successorBlockList.blockListType != kNotUsed) {
741 GrowableListIterator iterator;
742 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
743 &iterator);
744 while (true) {
745 SuccessorBlockInfo *successorBlockInfo =
746 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
747 if (successorBlockInfo == NULL) break;
748 BasicBlock* succBB = successorBlockInfo->block;
749 doDFSPreOrderSSARename(cUnit, succBB);
750 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700751 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700752 }
753 }
buzbeee1965672012-03-11 18:39:19 -0700754 cUnit->vRegToSSAMap = savedSSAMap;
buzbeef0cde542011-09-13 14:55:02 -0700755 return;
756}
757
buzbee67bf8852011-08-17 17:51:35 -0700758/* Perform SSA transformation for the whole method */
759void oatMethodSSATransformation(CompilationUnit* cUnit)
760{
761 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800762 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700763
buzbee99ba9642012-01-25 14:23:14 -0800764 if (!cUnit->disableDataflow) {
765 /* Compute the dominator info */
766 computeDominators(cUnit);
767 }
buzbee67bf8852011-08-17 17:51:35 -0700768
769 /* Allocate data structures in preparation for SSA conversion */
770 oatInitializeSSAConversion(cUnit);
771
buzbee99ba9642012-01-25 14:23:14 -0800772 if (!cUnit->disableDataflow) {
773 /* Find out the "Dalvik reg def x block" relation */
774 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700775
buzbee99ba9642012-01-25 14:23:14 -0800776 /* Insert phi nodes to dominance frontiers for all variables */
777 insertPhiNodes(cUnit);
778 }
buzbee67bf8852011-08-17 17:51:35 -0700779
780 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700781 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
782 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700783 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700784 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700785
buzbee99ba9642012-01-25 14:23:14 -0800786 if (!cUnit->disableDataflow) {
787 /*
788 * Shared temp bit vector used by each block to count the number of defs
789 * from all the predecessor blocks.
790 */
buzbeeba938cb2012-02-03 14:47:55 -0800791 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
792 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700793
buzbee99ba9642012-01-25 14:23:14 -0800794 /* Insert phi-operands with latest SSA names from predecessor blocks */
795 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
796 kReachableNodes,
797 false /* isIterative */);
798 }
buzbee67bf8852011-08-17 17:51:35 -0700799}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800800
801} // namespace art