blob: c5a6b8f7b1c539de812ef16560ebf22fb9fc0bf6 [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
buzbee3d661942012-03-14 17:37:27 -070029 // Can this block be reached only via previous block fallthrough?
30 if ((block->blockType == kDalvikByteCode) &&
31 (block->predecessors->numUsed == 1)) {
32 DCHECK_GE(cUnit->dfsOrder.numUsed, 1U);
33 int prevIdx = cUnit->dfsOrder.numUsed - 1;
34 int prevId = cUnit->dfsOrder.elemList[prevIdx];
35 BasicBlock* predBB = (BasicBlock*)block->predecessors->elemList[0];
36 if (predBB->id == prevId) {
37 block->fallThroughTarget = true;
38 }
39 }
40
buzbee5b537102012-01-17 17:33:47 -080041 /* Enqueue the preOrder block id */
buzbeeba938cb2012-02-03 14:47:55 -080042 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070043
buzbeee1965672012-03-11 18:39:19 -070044 if (block->fallThrough) {
buzbeee1965672012-03-11 18:39:19 -070045 recordDFSOrders(cUnit, block->fallThrough);
46 }
buzbee5b537102012-01-17 17:33:47 -080047 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070048 if (block->successorBlockList.blockListType != kNotUsed) {
49 GrowableListIterator iterator;
50 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
51 &iterator);
52 while (true) {
53 SuccessorBlockInfo *successorBlockInfo =
54 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
55 if (successorBlockInfo == NULL) break;
56 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080057 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070058 }
59 }
buzbee5b537102012-01-17 17:33:47 -080060
61 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
62 block->dfsId = cUnit->dfsPostOrder.numUsed;
buzbeeba938cb2012-02-03 14:47:55 -080063 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070064 return;
65}
66
buzbee5b537102012-01-17 17:33:47 -080067/* Sort the blocks by the Depth-First-Search */
buzbee31a4a6f2012-02-28 15:36:15 -080068void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070069{
buzbee5b537102012-01-17 17:33:47 -080070 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070071 if (cUnit->dfsOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080072 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
73 kListDfsOrder);
buzbee67bf8852011-08-17 17:51:35 -070074 } else {
75 /* Just reset the used length on the counter */
76 cUnit->dfsOrder.numUsed = 0;
77 }
78
buzbee5b537102012-01-17 17:33:47 -080079 /* Initialize or reset the DFS postOrder list */
80 if (cUnit->dfsPostOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080081 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -080082 kListDfsPostOrder);
buzbee5b537102012-01-17 17:33:47 -080083 } else {
84 /* Just reset the used length on the counter */
85 cUnit->dfsPostOrder.numUsed = 0;
86 }
87
buzbee67bf8852011-08-17 17:51:35 -070088 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
89 kAllNodes,
90 false /* isIterative */);
91
buzbee5b537102012-01-17 17:33:47 -080092 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070093 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
94}
95
96/*
97 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
98 * register idx is defined in BasicBlock bb.
99 */
buzbee31a4a6f2012-02-28 15:36:15 -0800100bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700101{
102 if (bb->dataFlowInfo == NULL) return false;
103
104 ArenaBitVectorIterator iterator;
105
106 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
107 while (true) {
108 int idx = oatBitVectorIteratorNext(&iterator);
109 if (idx == -1) break;
110 /* Block bb defines register idx */
buzbeeba938cb2012-02-03 14:47:55 -0800111 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700112 }
113 return true;
114}
115
buzbee31a4a6f2012-02-28 15:36:15 -0800116void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700117{
118 int numRegisters = cUnit->numDalvikRegisters;
119 /* Allocate numDalvikRegisters bit vector pointers */
120 cUnit->defBlockMatrix = (ArenaBitVector **)
buzbeeba938cb2012-02-03 14:47:55 -0800121 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
buzbee5abfa3e2012-01-31 17:01:43 -0800122 kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700123 int i;
124
125 /* Initialize numRegister vectors with numBlocks bits each */
126 for (i = 0; i < numRegisters; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800127 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
128 false, kBitMapBMatrix);
buzbee67bf8852011-08-17 17:51:35 -0700129 }
130 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
131 kAllNodes,
132 false /* isIterative */);
133 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
134 kAllNodes,
135 false /* isIterative */);
136
137 /*
138 * Also set the incoming parameters as defs in the entry block.
139 * Only need to handle the parameters for the outer method.
140 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800141 int numRegs = cUnit->numDalvikRegisters;
142 int inReg = numRegs - cUnit->numIns;
143 for (; inReg < numRegs; inReg++) {
buzbeeba938cb2012-02-03 14:47:55 -0800144 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700145 }
146}
147
148/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800149void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700150{
151 ArenaBitVectorIterator bvIterator;
152 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
153 GrowableList* blockList = &cUnit->blockList;
154
155 /* Iterate through the dominated blocks first */
156 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800157 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700158 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
159 if (bbIdx == -1) break;
160 BasicBlock* dominatedBB =
161 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
162 computeDomPostOrderTraversal(cUnit, dominatedBB);
163 }
164
165 /* Enter the current block id */
buzbeeba938cb2012-02-03 14:47:55 -0800166 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700167
168 /* hacky loop detection */
169 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
170 cUnit->hasLoop = true;
171 }
172}
173
buzbee31a4a6f2012-02-28 15:36:15 -0800174void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
175 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700176{
177 /*
178 * TODO - evaluate whether phi will ever need to be inserted into exit
179 * blocks.
180 */
181 if (succBB->iDom != domBB &&
182 succBB->blockType == kDalvikByteCode &&
183 succBB->hidden == false) {
buzbeeba938cb2012-02-03 14:47:55 -0800184 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700185 }
186}
187
188/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800189bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700190{
191 GrowableList* blockList = &cUnit->blockList;
192
193 /* Calculate DF_local */
194 if (bb->taken) {
buzbeeba938cb2012-02-03 14:47:55 -0800195 checkForDominanceFrontier(cUnit, bb, bb->taken);
buzbee67bf8852011-08-17 17:51:35 -0700196 }
197 if (bb->fallThrough) {
buzbeeba938cb2012-02-03 14:47:55 -0800198 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
buzbee67bf8852011-08-17 17:51:35 -0700199 }
200 if (bb->successorBlockList.blockListType != kNotUsed) {
201 GrowableListIterator iterator;
202 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
203 &iterator);
204 while (true) {
205 SuccessorBlockInfo *successorBlockInfo =
206 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
207 if (successorBlockInfo == NULL) break;
208 BasicBlock* succBB = successorBlockInfo->block;
buzbeeba938cb2012-02-03 14:47:55 -0800209 checkForDominanceFrontier(cUnit, bb, succBB);
buzbee67bf8852011-08-17 17:51:35 -0700210 }
211 }
212
213 /* Calculate DF_up */
214 ArenaBitVectorIterator bvIterator;
215 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
216 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800217 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700218 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
219 if (dominatedIdx == -1) break;
220 BasicBlock* dominatedBB = (BasicBlock* )
221 oatGrowableListGetElement(blockList, dominatedIdx);
222 ArenaBitVectorIterator dfIterator;
223 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
224 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800225 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700226 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
227 if (dfUpIdx == -1) break;
228 BasicBlock* dfUpBlock = (BasicBlock* )
229 oatGrowableListGetElement(blockList, dfUpIdx);
buzbeeba938cb2012-02-03 14:47:55 -0800230 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700231 }
232 }
233
234 return true;
235}
236
237/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800238bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700239{
240 int numTotalBlocks = cUnit->blockList.numUsed;
241
242 if (bb->dominators == NULL ) {
buzbeeba938cb2012-02-03 14:47:55 -0800243 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800244 false /* expandable */,
245 kBitMapDominators);
buzbeeba938cb2012-02-03 14:47:55 -0800246 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800247 false /* expandable */,
248 kBitMapIDominated);
buzbeeba938cb2012-02-03 14:47:55 -0800249 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800250 false /* expandable */,
251 kBitMapDomFrontier);
buzbee67bf8852011-08-17 17:51:35 -0700252 } else {
253 oatClearAllBits(bb->dominators);
254 oatClearAllBits(bb->iDominated);
255 oatClearAllBits(bb->domFrontier);
256 }
257 /* Set all bits in the dominator vector */
258 oatSetInitialBits(bb->dominators, numTotalBlocks);
259
260 return true;
261}
262
buzbee5b537102012-01-17 17:33:47 -0800263/*
264 * Worker function to compute each block's dominators. This implementation
265 * is only used when kDebugVerifyDataflow is active and should compute
266 * the same dominator sets as computeBlockDominators.
267 */
buzbee31a4a6f2012-02-28 15:36:15 -0800268bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700269{
270 GrowableList* blockList = &cUnit->blockList;
271 int numTotalBlocks = blockList->numUsed;
272 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
buzbee5abfa3e2012-01-31 17:01:43 -0800273 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700274
275 /*
276 * The dominator of the entry block has been preset to itself and we need
277 * to skip the calculation here.
278 */
279 if (bb == cUnit->entryBlock) return false;
280
281 oatSetInitialBits(tempBlockV, numTotalBlocks);
282
283 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800284 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700285 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800286 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
287 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700288 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700289 if (predBB->dominators != NULL) {
290 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
291 }
buzbee67bf8852011-08-17 17:51:35 -0700292 }
buzbeeba938cb2012-02-03 14:47:55 -0800293 oatSetBit(cUnit, tempBlockV, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700294 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
295 oatCopyBitVector(bb->dominators, tempBlockV);
296 return true;
297 }
298 return false;
299}
300
buzbee5b537102012-01-17 17:33:47 -0800301/*
302 * Worker function to compute the idom. This implementation is only
303 * used when kDebugVerifyDataflow is active and should compute the
304 * same iDom as computeBlockIDom.
305 */
buzbee31a4a6f2012-02-28 15:36:15 -0800306bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700307{
308 GrowableList* blockList = &cUnit->blockList;
309 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
310 ArenaBitVectorIterator bvIterator;
311 BasicBlock* iDom;
312
313 if (bb == cUnit->entryBlock) return false;
314
315 oatCopyBitVector(tempBlockV, bb->dominators);
316 oatClearBit(tempBlockV, bb->id);
317 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
318
319 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700320 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700321 if (oatCountSetBits(tempBlockV) == 1) {
322 iDom = (BasicBlock* ) oatGrowableListGetElement(
323 blockList, oatBitVectorIteratorNext(&bvIterator));
324 bb->iDom = iDom;
325 } else {
326 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700327 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700328 while (true) {
329 int nextDom = oatBitVectorIteratorNext(&bvIterator);
330 if (nextDom == -1) break;
331 BasicBlock* nextDomBB = (BasicBlock* )
332 oatGrowableListGetElement(blockList, nextDom);
333 /* iDom dominates nextDom - set new iDom */
334 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
335 iDomIdx = nextDom;
336 }
337
338 }
339 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
340 /* Set the immediate dominator block for bb */
341 bb->iDom = iDom;
342 }
343 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800344 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700345 return true;
346}
347
buzbee5b537102012-01-17 17:33:47 -0800348/*
349 * Walk through the ordered iDom list until we reach common parent.
350 * Given the ordering of iDomList, this common parent represents the
351 * last element of the intersection of block1 and block2 dominators.
352 */
353int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
354{
355 while (block1 != block2) {
356 while (block1 < block2) {
357 block1 = cUnit->iDomList[block1];
358 DCHECK_NE(block1, NOTVISITED);
359 }
360 while (block2 < block1) {
361 block2 = cUnit->iDomList[block2];
362 DCHECK_NE(block2, NOTVISITED);
363 }
364 }
365 return block1;
366}
367
368/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800369bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800370{
buzbee5abfa3e2012-01-31 17:01:43 -0800371 GrowableListIterator iter;
buzbee5b537102012-01-17 17:33:47 -0800372 int idom = -1;
373
374 /* Special-case entry block */
375 if (bb == cUnit->entryBlock) {
376 return false;
377 }
378
379 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800380 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee5b537102012-01-17 17:33:47 -0800381
382 /* Find the first processed predecessor */
383 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800384 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
385 CHECK(predBB != NULL);
buzbee5b537102012-01-17 17:33:47 -0800386 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
387 idom = predBB->dfsId;
388 break;
389 }
390 }
391
392 /* Scan the rest of the predecessors */
393 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800394 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
395 if (!predBB) break;
buzbee5b537102012-01-17 17:33:47 -0800396 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
397 continue;
398 } else {
399 idom = findCommonParent(cUnit, predBB->dfsId, idom);
400 }
401 }
402
403 DCHECK_NE(idom, NOTVISITED);
404
405 /* Did something change? */
406 if (cUnit->iDomList[bb->dfsId] != idom) {
407 cUnit->iDomList[bb->dfsId] = idom;
408 return true;
409 }
410 return false;
411}
412
413/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800414bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800415{
416 if (bb == cUnit->entryBlock) {
417 oatClearAllBits(bb->dominators);
418 } else {
419 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
420 }
buzbeeba938cb2012-02-03 14:47:55 -0800421 oatSetBit(cUnit, bb->dominators, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800422 return false;
423}
424
buzbee31a4a6f2012-02-28 15:36:15 -0800425bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800426{
427 if (bb != cUnit->entryBlock) {
428 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
429 DCHECK_NE(iDomDFSIdx, NOTVISITED);
430 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
431 BasicBlock* iDom = (BasicBlock*)
432 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
433 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
434 DCHECK_EQ(bb->iDom->id, iDom->id);
435 }
436 bb->iDom = iDom;
437 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800438 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800439 }
440 return false;
441}
442
buzbee67bf8852011-08-17 17:51:35 -0700443/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800444void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700445{
446 int numReachableBlocks = cUnit->numReachableBlocks;
447 int numTotalBlocks = cUnit->blockList.numUsed;
448
449 /* Initialize domination-related data structures */
450 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
451 kReachableNodes,
452 false /* isIterative */);
453
buzbee5b537102012-01-17 17:33:47 -0800454 /* Initalize & Clear iDomList */
455 if (cUnit->iDomList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800456 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
457 false, kAllocDFInfo);
buzbee5b537102012-01-17 17:33:47 -0800458 }
459 for (int i = 0; i < numReachableBlocks; i++) {
460 cUnit->iDomList[i] = NOTVISITED;
461 }
462
463 /* For post-order, last block is entry block. Set its iDom to istelf */
464 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
465 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
466
467 /* Compute the immediate dominators */
468 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
469 kReversePostOrderTraversal,
470 true /* isIterative */);
471
buzbee67bf8852011-08-17 17:51:35 -0700472 /* Set the dominator for the root node */
473 oatClearAllBits(cUnit->entryBlock->dominators);
buzbeeba938cb2012-02-03 14:47:55 -0800474 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700475
476 if (cUnit->tempBlockV == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800477 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800478 false /* expandable */,
479 kBitMapTmpBlockV);
buzbee67bf8852011-08-17 17:51:35 -0700480 } else {
481 oatClearAllBits(cUnit->tempBlockV);
482 }
buzbee67bf8852011-08-17 17:51:35 -0700483 cUnit->entryBlock->iDom = NULL;
buzbee5b537102012-01-17 17:33:47 -0800484
485 /* For testing, compute sets using alternate mechanism */
486 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
487 // Use alternate mechanism to compute dominators for comparison
488 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
489 kPreOrderDFSTraversal,
490 true /* isIterative */);
491
492 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
493 kReachableNodes,
494 false /* isIterative */);
495 }
496
497 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
498 kReachableNodes,
499 false /* isIterative */);
500
501 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
502 kReversePostOrderTraversal,
503 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700504
505 /*
506 * Now go ahead and compute the post order traversal based on the
507 * iDominated sets.
508 */
509 if (cUnit->domPostOrderTraversal.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800510 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
511 numReachableBlocks, kListDomPostOrderTraversal);
buzbee67bf8852011-08-17 17:51:35 -0700512 } else {
513 cUnit->domPostOrderTraversal.numUsed = 0;
514 }
515
516 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700517 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700518 (unsigned) cUnit->numReachableBlocks);
519
520 /* Now compute the dominance frontier for each block */
521 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
522 kPostOrderDOMTraversal,
523 false /* isIterative */);
524}
525
526/*
527 * Perform dest U= src1 ^ ~src2
528 * This is probably not general enough to be placed in BitVector.[ch].
529 */
buzbee31a4a6f2012-02-28 15:36:15 -0800530void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700531 const ArenaBitVector* src1,
532 const ArenaBitVector* src2)
533{
534 if (dest->storageSize != src1->storageSize ||
535 dest->storageSize != src2->storageSize ||
536 dest->expandable != src1->expandable ||
537 dest->expandable != src2->expandable) {
538 LOG(FATAL) << "Incompatible set properties";
539 }
540
541 unsigned int idx;
542 for (idx = 0; idx < dest->storageSize; idx++) {
543 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
544 }
545}
546
547/*
548 * Iterate through all successor blocks and propagate up the live-in sets.
549 * The calculated result is used for phi-node pruning - where we only need to
550 * insert a phi node if the variable is live-in to the block.
551 */
buzbee31a4a6f2012-02-28 15:36:15 -0800552bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700553{
554 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
555
556 if (bb->dataFlowInfo == NULL) return false;
557 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
558 if (bb->taken && bb->taken->dataFlowInfo)
559 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
560 bb->dataFlowInfo->defV);
561 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
562 computeSuccLiveIn(tempDalvikRegisterV,
563 bb->fallThrough->dataFlowInfo->liveInV,
564 bb->dataFlowInfo->defV);
565 if (bb->successorBlockList.blockListType != kNotUsed) {
566 GrowableListIterator iterator;
567 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
568 &iterator);
569 while (true) {
570 SuccessorBlockInfo *successorBlockInfo =
571 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
572 if (successorBlockInfo == NULL) break;
573 BasicBlock* succBB = successorBlockInfo->block;
574 if (succBB->dataFlowInfo) {
575 computeSuccLiveIn(tempDalvikRegisterV,
576 succBB->dataFlowInfo->liveInV,
577 bb->dataFlowInfo->defV);
578 }
579 }
580 }
581 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
582 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
583 return true;
584 }
585 return false;
586}
587
588/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800589void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700590{
591 int dalvikReg;
592 const GrowableList* blockList = &cUnit->blockList;
593 ArenaBitVector* phiBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800594 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
buzbee67bf8852011-08-17 17:51:35 -0700595 ArenaBitVector* tmpBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800596 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700597 ArenaBitVector* inputBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800598 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700599
600 cUnit->tempDalvikRegisterV =
buzbeeba938cb2012-02-03 14:47:55 -0800601 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
buzbee5abfa3e2012-01-31 17:01:43 -0800602 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700603
604 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
605 kPostOrderDFSTraversal,
606 true /* isIterative */);
607
608 /* Iterate through each Dalvik register */
609 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
610 bool change;
611 ArenaBitVectorIterator iterator;
612
613 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
614 oatClearAllBits(phiBlocks);
615
616 /* Calculate the phi blocks for each Dalvik register */
617 do {
618 change = false;
619 oatClearAllBits(tmpBlocks);
620 oatBitVectorIteratorInit(inputBlocks, &iterator);
621
622 while (true) {
623 int idx = oatBitVectorIteratorNext(&iterator);
624 if (idx == -1) break;
625 BasicBlock* defBB =
626 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
627
628 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800629 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700630 if (defBB->domFrontier != NULL) {
631 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
632 }
buzbee67bf8852011-08-17 17:51:35 -0700633 }
634 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
635 change = true;
636 oatCopyBitVector(phiBlocks, tmpBlocks);
637
638 /*
639 * Iterate through the original blocks plus the new ones in
640 * the dominance frontier.
641 */
642 oatCopyBitVector(inputBlocks, phiBlocks);
643 oatUnifyBitVectors(inputBlocks, inputBlocks,
644 cUnit->defBlockMatrix[dalvikReg]);
645 }
646 } while (change);
647
648 /*
649 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
650 * register is in the live-in set.
651 */
652 oatBitVectorIteratorInit(phiBlocks, &iterator);
653 while (true) {
654 int idx = oatBitVectorIteratorNext(&iterator);
655 if (idx == -1) break;
656 BasicBlock* phiBB =
657 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
658 /* Variable will be clobbered before being used - no need for phi */
659 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
buzbeeba938cb2012-02-03 14:47:55 -0800660 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800661 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
buzbee67bf8852011-08-17 17:51:35 -0700662 phi->dalvikInsn.vA = dalvikReg;
663 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700664 phi->meta.phiNext = cUnit->phiList;
665 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700666 oatPrependMIR(phiBB, phi);
667 }
668 }
669}
670
671/*
672 * Worker function to insert phi-operands with latest SSA names from
673 * predecessor blocks
674 */
buzbee31a4a6f2012-02-28 15:36:15 -0800675bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700676{
677 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
buzbee5abfa3e2012-01-31 17:01:43 -0800678 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700679 MIR *mir;
680
681 /* Phi nodes are at the beginning of each block */
682 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800683 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
buzbee67bf8852011-08-17 17:51:35 -0700684 return true;
685 int ssaReg = mir->ssaRep->defs[0];
buzbeee1965672012-03-11 18:39:19 -0700686 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
687 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700688
689 oatClearAllBits(ssaRegV);
690
691 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800692 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700693 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800694 BasicBlock* predBB =
695 (BasicBlock*)oatGrowableListIteratorNext(&iter);
696 if (!predBB) break;
buzbeee1965672012-03-11 18:39:19 -0700697 int ssaReg =
698 predBB->dataFlowInfo->vRegToSSAMap[vReg];
buzbeeba938cb2012-02-03 14:47:55 -0800699 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700700 }
701
702 /* Count the number of SSA registers for a Dalvik register */
703 int numUses = oatCountSetBits(ssaRegV);
704 mir->ssaRep->numUses = numUses;
705 mir->ssaRep->uses =
buzbeeba938cb2012-02-03 14:47:55 -0800706 (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700707 mir->ssaRep->fpUse =
buzbeeba938cb2012-02-03 14:47:55 -0800708 (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700709
710 ArenaBitVectorIterator phiIterator;
711
712 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
713 int *usePtr = mir->ssaRep->uses;
714
715 /* Set the uses array for the phi node */
716 while (true) {
717 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
718 if (ssaRegIdx == -1) break;
719 *usePtr++ = ssaRegIdx;
720 }
721 }
722
723 return true;
724}
725
buzbee31a4a6f2012-02-28 15:36:15 -0800726void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700727{
728
729 if (block->visited || block->hidden) return;
730 block->visited = true;
731
732 /* Process this block */
733 oatDoSSAConversion(cUnit, block);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800734 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700735
736 /* Save SSA map snapshot */
buzbeeba938cb2012-02-03 14:47:55 -0800737 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
738 kAllocDalvikToSSAMap);
buzbeee1965672012-03-11 18:39:19 -0700739 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700740
741 if (block->fallThrough) {
742 doDFSPreOrderSSARename(cUnit, block->fallThrough);
743 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700744 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700745 }
746 if (block->taken) {
747 doDFSPreOrderSSARename(cUnit, block->taken);
748 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700749 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700750 }
751 if (block->successorBlockList.blockListType != kNotUsed) {
752 GrowableListIterator iterator;
753 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
754 &iterator);
755 while (true) {
756 SuccessorBlockInfo *successorBlockInfo =
757 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
758 if (successorBlockInfo == NULL) break;
759 BasicBlock* succBB = successorBlockInfo->block;
760 doDFSPreOrderSSARename(cUnit, succBB);
761 /* Restore SSA map snapshot */
buzbeee1965672012-03-11 18:39:19 -0700762 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700763 }
764 }
buzbeee1965672012-03-11 18:39:19 -0700765 cUnit->vRegToSSAMap = savedSSAMap;
buzbeef0cde542011-09-13 14:55:02 -0700766 return;
767}
768
buzbee67bf8852011-08-17 17:51:35 -0700769/* Perform SSA transformation for the whole method */
770void oatMethodSSATransformation(CompilationUnit* cUnit)
771{
772 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800773 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700774
buzbee99ba9642012-01-25 14:23:14 -0800775 if (!cUnit->disableDataflow) {
776 /* Compute the dominator info */
777 computeDominators(cUnit);
778 }
buzbee67bf8852011-08-17 17:51:35 -0700779
780 /* Allocate data structures in preparation for SSA conversion */
781 oatInitializeSSAConversion(cUnit);
782
buzbee99ba9642012-01-25 14:23:14 -0800783 if (!cUnit->disableDataflow) {
784 /* Find out the "Dalvik reg def x block" relation */
785 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700786
buzbee99ba9642012-01-25 14:23:14 -0800787 /* Insert phi nodes to dominance frontiers for all variables */
788 insertPhiNodes(cUnit);
789 }
buzbee67bf8852011-08-17 17:51:35 -0700790
791 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700792 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
793 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700794 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700795 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700796
buzbee99ba9642012-01-25 14:23:14 -0800797 if (!cUnit->disableDataflow) {
798 /*
799 * Shared temp bit vector used by each block to count the number of defs
800 * from all the predecessor blocks.
801 */
buzbeeba938cb2012-02-03 14:47:55 -0800802 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
803 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700804
buzbee99ba9642012-01-25 14:23:14 -0800805 /* Insert phi-operands with latest SSA names from predecessor blocks */
806 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
807 kReachableNodes,
808 false /* isIterative */);
809 }
buzbee67bf8852011-08-17 17:51:35 -0700810}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800811
812} // namespace art