blob: ada93517bdfa539fb95361712e8cccdb919d5ff1 [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
Bill Buzbeea114add2012-05-03 15:00:40 -070026 if (block->visited || block->hidden) return;
27 block->visited = true;
buzbee67bf8852011-08-17 17:51:35 -070028
Bill Buzbeea114add2012-05-03 15:00:40 -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;
buzbee3d661942012-03-14 17:37:27 -070038 }
Bill Buzbeea114add2012-05-03 15:00:40 -070039 }
buzbee3d661942012-03-14 17:37:27 -070040
Bill Buzbeea114add2012-05-03 15:00:40 -070041 /* Enqueue the preOrder block id */
42 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070043
Bill Buzbeea114add2012-05-03 15:00:40 -070044 if (block->fallThrough) {
45 recordDFSOrders(cUnit, block->fallThrough);
46 }
47 if (block->taken) recordDFSOrders(cUnit, block->taken);
48 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;
57 recordDFSOrders(cUnit, succBB);
buzbeee1965672012-03-11 18:39:19 -070058 }
Bill Buzbeea114add2012-05-03 15:00:40 -070059 }
buzbee5b537102012-01-17 17:33:47 -080060
Bill Buzbeea114add2012-05-03 15:00:40 -070061 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
62 block->dfsId = cUnit->dfsPostOrder.numUsed;
63 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
64 return;
buzbee67bf8852011-08-17 17:51:35 -070065}
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{
Bill Buzbeea114add2012-05-03 15:00:40 -070070 /* Initialize or reset the DFS preOrder list */
71 if (cUnit->dfsOrder.elemList == NULL) {
72 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
73 kListDfsOrder);
74 } else {
75 /* Just reset the used length on the counter */
76 cUnit->dfsOrder.numUsed = 0;
77 }
buzbee67bf8852011-08-17 17:51:35 -070078
Bill Buzbeea114add2012-05-03 15:00:40 -070079 /* Initialize or reset the DFS postOrder list */
80 if (cUnit->dfsPostOrder.elemList == NULL) {
81 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
82 kListDfsPostOrder);
83 } else {
84 /* Just reset the used length on the counter */
85 cUnit->dfsPostOrder.numUsed = 0;
86 }
buzbee5b537102012-01-17 17:33:47 -080087
Bill Buzbeea114add2012-05-03 15:00:40 -070088 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
89 kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -070090
Bill Buzbeea114add2012-05-03 15:00:40 -070091 recordDFSOrders(cUnit, cUnit->entryBlock);
92 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
buzbee67bf8852011-08-17 17:51:35 -070093}
94
95/*
96 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
97 * register idx is defined in BasicBlock bb.
98 */
buzbee31a4a6f2012-02-28 15:36:15 -080099bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700100{
Bill Buzbeea114add2012-05-03 15:00:40 -0700101 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -0700102
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700104
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
106 while (true) {
107 int idx = oatBitVectorIteratorNext(&iterator);
108 if (idx == -1) break;
109 /* Block bb defines register idx */
110 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
111 }
112 return true;
buzbee67bf8852011-08-17 17:51:35 -0700113}
114
buzbee31a4a6f2012-02-28 15:36:15 -0800115void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700116{
Bill Buzbeea114add2012-05-03 15:00:40 -0700117 int numRegisters = cUnit->numDalvikRegisters;
118 /* Allocate numDalvikRegisters bit vector pointers */
119 cUnit->defBlockMatrix = (ArenaBitVector **)
120 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
121 kAllocDFInfo);
122 int i;
buzbee67bf8852011-08-17 17:51:35 -0700123
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 /* Initialize numRegister vectors with numBlocks bits each */
125 for (i = 0; i < numRegisters; i++) {
126 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
127 false, kBitMapBMatrix);
128 }
129 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
130 kAllNodes, false /* isIterative */);
131 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
132 kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700133
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 /*
135 * Also set the incoming parameters as defs in the entry block.
136 * Only need to handle the parameters for the outer method.
137 */
138 int numRegs = cUnit->numDalvikRegisters;
139 int inReg = numRegs - cUnit->numIns;
140 for (; inReg < numRegs; inReg++) {
141 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
142 }
buzbee67bf8852011-08-17 17:51:35 -0700143}
144
145/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800146void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700147{
Bill Buzbeea114add2012-05-03 15:00:40 -0700148 ArenaBitVectorIterator bvIterator;
149 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
150 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700151
Bill Buzbeea114add2012-05-03 15:00:40 -0700152 /* Iterate through the dominated blocks first */
153 while (true) {
154 //TUNING: hot call to oatBitVectorIteratorNext
155 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
156 if (bbIdx == -1) break;
157 BasicBlock* dominatedBB =
158 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
159 computeDomPostOrderTraversal(cUnit, dominatedBB);
160 }
buzbee67bf8852011-08-17 17:51:35 -0700161
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 /* Enter the current block id */
163 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700164
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 /* hacky loop detection */
166 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
167 cUnit->hasLoop = true;
168 }
buzbee67bf8852011-08-17 17:51:35 -0700169}
170
buzbee31a4a6f2012-02-28 15:36:15 -0800171void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700173{
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 /*
175 * TODO - evaluate whether phi will ever need to be inserted into exit
176 * blocks.
177 */
178 if (succBB->iDom != domBB &&
179 succBB->blockType == kDalvikByteCode &&
180 succBB->hidden == false) {
181 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
182 }
buzbee67bf8852011-08-17 17:51:35 -0700183}
184
185/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800186bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700187{
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700189
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 /* Calculate DF_local */
191 if (bb->taken) {
192 checkForDominanceFrontier(cUnit, bb, bb->taken);
193 }
194 if (bb->fallThrough) {
195 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
196 }
197 if (bb->successorBlockList.blockListType != kNotUsed) {
198 GrowableListIterator iterator;
199 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
200 &iterator);
201 while (true) {
202 SuccessorBlockInfo *successorBlockInfo =
203 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
204 if (successorBlockInfo == NULL) break;
205 BasicBlock* succBB = successorBlockInfo->block;
206 checkForDominanceFrontier(cUnit, bb, succBB);
207 }
208 }
buzbee67bf8852011-08-17 17:51:35 -0700209
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 /* Calculate DF_up */
211 ArenaBitVectorIterator bvIterator;
212 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
213 while (true) {
214 //TUNING: hot call to oatBitVectorIteratorNext
215 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
216 if (dominatedIdx == -1) break;
217 BasicBlock* dominatedBB = (BasicBlock* )
218 oatGrowableListGetElement(blockList, dominatedIdx);
219 ArenaBitVectorIterator dfIterator;
220 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
buzbee67bf8852011-08-17 17:51:35 -0700221 while (true) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700222 //TUNING: hot call to oatBitVectorIteratorNext
223 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
224 if (dfUpIdx == -1) break;
225 BasicBlock* dfUpBlock = (BasicBlock* )
226 oatGrowableListGetElement(blockList, dfUpIdx);
227 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700228 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 }
buzbee67bf8852011-08-17 17:51:35 -0700230
Bill Buzbeea114add2012-05-03 15:00:40 -0700231 return true;
buzbee67bf8852011-08-17 17:51:35 -0700232}
233
234/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800235bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700236{
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700238
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 if (bb->dominators == NULL ) {
240 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
241 false /* expandable */,
242 kBitMapDominators);
243 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
244 false /* expandable */,
245 kBitMapIDominated);
246 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
247 false /* expandable */,
248 kBitMapDomFrontier);
249 } else {
250 oatClearAllBits(bb->dominators);
251 oatClearAllBits(bb->iDominated);
252 oatClearAllBits(bb->domFrontier);
253 }
254 /* Set all bits in the dominator vector */
255 oatSetInitialBits(bb->dominators, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700256
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 return true;
buzbee67bf8852011-08-17 17:51:35 -0700258}
259
buzbee5b537102012-01-17 17:33:47 -0800260/*
261 * Worker function to compute each block's dominators. This implementation
262 * is only used when kDebugVerifyDataflow is active and should compute
263 * the same dominator sets as computeBlockDominators.
264 */
buzbee31a4a6f2012-02-28 15:36:15 -0800265bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700266{
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 GrowableList* blockList = &cUnit->blockList;
268 int numTotalBlocks = blockList->numUsed;
269 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
270 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700271
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 /*
273 * The dominator of the entry block has been preset to itself and we need
274 * to skip the calculation here.
275 */
276 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700277
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 oatSetInitialBits(tempBlockV, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700279
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 /* Iterate through the predecessors */
281 oatGrowableListIteratorInit(bb->predecessors, &iter);
282 while (true) {
283 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
284 if (!predBB) break;
285 /* tempBlockV = tempBlockV ^ dominators */
286 if (predBB->dominators != NULL) {
287 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
buzbee67bf8852011-08-17 17:51:35 -0700288 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 }
290 oatSetBit(cUnit, tempBlockV, bb->id);
291 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
292 oatCopyBitVector(bb->dominators, tempBlockV);
293 return true;
294 }
295 return false;
buzbee67bf8852011-08-17 17:51:35 -0700296}
297
buzbee5b537102012-01-17 17:33:47 -0800298/*
299 * Worker function to compute the idom. This implementation is only
300 * used when kDebugVerifyDataflow is active and should compute the
301 * same iDom as computeBlockIDom.
302 */
buzbee31a4a6f2012-02-28 15:36:15 -0800303bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700304{
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 GrowableList* blockList = &cUnit->blockList;
306 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
307 ArenaBitVectorIterator bvIterator;
308 BasicBlock* iDom;
buzbee67bf8852011-08-17 17:51:35 -0700309
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700311
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 oatCopyBitVector(tempBlockV, bb->dominators);
313 oatClearBit(tempBlockV, bb->id);
314 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
buzbee67bf8852011-08-17 17:51:35 -0700315
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 /* Should not see any dead block */
317 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
318 if (oatCountSetBits(tempBlockV) == 1) {
319 iDom = (BasicBlock* )
320 oatGrowableListGetElement(blockList,
321 oatBitVectorIteratorNext(&bvIterator));
322 bb->iDom = iDom;
323 } else {
324 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
325 DCHECK_NE(iDomIdx, -1);
326 while (true) {
327 int nextDom = oatBitVectorIteratorNext(&bvIterator);
328 if (nextDom == -1) break;
329 BasicBlock* nextDomBB = (BasicBlock* )
330 oatGrowableListGetElement(blockList, nextDom);
331 /* iDom dominates nextDom - set new iDom */
332 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
333 iDomIdx = nextDom;
334 }
buzbee67bf8852011-08-17 17:51:35 -0700335
buzbee67bf8852011-08-17 17:51:35 -0700336 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
338 /* Set the immediate dominator block for bb */
339 bb->iDom = iDom;
340 }
341 /* Add bb to the iDominated set of the immediate dominator block */
342 oatSetBit(cUnit, iDom->iDominated, bb->id);
343 return true;
buzbee67bf8852011-08-17 17:51:35 -0700344}
345
buzbee5b537102012-01-17 17:33:47 -0800346/*
347 * Walk through the ordered iDom list until we reach common parent.
348 * Given the ordering of iDomList, this common parent represents the
349 * last element of the intersection of block1 and block2 dominators.
350 */
351int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
352{
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 while (block1 != block2) {
354 while (block1 < block2) {
355 block1 = cUnit->iDomList[block1];
356 DCHECK_NE(block1, NOTVISITED);
buzbee5b537102012-01-17 17:33:47 -0800357 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 while (block2 < block1) {
359 block2 = cUnit->iDomList[block2];
360 DCHECK_NE(block2, NOTVISITED);
361 }
362 }
363 return block1;
buzbee5b537102012-01-17 17:33:47 -0800364}
365
366/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800367bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800368{
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 GrowableListIterator iter;
370 int idom = -1;
buzbee5b537102012-01-17 17:33:47 -0800371
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 /* Special-case entry block */
373 if (bb == cUnit->entryBlock) {
buzbee5b537102012-01-17 17:33:47 -0800374 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 }
376
377 /* Iterate through the predecessors */
378 oatGrowableListIteratorInit(bb->predecessors, &iter);
379
380 /* Find the first processed predecessor */
381 while (true) {
382 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
383 CHECK(predBB != NULL);
384 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
385 idom = predBB->dfsId;
386 break;
387 }
388 }
389
390 /* Scan the rest of the predecessors */
391 while (true) {
392 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
393 if (!predBB) break;
394 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
395 continue;
396 } else {
397 idom = findCommonParent(cUnit, predBB->dfsId, idom);
398 }
399 }
400
401 DCHECK_NE(idom, NOTVISITED);
402
403 /* Did something change? */
404 if (cUnit->iDomList[bb->dfsId] != idom) {
405 cUnit->iDomList[bb->dfsId] = idom;
406 return true;
407 }
408 return false;
buzbee5b537102012-01-17 17:33:47 -0800409}
410
411/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800412bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800413{
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 if (bb == cUnit->entryBlock) {
415 oatClearAllBits(bb->dominators);
416 } else {
417 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
418 }
419 oatSetBit(cUnit, bb->dominators, bb->id);
420 return false;
buzbee5b537102012-01-17 17:33:47 -0800421}
422
buzbee31a4a6f2012-02-28 15:36:15 -0800423bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800424{
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 if (bb != cUnit->entryBlock) {
426 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
427 DCHECK_NE(iDomDFSIdx, NOTVISITED);
428 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
429 BasicBlock* iDom = (BasicBlock*)
430 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
431 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
432 DCHECK_EQ(bb->iDom->id, iDom->id);
buzbee5b537102012-01-17 17:33:47 -0800433 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 bb->iDom = iDom;
435 /* Add bb to the iDominated set of the immediate dominator block */
436 oatSetBit(cUnit, iDom->iDominated, bb->id);
437 }
438 return false;
buzbee5b537102012-01-17 17:33:47 -0800439}
440
buzbee67bf8852011-08-17 17:51:35 -0700441/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800442void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700443{
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 int numReachableBlocks = cUnit->numReachableBlocks;
445 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700446
Bill Buzbeea114add2012-05-03 15:00:40 -0700447 /* Initialize domination-related data structures */
448 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
449 kReachableNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700450
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 /* Initalize & Clear iDomList */
452 if (cUnit->iDomList == NULL) {
453 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
454 false, kAllocDFInfo);
455 }
456 for (int i = 0; i < numReachableBlocks; i++) {
457 cUnit->iDomList[i] = NOTVISITED;
458 }
buzbee5b537102012-01-17 17:33:47 -0800459
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 /* For post-order, last block is entry block. Set its iDom to istelf */
461 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
462 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
buzbee5b537102012-01-17 17:33:47 -0800463
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 /* Compute the immediate dominators */
465 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
466 kReversePostOrderTraversal,
467 true /* isIterative */);
468
469 /* Set the dominator for the root node */
470 oatClearAllBits(cUnit->entryBlock->dominators);
471 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
472
473 if (cUnit->tempBlockV == NULL) {
474 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
475 false /* expandable */,
476 kBitMapTmpBlockV);
477 } else {
478 oatClearAllBits(cUnit->tempBlockV);
479 }
480 cUnit->entryBlock->iDom = NULL;
481
482 /* For testing, compute sets using alternate mechanism */
483 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
484 // Use alternate mechanism to compute dominators for comparison
485 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
486 kPreOrderDFSTraversal,
buzbee5b537102012-01-17 17:33:47 -0800487 true /* isIterative */);
488
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
490 kReachableNodes,
491 false /* isIterative */);
492 }
buzbee67bf8852011-08-17 17:51:35 -0700493
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
495 kReachableNodes,
496 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800497
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
499 kReversePostOrderTraversal,
500 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800501
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 /*
503 * Now go ahead and compute the post order traversal based on the
504 * iDominated sets.
505 */
506 if (cUnit->domPostOrderTraversal.elemList == NULL) {
507 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
508 numReachableBlocks, kListDomPostOrderTraversal);
509 } else {
510 cUnit->domPostOrderTraversal.numUsed = 0;
511 }
buzbee5b537102012-01-17 17:33:47 -0800512
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
514 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
515 (unsigned) cUnit->numReachableBlocks);
buzbee5b537102012-01-17 17:33:47 -0800516
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 /* Now compute the dominance frontier for each block */
518 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
519 kPostOrderDOMTraversal,
520 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700521}
522
523/*
524 * Perform dest U= src1 ^ ~src2
525 * This is probably not general enough to be placed in BitVector.[ch].
526 */
buzbee31a4a6f2012-02-28 15:36:15 -0800527void computeSuccLiveIn(ArenaBitVector* dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 const ArenaBitVector* src1,
529 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700530{
Bill Buzbeea114add2012-05-03 15:00:40 -0700531 if (dest->storageSize != src1->storageSize ||
532 dest->storageSize != src2->storageSize ||
533 dest->expandable != src1->expandable ||
534 dest->expandable != src2->expandable) {
535 LOG(FATAL) << "Incompatible set properties";
536 }
buzbee67bf8852011-08-17 17:51:35 -0700537
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 unsigned int idx;
539 for (idx = 0; idx < dest->storageSize; idx++) {
540 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
541 }
buzbee67bf8852011-08-17 17:51:35 -0700542}
543
544/*
545 * Iterate through all successor blocks and propagate up the live-in sets.
546 * The calculated result is used for phi-node pruning - where we only need to
547 * insert a phi node if the variable is live-in to the block.
548 */
buzbee31a4a6f2012-02-28 15:36:15 -0800549bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700550{
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
buzbee67bf8852011-08-17 17:51:35 -0700552
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 if (bb->dataFlowInfo == NULL) return false;
554 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
555 if (bb->taken && bb->taken->dataFlowInfo)
556 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
557 bb->dataFlowInfo->defV);
558 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
559 computeSuccLiveIn(tempDalvikRegisterV,
560 bb->fallThrough->dataFlowInfo->liveInV,
561 bb->dataFlowInfo->defV);
562 if (bb->successorBlockList.blockListType != kNotUsed) {
563 GrowableListIterator iterator;
564 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
565 &iterator);
566 while (true) {
567 SuccessorBlockInfo *successorBlockInfo =
568 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
569 if (successorBlockInfo == NULL) break;
570 BasicBlock* succBB = successorBlockInfo->block;
571 if (succBB->dataFlowInfo) {
buzbee67bf8852011-08-17 17:51:35 -0700572 computeSuccLiveIn(tempDalvikRegisterV,
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 succBB->dataFlowInfo->liveInV,
buzbee67bf8852011-08-17 17:51:35 -0700574 bb->dataFlowInfo->defV);
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 }
buzbee67bf8852011-08-17 17:51:35 -0700576 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 }
578 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
579 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
580 return true;
581 }
582 return false;
buzbee67bf8852011-08-17 17:51:35 -0700583}
584
585/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800586void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700587{
Bill Buzbeea114add2012-05-03 15:00:40 -0700588 int dalvikReg;
589 const GrowableList* blockList = &cUnit->blockList;
590 ArenaBitVector* phiBlocks =
591 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
592 ArenaBitVector* tmpBlocks =
593 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
594 ArenaBitVector* inputBlocks =
595 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700596
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 cUnit->tempDalvikRegisterV =
598 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
599 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700600
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
602 kPostOrderDFSTraversal, true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700603
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 /* Iterate through each Dalvik register */
605 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
606 bool change;
607 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700608
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
610 oatClearAllBits(phiBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700611
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 /* Calculate the phi blocks for each Dalvik register */
613 do {
614 change = false;
615 oatClearAllBits(tmpBlocks);
616 oatBitVectorIteratorInit(inputBlocks, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700617
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 while (true) {
619 int idx = oatBitVectorIteratorNext(&iterator);
620 if (idx == -1) break;
621 BasicBlock* defBB =
622 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
buzbee67bf8852011-08-17 17:51:35 -0700623
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 /* Merge the dominance frontier to tmpBlocks */
625 //TUNING: hot call to oatUnifyBitVectors
626 if (defBB->domFrontier != NULL) {
627 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
628 }
buzbee67bf8852011-08-17 17:51:35 -0700629 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
631 change = true;
632 oatCopyBitVector(phiBlocks, tmpBlocks);
633
634 /*
635 * Iterate through the original blocks plus the new ones in
636 * the dominance frontier.
637 */
638 oatCopyBitVector(inputBlocks, phiBlocks);
639 oatUnifyBitVectors(inputBlocks, inputBlocks,
640 cUnit->defBlockMatrix[dalvikReg]);
641 }
642 } while (change);
643
644 /*
645 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
646 * register is in the live-in set.
647 */
648 oatBitVectorIteratorInit(phiBlocks, &iterator);
649 while (true) {
650 int idx = oatBitVectorIteratorNext(&iterator);
651 if (idx == -1) break;
652 BasicBlock* phiBB =
653 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
654 /* Variable will be clobbered before being used - no need for phi */
655 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
656 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
657 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
658 phi->dalvikInsn.vA = dalvikReg;
659 phi->offset = phiBB->startOffset;
660 phi->meta.phiNext = cUnit->phiList;
661 cUnit->phiList = phi;
662 oatPrependMIR(phiBB, phi);
buzbee67bf8852011-08-17 17:51:35 -0700663 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700664 }
buzbee67bf8852011-08-17 17:51:35 -0700665}
666
667/*
668 * Worker function to insert phi-operands with latest SSA names from
669 * predecessor blocks
670 */
buzbee31a4a6f2012-02-28 15:36:15 -0800671bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700672{
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
674 GrowableListIterator iter;
675 MIR *mir;
buzbee67bf8852011-08-17 17:51:35 -0700676
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 /* Phi nodes are at the beginning of each block */
678 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
679 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
680 return true;
681 int ssaReg = mir->ssaRep->defs[0];
682 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
683 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700684
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 oatClearAllBits(ssaRegV);
buzbee67bf8852011-08-17 17:51:35 -0700686
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 /* Iterate through the predecessors */
688 oatGrowableListIteratorInit(bb->predecessors, &iter);
689 while (true) {
690 BasicBlock* predBB =
691 (BasicBlock*)oatGrowableListIteratorNext(&iter);
692 if (!predBB) break;
693 int ssaReg = predBB->dataFlowInfo->vRegToSSAMap[vReg];
694 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700695 }
696
Bill Buzbeea114add2012-05-03 15:00:40 -0700697 /* Count the number of SSA registers for a Dalvik register */
698 int numUses = oatCountSetBits(ssaRegV);
699 mir->ssaRep->numUses = numUses;
700 mir->ssaRep->uses =
701 (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
702 mir->ssaRep->fpUse =
703 (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
704
705 ArenaBitVectorIterator phiIterator;
706
707 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
708 int *usePtr = mir->ssaRep->uses;
709
710 /* Set the uses array for the phi node */
711 while (true) {
712 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
713 if (ssaRegIdx == -1) break;
714 *usePtr++ = ssaRegIdx;
715 }
716 }
717
718 return true;
buzbee67bf8852011-08-17 17:51:35 -0700719}
720
buzbee31a4a6f2012-02-28 15:36:15 -0800721void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700722{
723
Bill Buzbeea114add2012-05-03 15:00:40 -0700724 if (block->visited || block->hidden) return;
725 block->visited = true;
buzbeef0cde542011-09-13 14:55:02 -0700726
Bill Buzbeea114add2012-05-03 15:00:40 -0700727 /* Process this block */
728 oatDoSSAConversion(cUnit, block);
729 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700730
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 /* Save SSA map snapshot */
732 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
733 kAllocDalvikToSSAMap);
734 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700735
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 if (block->fallThrough) {
737 doDFSPreOrderSSARename(cUnit, block->fallThrough);
738 /* Restore SSA map snapshot */
739 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
740 }
741 if (block->taken) {
742 doDFSPreOrderSSARename(cUnit, block->taken);
743 /* Restore SSA map snapshot */
744 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
745 }
746 if (block->successorBlockList.blockListType != kNotUsed) {
747 GrowableListIterator iterator;
748 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
749 &iterator);
750 while (true) {
751 SuccessorBlockInfo *successorBlockInfo =
752 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
753 if (successorBlockInfo == NULL) break;
754 BasicBlock* succBB = successorBlockInfo->block;
755 doDFSPreOrderSSARename(cUnit, succBB);
756 /* Restore SSA map snapshot */
757 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700758 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700759 }
760 cUnit->vRegToSSAMap = savedSSAMap;
761 return;
buzbeef0cde542011-09-13 14:55:02 -0700762}
763
buzbee67bf8852011-08-17 17:51:35 -0700764/* Perform SSA transformation for the whole method */
765void oatMethodSSATransformation(CompilationUnit* cUnit)
766{
Bill Buzbeea114add2012-05-03 15:00:40 -0700767 /* Compute the DFS order */
768 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700769
Bill Buzbeea114add2012-05-03 15:00:40 -0700770 if (!cUnit->disableDataflow) {
771 /* Compute the dominator info */
772 computeDominators(cUnit);
773 }
buzbee67bf8852011-08-17 17:51:35 -0700774
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 /* Allocate data structures in preparation for SSA conversion */
776 oatInitializeSSAConversion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700777
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 if (!cUnit->disableDataflow) {
779 /* Find out the "Dalvik reg def x block" relation */
780 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700781
Bill Buzbeea114add2012-05-03 15:00:40 -0700782 /* Insert phi nodes to dominance frontiers for all variables */
783 insertPhiNodes(cUnit);
784 }
buzbee67bf8852011-08-17 17:51:35 -0700785
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 /* Rename register names by local defs and phi nodes */
787 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
788 kAllNodes, false /* isIterative */);
789 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700790
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 if (!cUnit->disableDataflow) {
792 /*
793 * Shared temp bit vector used by each block to count the number of defs
794 * from all the predecessor blocks.
795 */
796 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
797 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700798
Bill Buzbeea114add2012-05-03 15:00:40 -0700799 /* Insert phi-operands with latest SSA names from predecessor blocks */
800 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
801 kReachableNodes, false /* isIterative */);
802 }
buzbee67bf8852011-08-17 17:51:35 -0700803}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800804
805} // namespace art