blob: e9c3d70495d2496ddfd854a3ca88cd40ab82188a [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "Dataflow.h"
19
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080020namespace art {
21
buzbee67bf8852011-08-17 17:51:35 -070022/* Enter the node to the dfsOrder list then visit its successors */
buzbee5b537102012-01-17 17:33:47 -080023STATIC void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
buzbee67bf8852011-08-17 17:51:35 -070024{
25
26 if (block->visited || block->hidden) return;
27 block->visited = true;
28
buzbee5b537102012-01-17 17:33:47 -080029 /* Enqueue the preOrder block id */
buzbee67bf8852011-08-17 17:51:35 -070030 oatInsertGrowableList(&cUnit->dfsOrder, block->id);
31
buzbee5b537102012-01-17 17:33:47 -080032 if (block->fallThrough) recordDFSOrders(cUnit, block->fallThrough);
33 if (block->taken) recordDFSOrders(cUnit, block->taken);
buzbee67bf8852011-08-17 17:51:35 -070034 if (block->successorBlockList.blockListType != kNotUsed) {
35 GrowableListIterator iterator;
36 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
37 &iterator);
38 while (true) {
39 SuccessorBlockInfo *successorBlockInfo =
40 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
41 if (successorBlockInfo == NULL) break;
42 BasicBlock* succBB = successorBlockInfo->block;
buzbee5b537102012-01-17 17:33:47 -080043 recordDFSOrders(cUnit, succBB);
buzbee67bf8852011-08-17 17:51:35 -070044 }
45 }
buzbee5b537102012-01-17 17:33:47 -080046
47 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
48 block->dfsId = cUnit->dfsPostOrder.numUsed;
49 oatInsertGrowableList(&cUnit->dfsPostOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -070050 return;
51}
52
buzbee5b537102012-01-17 17:33:47 -080053/* Sort the blocks by the Depth-First-Search */
54STATIC void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070055{
buzbee5b537102012-01-17 17:33:47 -080056 /* Initialize or reset the DFS preOrder list */
buzbee67bf8852011-08-17 17:51:35 -070057 if (cUnit->dfsOrder.elemList == NULL) {
58 oatInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks);
59 } else {
60 /* Just reset the used length on the counter */
61 cUnit->dfsOrder.numUsed = 0;
62 }
63
buzbee5b537102012-01-17 17:33:47 -080064 /* Initialize or reset the DFS postOrder list */
65 if (cUnit->dfsPostOrder.elemList == NULL) {
66 oatInitGrowableList(&cUnit->dfsPostOrder, cUnit->numBlocks);
67 } else {
68 /* Just reset the used length on the counter */
69 cUnit->dfsPostOrder.numUsed = 0;
70 }
71
buzbee67bf8852011-08-17 17:51:35 -070072 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
73 kAllNodes,
74 false /* isIterative */);
75
buzbee5b537102012-01-17 17:33:47 -080076 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -070077 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
78}
79
80/*
81 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
82 * register idx is defined in BasicBlock bb.
83 */
buzbeeed3e9302011-09-23 17:34:19 -070084STATIC bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070085{
86 if (bb->dataFlowInfo == NULL) return false;
87
88 ArenaBitVectorIterator iterator;
89
90 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
91 while (true) {
92 int idx = oatBitVectorIteratorNext(&iterator);
93 if (idx == -1) break;
94 /* Block bb defines register idx */
95 oatSetBit(cUnit->defBlockMatrix[idx], bb->id);
96 }
97 return true;
98}
99
buzbeeed3e9302011-09-23 17:34:19 -0700100STATIC void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700101{
102 int numRegisters = cUnit->numDalvikRegisters;
103 /* Allocate numDalvikRegisters bit vector pointers */
104 cUnit->defBlockMatrix = (ArenaBitVector **)
105 oatNew(sizeof(ArenaBitVector *) * numRegisters, true);
106 int i;
107
108 /* Initialize numRegister vectors with numBlocks bits each */
109 for (i = 0; i < numRegisters; i++) {
110 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit->numBlocks,
111 false);
112 }
113 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
114 kAllNodes,
115 false /* isIterative */);
116 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
117 kAllNodes,
118 false /* isIterative */);
119
120 /*
121 * Also set the incoming parameters as defs in the entry block.
122 * Only need to handle the parameters for the outer method.
123 */
Ian Rogersa3760aa2011-11-14 14:32:37 -0800124 int numRegs = cUnit->numDalvikRegisters;
125 int inReg = numRegs - cUnit->numIns;
126 for (; inReg < numRegs; inReg++) {
127 oatSetBit(cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
buzbee67bf8852011-08-17 17:51:35 -0700128 }
129}
130
131/* Compute the post-order traversal of the CFG */
buzbeeed3e9302011-09-23 17:34:19 -0700132STATIC void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700133{
134 ArenaBitVectorIterator bvIterator;
135 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
136 GrowableList* blockList = &cUnit->blockList;
137
138 /* Iterate through the dominated blocks first */
139 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800140 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700141 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
142 if (bbIdx == -1) break;
143 BasicBlock* dominatedBB =
144 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
145 computeDomPostOrderTraversal(cUnit, dominatedBB);
146 }
147
148 /* Enter the current block id */
149 oatInsertGrowableList(&cUnit->domPostOrderTraversal, bb->id);
150
151 /* hacky loop detection */
152 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
153 cUnit->hasLoop = true;
154 }
155}
156
buzbeeed3e9302011-09-23 17:34:19 -0700157STATIC void checkForDominanceFrontier(BasicBlock* domBB,
buzbee67bf8852011-08-17 17:51:35 -0700158 const BasicBlock* succBB)
159{
160 /*
161 * TODO - evaluate whether phi will ever need to be inserted into exit
162 * blocks.
163 */
164 if (succBB->iDom != domBB &&
165 succBB->blockType == kDalvikByteCode &&
166 succBB->hidden == false) {
167 oatSetBit(domBB->domFrontier, succBB->id);
168 }
169}
170
171/* Worker function to compute the dominance frontier */
buzbeeed3e9302011-09-23 17:34:19 -0700172STATIC bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700173{
174 GrowableList* blockList = &cUnit->blockList;
175
176 /* Calculate DF_local */
177 if (bb->taken) {
178 checkForDominanceFrontier(bb, bb->taken);
179 }
180 if (bb->fallThrough) {
181 checkForDominanceFrontier(bb, bb->fallThrough);
182 }
183 if (bb->successorBlockList.blockListType != kNotUsed) {
184 GrowableListIterator iterator;
185 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
186 &iterator);
187 while (true) {
188 SuccessorBlockInfo *successorBlockInfo =
189 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
190 if (successorBlockInfo == NULL) break;
191 BasicBlock* succBB = successorBlockInfo->block;
192 checkForDominanceFrontier(bb, succBB);
193 }
194 }
195
196 /* Calculate DF_up */
197 ArenaBitVectorIterator bvIterator;
198 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
199 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800200 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700201 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
202 if (dominatedIdx == -1) break;
203 BasicBlock* dominatedBB = (BasicBlock* )
204 oatGrowableListGetElement(blockList, dominatedIdx);
205 ArenaBitVectorIterator dfIterator;
206 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
207 while (true) {
buzbee5b537102012-01-17 17:33:47 -0800208 //TUNING: hot call to oatBitVectorIteratorNext
buzbee67bf8852011-08-17 17:51:35 -0700209 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
210 if (dfUpIdx == -1) break;
211 BasicBlock* dfUpBlock = (BasicBlock* )
212 oatGrowableListGetElement(blockList, dfUpIdx);
213 checkForDominanceFrontier(bb, dfUpBlock);
214 }
215 }
216
217 return true;
218}
219
220/* Worker function for initializing domination-related data structures */
buzbeeed3e9302011-09-23 17:34:19 -0700221STATIC bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700222{
223 int numTotalBlocks = cUnit->blockList.numUsed;
224
225 if (bb->dominators == NULL ) {
226 bb->dominators = oatAllocBitVector(numTotalBlocks,
227 false /* expandable */);
228 bb->iDominated = oatAllocBitVector(numTotalBlocks,
229 false /* expandable */);
230 bb->domFrontier = oatAllocBitVector(numTotalBlocks,
231 false /* expandable */);
232 } else {
233 oatClearAllBits(bb->dominators);
234 oatClearAllBits(bb->iDominated);
235 oatClearAllBits(bb->domFrontier);
236 }
237 /* Set all bits in the dominator vector */
238 oatSetInitialBits(bb->dominators, numTotalBlocks);
239
240 return true;
241}
242
buzbee5b537102012-01-17 17:33:47 -0800243/*
244 * Worker function to compute each block's dominators. This implementation
245 * is only used when kDebugVerifyDataflow is active and should compute
246 * the same dominator sets as computeBlockDominators.
247 */
248STATIC bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700249{
250 GrowableList* blockList = &cUnit->blockList;
251 int numTotalBlocks = blockList->numUsed;
252 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
253 ArenaBitVectorIterator bvIterator;
254
255 /*
256 * The dominator of the entry block has been preset to itself and we need
257 * to skip the calculation here.
258 */
259 if (bb == cUnit->entryBlock) return false;
260
261 oatSetInitialBits(tempBlockV, numTotalBlocks);
262
263 /* Iterate through the predecessors */
264 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
265 while (true) {
266 int predIdx = oatBitVectorIteratorNext(&bvIterator);
267 if (predIdx == -1) break;
268 BasicBlock* predBB = (BasicBlock* ) oatGrowableListGetElement(
269 blockList, predIdx);
270 /* tempBlockV = tempBlockV ^ dominators */
buzbeeaad72012011-09-21 21:52:09 -0700271 if (predBB->dominators != NULL) {
272 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
273 }
buzbee67bf8852011-08-17 17:51:35 -0700274 }
275 oatSetBit(tempBlockV, bb->id);
276 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
277 oatCopyBitVector(bb->dominators, tempBlockV);
278 return true;
279 }
280 return false;
281}
282
buzbee5b537102012-01-17 17:33:47 -0800283/*
284 * Worker function to compute the idom. This implementation is only
285 * used when kDebugVerifyDataflow is active and should compute the
286 * same iDom as computeBlockIDom.
287 */
288STATIC bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700289{
290 GrowableList* blockList = &cUnit->blockList;
291 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
292 ArenaBitVectorIterator bvIterator;
293 BasicBlock* iDom;
294
295 if (bb == cUnit->entryBlock) return false;
296
297 oatCopyBitVector(tempBlockV, bb->dominators);
298 oatClearBit(tempBlockV, bb->id);
299 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
300
301 /* Should not see any dead block */
buzbeeed3e9302011-09-23 17:34:19 -0700302 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
buzbee67bf8852011-08-17 17:51:35 -0700303 if (oatCountSetBits(tempBlockV) == 1) {
304 iDom = (BasicBlock* ) oatGrowableListGetElement(
305 blockList, oatBitVectorIteratorNext(&bvIterator));
306 bb->iDom = iDom;
307 } else {
308 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
buzbeeed3e9302011-09-23 17:34:19 -0700309 DCHECK_NE(iDomIdx, -1);
buzbee67bf8852011-08-17 17:51:35 -0700310 while (true) {
311 int nextDom = oatBitVectorIteratorNext(&bvIterator);
312 if (nextDom == -1) break;
313 BasicBlock* nextDomBB = (BasicBlock* )
314 oatGrowableListGetElement(blockList, nextDom);
315 /* iDom dominates nextDom - set new iDom */
316 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
317 iDomIdx = nextDom;
318 }
319
320 }
321 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
322 /* Set the immediate dominator block for bb */
323 bb->iDom = iDom;
324 }
325 /* Add bb to the iDominated set of the immediate dominator block */
326 oatSetBit(iDom->iDominated, bb->id);
327 return true;
328}
329
buzbee5b537102012-01-17 17:33:47 -0800330/*
331 * Walk through the ordered iDom list until we reach common parent.
332 * Given the ordering of iDomList, this common parent represents the
333 * last element of the intersection of block1 and block2 dominators.
334 */
335int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
336{
337 while (block1 != block2) {
338 while (block1 < block2) {
339 block1 = cUnit->iDomList[block1];
340 DCHECK_NE(block1, NOTVISITED);
341 }
342 while (block2 < block1) {
343 block2 = cUnit->iDomList[block2];
344 DCHECK_NE(block2, NOTVISITED);
345 }
346 }
347 return block1;
348}
349
350/* Worker function to compute each block's immediate dominator */
351STATIC bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
352{
353 GrowableList* blockList = &cUnit->blockList;
354 ArenaBitVectorIterator bvIterator;
355 int idom = -1;
356
357 /* Special-case entry block */
358 if (bb == cUnit->entryBlock) {
359 return false;
360 }
361
362 /* Iterate through the predecessors */
363 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
364
365 /* Find the first processed predecessor */
366 while (true) {
367 //TUNING: hot call to oatBitVectorIteratorNext
368 int predIdx = oatBitVectorIteratorNext(&bvIterator);
369 DCHECK_NE(predIdx, -1); /* Should find one */
370 BasicBlock* predBB = (BasicBlock* ) oatGrowableListGetElement(
371 blockList, predIdx);
372 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) {
380 int predIdx = oatBitVectorIteratorNext(&bvIterator);
381 if (predIdx == -1) break;
382 BasicBlock* predBB = (BasicBlock* ) oatGrowableListGetElement(
383 blockList, predIdx);
384 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
385 continue;
386 } else {
387 idom = findCommonParent(cUnit, predBB->dfsId, idom);
388 }
389 }
390
391 DCHECK_NE(idom, NOTVISITED);
392
393 /* Did something change? */
394 if (cUnit->iDomList[bb->dfsId] != idom) {
395 cUnit->iDomList[bb->dfsId] = idom;
396 return true;
397 }
398 return false;
399}
400
401/* Worker function to compute each block's domintors */
402STATIC bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
403{
404 if (bb == cUnit->entryBlock) {
405 oatClearAllBits(bb->dominators);
406 } else {
407 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
408 }
409 oatSetBit(bb->dominators, bb->id);
410 return false;
411}
412
413STATIC bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
414{
415 if (bb != cUnit->entryBlock) {
416 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
417 DCHECK_NE(iDomDFSIdx, NOTVISITED);
418 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
419 BasicBlock* iDom = (BasicBlock*)
420 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
421 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
422 DCHECK_EQ(bb->iDom->id, iDom->id);
423 }
424 bb->iDom = iDom;
425 /* Add bb to the iDominated set of the immediate dominator block */
426 oatSetBit(iDom->iDominated, bb->id);
427 }
428 return false;
429}
430
buzbee67bf8852011-08-17 17:51:35 -0700431/* Compute dominators, immediate dominator, and dominance fronter */
buzbeeed3e9302011-09-23 17:34:19 -0700432STATIC void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700433{
434 int numReachableBlocks = cUnit->numReachableBlocks;
435 int numTotalBlocks = cUnit->blockList.numUsed;
436
437 /* Initialize domination-related data structures */
438 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
439 kReachableNodes,
440 false /* isIterative */);
441
buzbee5b537102012-01-17 17:33:47 -0800442 /* Initalize & Clear iDomList */
443 if (cUnit->iDomList == NULL) {
444 cUnit->iDomList = (int*)oatNew(sizeof(int) * numReachableBlocks, false);
445 }
446 for (int i = 0; i < numReachableBlocks; i++) {
447 cUnit->iDomList[i] = NOTVISITED;
448 }
449
450 /* For post-order, last block is entry block. Set its iDom to istelf */
451 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
452 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
453
454 /* Compute the immediate dominators */
455 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
456 kReversePostOrderTraversal,
457 true /* isIterative */);
458
buzbee67bf8852011-08-17 17:51:35 -0700459 /* Set the dominator for the root node */
460 oatClearAllBits(cUnit->entryBlock->dominators);
461 oatSetBit(cUnit->entryBlock->dominators, cUnit->entryBlock->id);
462
463 if (cUnit->tempBlockV == NULL) {
464 cUnit->tempBlockV = oatAllocBitVector(numTotalBlocks,
465 false /* expandable */);
466 } 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) {
496 oatInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks);
497 } else {
498 cUnit->domPostOrderTraversal.numUsed = 0;
499 }
500
501 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
buzbeeed3e9302011-09-23 17:34:19 -0700502 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
buzbee67bf8852011-08-17 17:51:35 -0700503 (unsigned) cUnit->numReachableBlocks);
504
505 /* Now compute the dominance frontier for each block */
506 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
507 kPostOrderDOMTraversal,
508 false /* isIterative */);
509}
510
511/*
512 * Perform dest U= src1 ^ ~src2
513 * This is probably not general enough to be placed in BitVector.[ch].
514 */
buzbeeed3e9302011-09-23 17:34:19 -0700515STATIC void computeSuccLiveIn(ArenaBitVector* dest,
buzbee67bf8852011-08-17 17:51:35 -0700516 const ArenaBitVector* src1,
517 const ArenaBitVector* src2)
518{
519 if (dest->storageSize != src1->storageSize ||
520 dest->storageSize != src2->storageSize ||
521 dest->expandable != src1->expandable ||
522 dest->expandable != src2->expandable) {
523 LOG(FATAL) << "Incompatible set properties";
524 }
525
526 unsigned int idx;
527 for (idx = 0; idx < dest->storageSize; idx++) {
528 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
529 }
530}
531
532/*
533 * Iterate through all successor blocks and propagate up the live-in sets.
534 * The calculated result is used for phi-node pruning - where we only need to
535 * insert a phi node if the variable is live-in to the block.
536 */
buzbeeed3e9302011-09-23 17:34:19 -0700537STATIC bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700538{
539 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
540
541 if (bb->dataFlowInfo == NULL) return false;
542 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
543 if (bb->taken && bb->taken->dataFlowInfo)
544 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
545 bb->dataFlowInfo->defV);
546 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
547 computeSuccLiveIn(tempDalvikRegisterV,
548 bb->fallThrough->dataFlowInfo->liveInV,
549 bb->dataFlowInfo->defV);
550 if (bb->successorBlockList.blockListType != kNotUsed) {
551 GrowableListIterator iterator;
552 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
553 &iterator);
554 while (true) {
555 SuccessorBlockInfo *successorBlockInfo =
556 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
557 if (successorBlockInfo == NULL) break;
558 BasicBlock* succBB = successorBlockInfo->block;
559 if (succBB->dataFlowInfo) {
560 computeSuccLiveIn(tempDalvikRegisterV,
561 succBB->dataFlowInfo->liveInV,
562 bb->dataFlowInfo->defV);
563 }
564 }
565 }
566 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
567 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
568 return true;
569 }
570 return false;
571}
572
573/* Insert phi nodes to for each variable to the dominance frontiers */
buzbeeed3e9302011-09-23 17:34:19 -0700574STATIC void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700575{
576 int dalvikReg;
577 const GrowableList* blockList = &cUnit->blockList;
578 ArenaBitVector* phiBlocks =
579 oatAllocBitVector(cUnit->numBlocks, false);
580 ArenaBitVector* tmpBlocks =
581 oatAllocBitVector(cUnit->numBlocks, false);
582 ArenaBitVector* inputBlocks =
583 oatAllocBitVector(cUnit->numBlocks, false);
584
585 cUnit->tempDalvikRegisterV =
586 oatAllocBitVector(cUnit->numDalvikRegisters, false);
587
588 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
589 kPostOrderDFSTraversal,
590 true /* isIterative */);
591
592 /* Iterate through each Dalvik register */
593 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
594 bool change;
595 ArenaBitVectorIterator iterator;
596
597 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
598 oatClearAllBits(phiBlocks);
599
600 /* Calculate the phi blocks for each Dalvik register */
601 do {
602 change = false;
603 oatClearAllBits(tmpBlocks);
604 oatBitVectorIteratorInit(inputBlocks, &iterator);
605
606 while (true) {
607 int idx = oatBitVectorIteratorNext(&iterator);
608 if (idx == -1) break;
609 BasicBlock* defBB =
610 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
611
612 /* Merge the dominance frontier to tmpBlocks */
buzbee5b537102012-01-17 17:33:47 -0800613 //TUNING: hot call to oatUnifyBitVectors
buzbeeaad72012011-09-21 21:52:09 -0700614 if (defBB->domFrontier != NULL) {
615 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
616 }
buzbee67bf8852011-08-17 17:51:35 -0700617 }
618 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
619 change = true;
620 oatCopyBitVector(phiBlocks, tmpBlocks);
621
622 /*
623 * Iterate through the original blocks plus the new ones in
624 * the dominance frontier.
625 */
626 oatCopyBitVector(inputBlocks, phiBlocks);
627 oatUnifyBitVectors(inputBlocks, inputBlocks,
628 cUnit->defBlockMatrix[dalvikReg]);
629 }
630 } while (change);
631
632 /*
633 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
634 * register is in the live-in set.
635 */
636 oatBitVectorIteratorInit(phiBlocks, &iterator);
637 while (true) {
638 int idx = oatBitVectorIteratorNext(&iterator);
639 if (idx == -1) break;
640 BasicBlock* phiBB =
641 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
642 /* Variable will be clobbered before being used - no need for phi */
643 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
644 MIR *phi = (MIR *) oatNew(sizeof(MIR), true);
645 phi->dalvikInsn.opcode = (Opcode)kMirOpPhi;
646 phi->dalvikInsn.vA = dalvikReg;
647 phi->offset = phiBB->startOffset;
buzbeec0ecd652011-09-25 18:11:54 -0700648 phi->meta.phiNext = cUnit->phiList;
649 cUnit->phiList = phi;
buzbee67bf8852011-08-17 17:51:35 -0700650 oatPrependMIR(phiBB, phi);
651 }
652 }
653}
654
655/*
656 * Worker function to insert phi-operands with latest SSA names from
657 * predecessor blocks
658 */
buzbeeed3e9302011-09-23 17:34:19 -0700659STATIC bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700660{
661 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
662 ArenaBitVectorIterator bvIterator;
663 GrowableList* blockList = &cUnit->blockList;
664 MIR *mir;
665
666 /* Phi nodes are at the beginning of each block */
667 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
668 if (mir->dalvikInsn.opcode != (Opcode)kMirOpPhi)
669 return true;
670 int ssaReg = mir->ssaRep->defs[0];
671 int encodedDalvikValue =
672 (int) oatGrowableListGetElement(cUnit->ssaToDalvikMap, ssaReg);
673 int dalvikReg = DECODE_REG(encodedDalvikValue);
674
675 oatClearAllBits(ssaRegV);
676
677 /* Iterate through the predecessors */
678 oatBitVectorIteratorInit(bb->predecessors, &bvIterator);
679 while (true) {
680 int predIdx = oatBitVectorIteratorNext(&bvIterator);
681 if (predIdx == -1) break;
682 BasicBlock* predBB = (BasicBlock* ) oatGrowableListGetElement(
683 blockList, predIdx);
684 int encodedSSAValue =
685 predBB->dataFlowInfo->dalvikToSSAMap[dalvikReg];
686 int ssaReg = DECODE_REG(encodedSSAValue);
687 oatSetBit(ssaRegV, ssaReg);
688 }
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 =
694 (int *) oatNew(sizeof(int) * numUses, false);
695 mir->ssaRep->fpUse =
696 (bool *) oatNew(sizeof(bool) * numUses, true);
697
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
buzbeeed3e9302011-09-23 17:34:19 -0700714STATIC void 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 */
725 int* savedSSAMap = (int*)oatNew(mapSize, false);
726 memcpy(savedSSAMap, cUnit->dalvikToSSAMap, mapSize);
727
728 if (block->fallThrough) {
729 doDFSPreOrderSSARename(cUnit, block->fallThrough);
730 /* Restore SSA map snapshot */
731 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
732 }
733 if (block->taken) {
734 doDFSPreOrderSSARename(cUnit, block->taken);
735 /* Restore SSA map snapshot */
736 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
737 }
738 if (block->successorBlockList.blockListType != kNotUsed) {
739 GrowableListIterator iterator;
740 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
741 &iterator);
742 while (true) {
743 SuccessorBlockInfo *successorBlockInfo =
744 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
745 if (successorBlockInfo == NULL) break;
746 BasicBlock* succBB = successorBlockInfo->block;
747 doDFSPreOrderSSARename(cUnit, succBB);
748 /* Restore SSA map snapshot */
749 memcpy(cUnit->dalvikToSSAMap, savedSSAMap, mapSize);
750 }
751 }
752 cUnit->dalvikToSSAMap = savedSSAMap;
753 return;
754}
755
buzbee67bf8852011-08-17 17:51:35 -0700756/* Perform SSA transformation for the whole method */
757void oatMethodSSATransformation(CompilationUnit* cUnit)
758{
759 /* Compute the DFS order */
buzbee5b537102012-01-17 17:33:47 -0800760 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700761
buzbee99ba9642012-01-25 14:23:14 -0800762 if (!cUnit->disableDataflow) {
763 /* Compute the dominator info */
764 computeDominators(cUnit);
765 }
buzbee67bf8852011-08-17 17:51:35 -0700766
767 /* Allocate data structures in preparation for SSA conversion */
768 oatInitializeSSAConversion(cUnit);
769
buzbee99ba9642012-01-25 14:23:14 -0800770 if (!cUnit->disableDataflow) {
771 /* Find out the "Dalvik reg def x block" relation */
772 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700773
buzbee99ba9642012-01-25 14:23:14 -0800774 /* Insert phi nodes to dominance frontiers for all variables */
775 insertPhiNodes(cUnit);
776 }
buzbee67bf8852011-08-17 17:51:35 -0700777
778 /* Rename register names by local defs and phi nodes */
buzbeef0cde542011-09-13 14:55:02 -0700779 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
780 kAllNodes,
buzbee67bf8852011-08-17 17:51:35 -0700781 false /* isIterative */);
buzbeef0cde542011-09-13 14:55:02 -0700782 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700783
buzbee99ba9642012-01-25 14:23:14 -0800784 if (!cUnit->disableDataflow) {
785 /*
786 * Shared temp bit vector used by each block to count the number of defs
787 * from all the predecessor blocks.
788 */
789 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit->numSSARegs,
buzbee67bf8852011-08-17 17:51:35 -0700790 false);
791
buzbee99ba9642012-01-25 14:23:14 -0800792 /* Insert phi-operands with latest SSA names from predecessor blocks */
793 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
794 kReachableNodes,
795 false /* isIterative */);
796 }
buzbee67bf8852011-08-17 17:51:35 -0700797}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800798
799} // namespace art