blob: cdb711e44ba32652a4adcb0102a12abdf10acdf8 [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
buzbee5b537102012-01-17 17:33:47 -080032 if (block->fallThrough) recordDFSOrders(cUnit, block->fallThrough);
33 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070034 if (block->successorBlockList.blockListType != kNotUsed) {
35 GrowableListIterator iterator;
36 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
37 &iterator);
38 while (true) {
39 SuccessorBlockInfo *successorBlockInfo =
40 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
41 if (successorBlockInfo == NULL) break;
42 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080043 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070044 }
45 }
buzbee5b537102012-01-17 17:33:47 -080046
47 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
48 block->dfsId = cUnit->dfsPostOrder.numUsed;
buzbeeba938cb2012-02-03 14:47:55 -080049 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070050 return;
51}
52
buzbee5b537102012-01-17 17:33:47 -080053/* Sort the blocks by the Depth-First-Search */
buzbee31a4a6f2012-02-28 15:36:15 -080054void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070055{
buzbee5b537102012-01-17 17:33:47 -080056 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070057 if (cUnit->dfsOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080058 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
59 kListDfsOrder);
buzbee67bf8852011-08-17 17:51:35 -070060 } else {
61 /* Just reset the used length on the counter */
62 cUnit->dfsOrder.numUsed = 0;
63 }
64
buzbee5b537102012-01-17 17:33:47 -080065 /* Initialize or reset the DFS postOrder list */
66 if (cUnit->dfsPostOrder.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -080067 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -080068 kListDfsPostOrder);
buzbee5b537102012-01-17 17:33:47 -080069 } else {
70 /* Just reset the used length on the counter */
71 cUnit->dfsPostOrder.numUsed = 0;
72 }
73
buzbee67bf8852011-08-17 17:51:35 -070074 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
75 kAllNodes,
76 false /* isIterative */);
77
buzbee5b537102012-01-17 17:33:47 -080078 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070079 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
80}
81
82/*
83 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
84 * register idx is defined in BasicBlock bb.
85 */
buzbee31a4a6f2012-02-28 15:36:15 -080086bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070087{
88 if (bb->dataFlowInfo == NULL) return false;
89
90 ArenaBitVectorIterator iterator;
91
92 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
93 while (true) {
94 int idx = oatBitVectorIteratorNext(&iterator);
95 if (idx == -1) break;
96 /* Block bb defines register idx */
buzbeeba938cb2012-02-03 14:47:55 -080097 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
buzbee67bf8852011-08-17 17:51:35 -070098 }
99 return true;
100}
101
buzbee31a4a6f2012-02-28 15:36:15 -0800102void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700103{
104 int numRegisters = cUnit->numDalvikRegisters;
105 /* Allocate numDalvikRegisters bit vector pointers */
106 cUnit->defBlockMatrix = (ArenaBitVector **)
buzbeeba938cb2012-02-03 14:47:55 -0800107 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
buzbee5abfa3e2012-01-31 17:01:43 -0800108 kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700109 int i;
110
111 /* Initialize numRegister vectors with numBlocks bits each */
112 for (i = 0; i < numRegisters; i++) {
buzbeeba938cb2012-02-03 14:47:55 -0800113 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
114 false, kBitMapBMatrix);
buzbee67bf8852011-08-17 17:51:35 -0700115 }
116 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
117 kAllNodes,
118 false /* isIterative */);
119 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
120 kAllNodes,
121 false /* isIterative */);
122
123 /*
124 * Also set the incoming parameters as defs in the entry block.
125 * Only need to handle the parameters for the outer method.
126 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800127 int numRegs = cUnit->numDalvikRegisters;
128 int inReg = numRegs - cUnit->numIns;
129 for (; inReg < numRegs; inReg++) {
buzbeeba938cb2012-02-03 14:47:55 -0800130 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700131 }
132}
133
134/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800135void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700136{
137 ArenaBitVectorIterator bvIterator;
138 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
139 GrowableList* blockList = &cUnit->blockList;
140
141 /* Iterate through the dominated blocks first */
142 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800143 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700144 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
145 if (bbIdx == -1) break;
146 BasicBlock* dominatedBB =
147 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
148 computeDomPostOrderTraversal(cUnit, dominatedBB);
149 }
150
151 /* Enter the current block id */
buzbeeba938cb2012-02-03 14:47:55 -0800152 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700153
154 /* hacky loop detection */
155 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
156 cUnit->hasLoop = true;
157 }
158}
159
buzbee31a4a6f2012-02-28 15:36:15 -0800160void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
161 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700162{
163 /*
164 * TODO - evaluate whether phi will ever need to be inserted into exit
165 * blocks.
166 */
167 if (succBB->iDom != domBB &&
168 succBB->blockType == kDalvikByteCode &&
169 succBB->hidden == false) {
buzbeeba938cb2012-02-03 14:47:55 -0800170 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700171 }
172}
173
174/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800175bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700176{
177 GrowableList* blockList = &cUnit->blockList;
178
179 /* Calculate DF_local */
180 if (bb->taken) {
buzbeeba938cb2012-02-03 14:47:55 -0800181 checkForDominanceFrontier(cUnit, bb, bb->taken);
buzbee67bf8852011-08-17 17:51:35 -0700182 }
183 if (bb->fallThrough) {
buzbeeba938cb2012-02-03 14:47:55 -0800184 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
buzbee67bf8852011-08-17 17:51:35 -0700185 }
186 if (bb->successorBlockList.blockListType != kNotUsed) {
187 GrowableListIterator iterator;
188 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
189 &iterator);
190 while (true) {
191 SuccessorBlockInfo *successorBlockInfo =
192 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
193 if (successorBlockInfo == NULL) break;
194 BasicBlock* succBB = successorBlockInfo->block;
buzbeeba938cb2012-02-03 14:47:55 -0800195 checkForDominanceFrontier(cUnit, bb, succBB);
buzbee67bf8852011-08-17 17:51:35 -0700196 }
197 }
198
199 /* Calculate DF_up */
200 ArenaBitVectorIterator bvIterator;
201 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
202 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800203 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700204 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
205 if (dominatedIdx == -1) break;
206 BasicBlock* dominatedBB = (BasicBlock* )
207 oatGrowableListGetElement(blockList, dominatedIdx);
208 ArenaBitVectorIterator dfIterator;
209 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
210 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800211 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700212 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
213 if (dfUpIdx == -1) break;
214 BasicBlock* dfUpBlock = (BasicBlock* )
215 oatGrowableListGetElement(blockList, dfUpIdx);
buzbeeba938cb2012-02-03 14:47:55 -0800216 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700217 }
218 }
219
220 return true;
221}
222
223/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800224bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700225{
226 int numTotalBlocks = cUnit->blockList.numUsed;
227
228 if (bb->dominators == NULL ) {
buzbeeba938cb2012-02-03 14:47:55 -0800229 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800230 false /* expandable */,
231 kBitMapDominators);
buzbeeba938cb2012-02-03 14:47:55 -0800232 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800233 false /* expandable */,
234 kBitMapIDominated);
buzbeeba938cb2012-02-03 14:47:55 -0800235 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800236 false /* expandable */,
237 kBitMapDomFrontier);
buzbee67bf8852011-08-17 17:51:35 -0700238 } else {
239 oatClearAllBits(bb->dominators);
240 oatClearAllBits(bb->iDominated);
241 oatClearAllBits(bb->domFrontier);
242 }
243 /* Set all bits in the dominator vector */
244 oatSetInitialBits(bb->dominators, numTotalBlocks);
245
246 return true;
247}
248
buzbee5b537102012-01-17 17:33:47 -0800249/*
250 * Worker function to compute each block's dominators. This implementation
251 * is only used when kDebugVerifyDataflow is active and should compute
252 * the same dominator sets as computeBlockDominators.
253 */
buzbee31a4a6f2012-02-28 15:36:15 -0800254bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700255{
256 GrowableList* blockList = &cUnit->blockList;
257 int numTotalBlocks = blockList->numUsed;
258 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
buzbee5abfa3e2012-01-31 17:01:43 -0800259 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700260
261 /*
262 * The dominator of the entry block has been preset to itself and we need
263 * to skip the calculation here.
264 */
265 if (bb == cUnit->entryBlock) return false;
266
267 oatSetInitialBits(tempBlockV, numTotalBlocks);
268
269 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800270 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700271 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800272 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
273 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700274 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700275 if (predBB->dominators != NULL) {
276 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
277 }
buzbee67bf8852011-08-17 17:51:35 -0700278 }
buzbeeba938cb2012-02-03 14:47:55 -0800279 oatSetBit(cUnit, tempBlockV, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700280 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
281 oatCopyBitVector(bb->dominators, tempBlockV);
282 return true;
283 }
284 return false;
285}
286
buzbee5b537102012-01-17 17:33:47 -0800287/*
288 * Worker function to compute the idom. This implementation is only
289 * used when kDebugVerifyDataflow is active and should compute the
290 * same iDom as computeBlockIDom.
291 */
buzbee31a4a6f2012-02-28 15:36:15 -0800292bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700293{
294 GrowableList* blockList = &cUnit->blockList;
295 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
296 ArenaBitVectorIterator bvIterator;
297 BasicBlock* iDom;
298
299 if (bb == cUnit->entryBlock) return false;
300
301 oatCopyBitVector(tempBlockV, bb->dominators);
302 oatClearBit(tempBlockV, bb->id);
303 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
304
305 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700306 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700307 if (oatCountSetBits(tempBlockV) == 1) {
308 iDom = (BasicBlock* ) oatGrowableListGetElement(
309 blockList, oatBitVectorIteratorNext(&bvIterator));
310 bb->iDom = iDom;
311 } else {
312 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700313 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700314 while (true) {
315 int nextDom = oatBitVectorIteratorNext(&bvIterator);
316 if (nextDom == -1) break;
317 BasicBlock* nextDomBB = (BasicBlock* )
318 oatGrowableListGetElement(blockList, nextDom);
319 /* iDom dominates nextDom - set new iDom */
320 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
321 iDomIdx = nextDom;
322 }
323
324 }
325 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
326 /* Set the immediate dominator block for bb */
327 bb->iDom = iDom;
328 }
329 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800330 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700331 return true;
332}
333
buzbee5b537102012-01-17 17:33:47 -0800334/*
335 * Walk through the ordered iDom list until we reach common parent.
336 * Given the ordering of iDomList, this common parent represents the
337 * last element of the intersection of block1 and block2 dominators.
338 */
339int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
340{
341 while (block1 != block2) {
342 while (block1 < block2) {
343 block1 = cUnit->iDomList[block1];
344 DCHECK_NE(block1, NOTVISITED);
345 }
346 while (block2 < block1) {
347 block2 = cUnit->iDomList[block2];
348 DCHECK_NE(block2, NOTVISITED);
349 }
350 }
351 return block1;
352}
353
354/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800355bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800356{
buzbee5abfa3e2012-01-31 17:01:43 -0800357 GrowableListIterator iter;
buzbee5b537102012-01-17 17:33:47 -0800358 int idom = -1;
359
360 /* Special-case entry block */
361 if (bb == cUnit->entryBlock) {
362 return false;
363 }
364
365 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800366 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee5b537102012-01-17 17:33:47 -0800367
368 /* Find the first processed predecessor */
369 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800370 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
371 CHECK(predBB != NULL);
buzbee5b537102012-01-17 17:33:47 -0800372 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
373 idom = predBB->dfsId;
374 break;
375 }
376 }
377
378 /* Scan the rest of the predecessors */
379 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800380 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
381 if (!predBB) break;
buzbee5b537102012-01-17 17:33:47 -0800382 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
383 continue;
384 } else {
385 idom = findCommonParent(cUnit, predBB->dfsId, idom);
386 }
387 }
388
389 DCHECK_NE(idom, NOTVISITED);
390
391 /* Did something change? */
392 if (cUnit->iDomList[bb->dfsId] != idom) {
393 cUnit->iDomList[bb->dfsId] = idom;
394 return true;
395 }
396 return false;
397}
398
399/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800400bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800401{
402 if (bb == cUnit->entryBlock) {
403 oatClearAllBits(bb->dominators);
404 } else {
405 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
406 }
buzbeeba938cb2012-02-03 14:47:55 -0800407 oatSetBit(cUnit, bb->dominators, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800408 return false;
409}
410
buzbee31a4a6f2012-02-28 15:36:15 -0800411bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800412{
413 if (bb != cUnit->entryBlock) {
414 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
415 DCHECK_NE(iDomDFSIdx, NOTVISITED);
416 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
417 BasicBlock* iDom = (BasicBlock*)
418 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
419 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
420 DCHECK_EQ(bb->iDom->id, iDom->id);
421 }
422 bb->iDom = iDom;
423 /* Add bb to the iDominated set of the immediate dominator block */
buzbeeba938cb2012-02-03 14:47:55 -0800424 oatSetBit(cUnit, iDom->iDominated, bb->id);
buzbee5b537102012-01-17 17:33:47 -0800425 }
426 return false;
427}
428
buzbee67bf8852011-08-17 17:51:35 -0700429/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800430void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700431{
432 int numReachableBlocks = cUnit->numReachableBlocks;
433 int numTotalBlocks = cUnit->blockList.numUsed;
434
435 /* Initialize domination-related data structures */
436 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
437 kReachableNodes,
438 false /* isIterative */);
439
buzbee5b537102012-01-17 17:33:47 -0800440 /* Initalize & Clear iDomList */
441 if (cUnit->iDomList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800442 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
443 false, kAllocDFInfo);
buzbee5b537102012-01-17 17:33:47 -0800444 }
445 for (int i = 0; i < numReachableBlocks; i++) {
446 cUnit->iDomList[i] = NOTVISITED;
447 }
448
449 /* For post-order, last block is entry block. Set its iDom to istelf */
450 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
451 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
452
453 /* Compute the immediate dominators */
454 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
455 kReversePostOrderTraversal,
456 true /* isIterative */);
457
buzbee67bf8852011-08-17 17:51:35 -0700458 /* Set the dominator for the root node */
459 oatClearAllBits(cUnit->entryBlock->dominators);
buzbeeba938cb2012-02-03 14:47:55 -0800460 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700461
462 if (cUnit->tempBlockV == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800463 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
buzbee5abfa3e2012-01-31 17:01:43 -0800464 false /* expandable */,
465 kBitMapTmpBlockV);
buzbee67bf8852011-08-17 17:51:35 -0700466 } else {
467 oatClearAllBits(cUnit->tempBlockV);
468 }
buzbee67bf8852011-08-17 17:51:35 -0700469 cUnit->entryBlock->iDom = NULL;
buzbee5b537102012-01-17 17:33:47 -0800470
471 /* For testing, compute sets using alternate mechanism */
472 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
473 // Use alternate mechanism to compute dominators for comparison
474 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
475 kPreOrderDFSTraversal,
476 true /* isIterative */);
477
478 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
479 kReachableNodes,
480 false /* isIterative */);
481 }
482
483 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
484 kReachableNodes,
485 false /* isIterative */);
486
487 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
488 kReversePostOrderTraversal,
489 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700490
491 /*
492 * Now go ahead and compute the post order traversal based on the
493 * iDominated sets.
494 */
495 if (cUnit->domPostOrderTraversal.elemList == NULL) {
buzbeeba938cb2012-02-03 14:47:55 -0800496 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
497 numReachableBlocks, kListDomPostOrderTraversal);
buzbee67bf8852011-08-17 17:51:35 -0700498 } else {
499 cUnit->domPostOrderTraversal.numUsed = 0;
500 }
501
502 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700503 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700504 (unsigned) cUnit->numReachableBlocks);
505
506 /* Now compute the dominance frontier for each block */
507 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
508 kPostOrderDOMTraversal,
509 false /* isIterative */);
510}
511
512/*
513 * Perform dest U= src1 ^ ~src2
514 * This is probably not general enough to be placed in BitVector.[ch].
515 */
buzbee31a4a6f2012-02-28 15:36:15 -0800516void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700517 const ArenaBitVector* src1,
518 const ArenaBitVector* src2)
519{
520 if (dest->storageSize != src1->storageSize ||
521 dest->storageSize != src2->storageSize ||
522 dest->expandable != src1->expandable ||
523 dest->expandable != src2->expandable) {
524 LOG(FATAL) << "Incompatible set properties";
525 }
526
527 unsigned int idx;
528 for (idx = 0; idx < dest->storageSize; idx++) {
529 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
530 }
531}
532
533/*
534 * Iterate through all successor blocks and propagate up the live-in sets.
535 * The calculated result is used for phi-node pruning - where we only need to
536 * insert a phi node if the variable is live-in to the block.
537 */
buzbee31a4a6f2012-02-28 15:36:15 -0800538bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700539{
540 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
541
542 if (bb->dataFlowInfo == NULL) return false;
543 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
544 if (bb->taken && bb->taken->dataFlowInfo)
545 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
546 bb->dataFlowInfo->defV);
547 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
548 computeSuccLiveIn(tempDalvikRegisterV,
549 bb->fallThrough->dataFlowInfo->liveInV,
550 bb->dataFlowInfo->defV);
551 if (bb->successorBlockList.blockListType != kNotUsed) {
552 GrowableListIterator iterator;
553 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
554 &iterator);
555 while (true) {
556 SuccessorBlockInfo *successorBlockInfo =
557 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
558 if (successorBlockInfo == NULL) break;
559 BasicBlock* succBB = successorBlockInfo->block;
560 if (succBB->dataFlowInfo) {
561 computeSuccLiveIn(tempDalvikRegisterV,
562 succBB->dataFlowInfo->liveInV,
563 bb->dataFlowInfo->defV);
564 }
565 }
566 }
567 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
568 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
569 return true;
570 }
571 return false;
572}
573
574/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800575void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700576{
577 int dalvikReg;
578 const GrowableList* blockList = &cUnit->blockList;
579 ArenaBitVector* phiBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800580 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
buzbee67bf8852011-08-17 17:51:35 -0700581 ArenaBitVector* tmpBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800582 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700583 ArenaBitVector* inputBlocks =
buzbeeba938cb2012-02-03 14:47:55 -0800584 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700585
586 cUnit->tempDalvikRegisterV =
buzbeeba938cb2012-02-03 14:47:55 -0800587 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
buzbee5abfa3e2012-01-31 17:01:43 -0800588 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700589
590 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
591 kPostOrderDFSTraversal,
592 true /* isIterative */);
593
594 /* Iterate through each Dalvik register */
595 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
596 bool change;
597 ArenaBitVectorIterator iterator;
598
599 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
600 oatClearAllBits(phiBlocks);
601
602 /* Calculate the phi blocks for each Dalvik register */
603 do {
604 change = false;
605 oatClearAllBits(tmpBlocks);
606 oatBitVectorIteratorInit(inputBlocks, &iterator);
607
608 while (true) {
609 int idx = oatBitVectorIteratorNext(&iterator);
610 if (idx == -1) break;
611 BasicBlock* defBB =
612 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
613
614 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800615 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700616 if (defBB->domFrontier != NULL) {
617 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
618 }
buzbee67bf8852011-08-17 17:51:35 -0700619 }
620 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
621 change = true;
622 oatCopyBitVector(phiBlocks, tmpBlocks);
623
624 /*
625 * Iterate through the original blocks plus the new ones in
626 * the dominance frontier.
627 */
628 oatCopyBitVector(inputBlocks, phiBlocks);
629 oatUnifyBitVectors(inputBlocks, inputBlocks,
630 cUnit->defBlockMatrix[dalvikReg]);
631 }
632 } while (change);
633
634 /*
635 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
636 * register is in the live-in set.
637 */
638 oatBitVectorIteratorInit(phiBlocks, &iterator);
639 while (true) {
640 int idx = oatBitVectorIteratorNext(&iterator);
641 if (idx == -1) break;
642 BasicBlock* phiBB =
643 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
644 /* Variable will be clobbered before being used - no need for phi */
645 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
buzbeeba938cb2012-02-03 14:47:55 -0800646 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800647 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
buzbee67bf8852011-08-17 17:51:35 -0700648 phi->dalvikInsn.vA = dalvikReg;
649 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700650 phi->meta.phiNext = cUnit->phiList;
651 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700652 oatPrependMIR(phiBB, phi);
653 }
654 }
655}
656
657/*
658 * Worker function to insert phi-operands with latest SSA names from
659 * predecessor blocks
660 */
buzbee31a4a6f2012-02-28 15:36:15 -0800661bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700662{
663 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
buzbee5abfa3e2012-01-31 17:01:43 -0800664 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700665 MIR *mir;
666
667 /* Phi nodes are at the beginning of each block */
668 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800669 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
buzbee67bf8852011-08-17 17:51:35 -0700670 return true;
671 int ssaReg = mir->ssaRep->defs[0];
672 int encodedDalvikValue =
673 (int) oatGrowableListGetElement(cUnit->ssaToDalvikMap, ssaReg);
674 int dalvikReg = DECODE_REG(encodedDalvikValue);
675
676 oatClearAllBits(ssaRegV);
677
678 /* Iterate through the predecessors */
buzbee5abfa3e2012-01-31 17:01:43 -0800679 oatGrowableListIteratorInit(bb->predecessors, &iter);
buzbee67bf8852011-08-17 17:51:35 -0700680 while (true) {
buzbee5abfa3e2012-01-31 17:01:43 -0800681 BasicBlock* predBB =
682 (BasicBlock*)oatGrowableListIteratorNext(&iter);
683 if (!predBB) break;
buzbee67bf8852011-08-17 17:51:35 -0700684 int encodedSSAValue =
685 predBB->dataFlowInfo->dalvikToSSAMap[dalvikReg];
686 int ssaReg = DECODE_REG(encodedSSAValue);
buzbeeba938cb2012-02-03 14:47:55 -0800687 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700688 }
689
690 /* Count the number of SSA registers for a Dalvik register */
691 int numUses = oatCountSetBits(ssaRegV);
692 mir->ssaRep->numUses = numUses;
693 mir->ssaRep->uses =
buzbeeba938cb2012-02-03 14:47:55 -0800694 (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700695 mir->ssaRep->fpUse =
buzbeeba938cb2012-02-03 14:47:55 -0800696 (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
buzbee67bf8852011-08-17 17:51:35 -0700697
698 ArenaBitVectorIterator phiIterator;
699
700 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
701 int *usePtr = mir->ssaRep->uses;
702
703 /* Set the uses array for the phi node */
704 while (true) {
705 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
706 if (ssaRegIdx == -1) break;
707 *usePtr++ = ssaRegIdx;
708 }
709 }
710
711 return true;
712}
713
buzbee31a4a6f2012-02-28 15:36:15 -0800714void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700715{
716
717 if (block->visited || block->hidden) return;
718 block->visited = true;
719
720 /* Process this block */
721 oatDoSSAConversion(cUnit, block);
Ian Rogersa3760aa2011-11-14 14:32:37 -0800722 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700723
724 /* Save SSA map snapshot */
buzbeeba938cb2012-02-03 14:47:55 -0800725 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
726 kAllocDalvikToSSAMap);
buzbeef0cde542011-09-13 14:55:02 -0700727 memcpy(savedSSAMap, cUnit->dalvikToSSAMap, mapSize);
728
729 if (block->fallThrough) {
730 doDFSPreOrderSSARename(cUnit, block->fallThrough);
731 /* Restore SSA map snapshot */
732 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
733 }
734 if (block->taken) {
735 doDFSPreOrderSSARename(cUnit, block->taken);
736 /* Restore SSA map snapshot */
737 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
738 }
739 if (block->successorBlockList.blockListType != kNotUsed) {
740 GrowableListIterator iterator;
741 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
742 &iterator);
743 while (true) {
744 SuccessorBlockInfo *successorBlockInfo =
745 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
746 if (successorBlockInfo == NULL) break;
747 BasicBlock* succBB = successorBlockInfo->block;
748 doDFSPreOrderSSARename(cUnit, succBB);
749 /* Restore SSA map snapshot */
750 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
751 }
752 }
753 cUnit->dalvikToSSAMap = savedSSAMap;
754 return;
755}
756
buzbee67bf8852011-08-17 17:51:35 -0700757/* Perform SSA transformation for the whole method */
758void oatMethodSSATransformation(CompilationUnit* cUnit)
759{
760 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800761 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700762
buzbee99ba9642012-01-25 14:23:14 -0800763 if (!cUnit->disableDataflow) {
764 /* Compute the dominator info */
765 computeDominators(cUnit);
766 }
buzbee67bf8852011-08-17 17:51:35 -0700767
768 /* Allocate data structures in preparation for SSA conversion */
769 oatInitializeSSAConversion(cUnit);
770
buzbee99ba9642012-01-25 14:23:14 -0800771 if (!cUnit->disableDataflow) {
772 /* Find out the "Dalvik reg def x block" relation */
773 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700774
buzbee99ba9642012-01-25 14:23:14 -0800775 /* Insert phi nodes to dominance frontiers for all variables */
776 insertPhiNodes(cUnit);
777 }
buzbee67bf8852011-08-17 17:51:35 -0700778
779 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700780 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
781 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700782 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700783 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700784
buzbee99ba9642012-01-25 14:23:14 -0800785 if (!cUnit->disableDataflow) {
786 /*
787 * Shared temp bit vector used by each block to count the number of defs
788 * from all the predecessor blocks.
789 */
buzbeeba938cb2012-02-03 14:47:55 -0800790 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
791 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700792
buzbee99ba9642012-01-25 14:23:14 -0800793 /* Insert phi-operands with latest SSA names from predecessor blocks */
794 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
795 kReachableNodes,
796 false /* isIterative */);
797 }
buzbee67bf8852011-08-17 17:51:35 -0700798}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800799
800} // namespace art