blob: aedf4be2e6f7feadc91d824ef05afd3a3b0a6f97 [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
buzbeee5f01222012-06-14 15:19:35 -070022// Make sure iterative dfs recording matches old recursive version
23//#define TEST_DFS
24
25inline BasicBlock* needsVisit(BasicBlock* bb) {
26 if (bb != NULL) {
27 if (bb->visited || bb->hidden) {
28 bb = NULL;
29 }
30 }
31 return bb;
32}
33
34BasicBlock* nextUnvisitedSuccessor(BasicBlock* bb)
35{
36 BasicBlock* res = needsVisit(bb->fallThrough);
37 if (res == NULL) {
38 res = needsVisit(bb->taken);
39 if (res == NULL) {
40 if (bb->successorBlockList.blockListType != kNotUsed) {
41 GrowableListIterator iterator;
42 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
43 &iterator);
44 while (true) {
45 SuccessorBlockInfo *sbi = (SuccessorBlockInfo*)
46 oatGrowableListIteratorNext(&iterator);
47 if (sbi == NULL) break;
48 res = needsVisit(sbi->block);
49 if (res != NULL) break;
50 }
51 }
52 }
53 }
54 return res;
55}
56
57void markPreOrder(CompilationUnit* cUnit, BasicBlock* block)
58{
59 block->visited = true;
60 // Can this block be reached only via previous block fallthrough?
61 if ((block->blockType == kDalvikByteCode) &&
62 (block->predecessors->numUsed == 1)) {
63 DCHECK_GE(cUnit->dfsOrder.numUsed, 1U);
64 int prevIdx = cUnit->dfsOrder.numUsed - 1;
65 int prevId = cUnit->dfsOrder.elemList[prevIdx];
66 BasicBlock* predBB = (BasicBlock*)block->predecessors->elemList[0];
67 if (predBB->id == prevId) {
68 block->fallThroughTarget = true;
69 }
70 }
71
72 /* Enqueue the preOrder block id */
73 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
74}
75
buzbee31a4a6f2012-02-28 15:36:15 -080076void recordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
buzbee67bf8852011-08-17 17:51:35 -070077{
buzbeee5f01222012-06-14 15:19:35 -070078 std::vector<BasicBlock*> succ;
79 markPreOrder(cUnit, block);
80 succ.push_back(block);
81 while (!succ.empty()) {
82 BasicBlock* curr = succ.back();
83 BasicBlock* nextSuccessor = nextUnvisitedSuccessor(curr);
84 if (nextSuccessor != NULL) {
85 markPreOrder(cUnit, nextSuccessor);
86 succ.push_back(nextSuccessor);
87 continue;
88 }
89 curr->dfsId = cUnit->dfsPostOrder.numUsed;
90 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, curr->id);
91 succ.pop_back();
92 }
93}
94
95#if defined(TEST_DFS)
96/* Enter the node to the dfsOrder list then visit its successors */
97void recursiveRecordDFSOrders(CompilationUnit* cUnit, BasicBlock* block)
98{
buzbee67bf8852011-08-17 17:51:35 -070099
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 if (block->visited || block->hidden) return;
101 block->visited = true;
buzbee67bf8852011-08-17 17:51:35 -0700102
Bill Buzbeea114add2012-05-03 15:00:40 -0700103 // Can this block be reached only via previous block fallthrough?
104 if ((block->blockType == kDalvikByteCode) &&
105 (block->predecessors->numUsed == 1)) {
106 DCHECK_GE(cUnit->dfsOrder.numUsed, 1U);
107 int prevIdx = cUnit->dfsOrder.numUsed - 1;
108 int prevId = cUnit->dfsOrder.elemList[prevIdx];
109 BasicBlock* predBB = (BasicBlock*)block->predecessors->elemList[0];
110 if (predBB->id == prevId) {
111 block->fallThroughTarget = true;
buzbee3d661942012-03-14 17:37:27 -0700112 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700113 }
buzbee3d661942012-03-14 17:37:27 -0700114
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 /* Enqueue the preOrder block id */
116 oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
buzbee67bf8852011-08-17 17:51:35 -0700117
Bill Buzbeea114add2012-05-03 15:00:40 -0700118 if (block->fallThrough) {
buzbeee5f01222012-06-14 15:19:35 -0700119 recursiveRecordDFSOrders(cUnit, block->fallThrough);
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 }
buzbeee5f01222012-06-14 15:19:35 -0700121 if (block->taken) recursiveRecordDFSOrders(cUnit, block->taken);
Bill Buzbeea114add2012-05-03 15:00:40 -0700122 if (block->successorBlockList.blockListType != kNotUsed) {
123 GrowableListIterator iterator;
124 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
125 &iterator);
126 while (true) {
127 SuccessorBlockInfo *successorBlockInfo =
128 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
129 if (successorBlockInfo == NULL) break;
130 BasicBlock* succBB = successorBlockInfo->block;
buzbeee5f01222012-06-14 15:19:35 -0700131 recursiveRecordDFSOrders(cUnit, succBB);
buzbeee1965672012-03-11 18:39:19 -0700132 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 }
buzbee5b537102012-01-17 17:33:47 -0800134
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
136 block->dfsId = cUnit->dfsPostOrder.numUsed;
137 oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
138 return;
buzbee67bf8852011-08-17 17:51:35 -0700139}
buzbeee5f01222012-06-14 15:19:35 -0700140#endif
buzbee67bf8852011-08-17 17:51:35 -0700141
buzbee5b537102012-01-17 17:33:47 -0800142/* Sort the blocks by the Depth-First-Search */
buzbee31a4a6f2012-02-28 15:36:15 -0800143void computeDFSOrders(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700144{
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 /* Initialize or reset the DFS preOrder list */
146 if (cUnit->dfsOrder.elemList == NULL) {
147 oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
148 kListDfsOrder);
149 } else {
150 /* Just reset the used length on the counter */
151 cUnit->dfsOrder.numUsed = 0;
152 }
buzbee67bf8852011-08-17 17:51:35 -0700153
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 /* Initialize or reset the DFS postOrder list */
155 if (cUnit->dfsPostOrder.elemList == NULL) {
156 oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
157 kListDfsPostOrder);
158 } else {
159 /* Just reset the used length on the counter */
160 cUnit->dfsPostOrder.numUsed = 0;
161 }
buzbee5b537102012-01-17 17:33:47 -0800162
buzbeee5f01222012-06-14 15:19:35 -0700163#if defined(TEST_DFS)
164 // Reset visited flags
Bill Buzbeea114add2012-05-03 15:00:40 -0700165 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
166 kAllNodes, false /* isIterative */);
buzbeee5f01222012-06-14 15:19:35 -0700167 // Record pre and post order dfs
168 recursiveRecordDFSOrders(cUnit, cUnit->entryBlock);
169 // Copy the results for later comparison and reset the lists
170 GrowableList recursiveDfsOrder;
171 GrowableList recursiveDfsPostOrder;
172 oatInitGrowableList(cUnit, &recursiveDfsOrder, cUnit->dfsOrder.numUsed,
173 kListDfsOrder);
174 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
175 oatInsertGrowableList(cUnit, &recursiveDfsOrder,
176 cUnit->dfsOrder.elemList[i]);
177 }
178 cUnit->dfsOrder.numUsed = 0;
179 oatInitGrowableList(cUnit, &recursiveDfsPostOrder,
180 cUnit->dfsPostOrder.numUsed, kListDfsOrder);
181 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
182 oatInsertGrowableList(cUnit, &recursiveDfsPostOrder,
183 cUnit->dfsPostOrder.elemList[i]);
184 }
185 cUnit->dfsPostOrder.numUsed = 0;
186#endif
buzbee67bf8852011-08-17 17:51:35 -0700187
buzbeee5f01222012-06-14 15:19:35 -0700188 // Reset visited flags from all nodes
189 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
190 kAllNodes, false /* isIterative */);
191 // Record dfs orders
Bill Buzbeea114add2012-05-03 15:00:40 -0700192 recordDFSOrders(cUnit, cUnit->entryBlock);
buzbeee5f01222012-06-14 15:19:35 -0700193
194#if defined(TEST_DFS)
195 bool mismatch = false;
196 mismatch |= (cUnit->dfsOrder.numUsed != recursiveDfsOrder.numUsed);
197 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
198 mismatch |= (cUnit->dfsOrder.elemList[i] !=
199 recursiveDfsOrder.elemList[i]);
200 }
201 mismatch |= (cUnit->dfsPostOrder.numUsed != recursiveDfsPostOrder.numUsed);
202 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
203 mismatch |= (cUnit->dfsPostOrder.elemList[i] !=
204 recursiveDfsPostOrder.elemList[i]);
205 }
206 if (mismatch) {
207 LOG(INFO) << "Mismatch for "
208 << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
209 oatDumpCFG(cUnit, "/tmp/");
210 LOG(INFO) << "New dfs";
211 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
212 LOG(INFO) << i << " - " << cUnit->dfsOrder.elemList[i];
213 }
214 LOG(INFO) << "Recursive dfs";
215 for (unsigned int i = 0; i < recursiveDfsOrder.numUsed; i++) {
216 LOG(INFO) << i << " - " << recursiveDfsOrder.elemList[i];
217 }
218 LOG(INFO) << "New post dfs";
219 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
220 LOG(INFO) << i << " - " << cUnit->dfsPostOrder.elemList[i];
221 }
222 LOG(INFO) << "Recursive post dfs";
223 for (unsigned int i = 0; i < recursiveDfsPostOrder.numUsed; i++) {
224 LOG(INFO) << i << " - " << recursiveDfsPostOrder.elemList[i];
225 }
226 }
227 CHECK_EQ(cUnit->dfsOrder.numUsed, recursiveDfsOrder.numUsed);
228 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
229 CHECK_EQ(cUnit->dfsOrder.elemList[i], recursiveDfsOrder.elemList[i]);
230 }
231 CHECK_EQ(cUnit->dfsPostOrder.numUsed, recursiveDfsPostOrder.numUsed);
232 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
233 CHECK_EQ(cUnit->dfsPostOrder.elemList[i],
234 recursiveDfsPostOrder.elemList[i]);
235 }
236#endif
237
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700239}
240
241/*
242 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
243 * register idx is defined in BasicBlock bb.
244 */
buzbee31a4a6f2012-02-28 15:36:15 -0800245bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700246{
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -0700248
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700250
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
252 while (true) {
253 int idx = oatBitVectorIteratorNext(&iterator);
254 if (idx == -1) break;
255 /* Block bb defines register idx */
256 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
257 }
258 return true;
buzbee67bf8852011-08-17 17:51:35 -0700259}
260
buzbee31a4a6f2012-02-28 15:36:15 -0800261void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700262{
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 int numRegisters = cUnit->numDalvikRegisters;
264 /* Allocate numDalvikRegisters bit vector pointers */
265 cUnit->defBlockMatrix = (ArenaBitVector **)
266 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
267 kAllocDFInfo);
268 int i;
buzbee67bf8852011-08-17 17:51:35 -0700269
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 /* Initialize numRegister vectors with numBlocks bits each */
271 for (i = 0; i < numRegisters; i++) {
272 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
273 false, kBitMapBMatrix);
274 }
275 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
276 kAllNodes, false /* isIterative */);
277 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
278 kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700279
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 /*
281 * Also set the incoming parameters as defs in the entry block.
282 * Only need to handle the parameters for the outer method.
283 */
284 int numRegs = cUnit->numDalvikRegisters;
285 int inReg = numRegs - cUnit->numIns;
286 for (; inReg < numRegs; inReg++) {
287 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
288 }
buzbee67bf8852011-08-17 17:51:35 -0700289}
290
291/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800292void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700293{
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 ArenaBitVectorIterator bvIterator;
295 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
296 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700297
Bill Buzbeea114add2012-05-03 15:00:40 -0700298 /* Iterate through the dominated blocks first */
299 while (true) {
300 //TUNING: hot call to oatBitVectorIteratorNext
301 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
302 if (bbIdx == -1) break;
303 BasicBlock* dominatedBB =
304 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
305 computeDomPostOrderTraversal(cUnit, dominatedBB);
306 }
buzbee67bf8852011-08-17 17:51:35 -0700307
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 /* Enter the current block id */
309 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700310
Bill Buzbeea114add2012-05-03 15:00:40 -0700311 /* hacky loop detection */
312 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
313 cUnit->hasLoop = true;
314 }
buzbee67bf8852011-08-17 17:51:35 -0700315}
316
buzbee31a4a6f2012-02-28 15:36:15 -0800317void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700319{
Bill Buzbeea114add2012-05-03 15:00:40 -0700320 /*
321 * TODO - evaluate whether phi will ever need to be inserted into exit
322 * blocks.
323 */
324 if (succBB->iDom != domBB &&
325 succBB->blockType == kDalvikByteCode &&
326 succBB->hidden == false) {
327 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
328 }
buzbee67bf8852011-08-17 17:51:35 -0700329}
330
331/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800332bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700333{
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700335
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 /* Calculate DF_local */
337 if (bb->taken) {
338 checkForDominanceFrontier(cUnit, bb, bb->taken);
339 }
340 if (bb->fallThrough) {
341 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
342 }
343 if (bb->successorBlockList.blockListType != kNotUsed) {
344 GrowableListIterator iterator;
345 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
346 &iterator);
347 while (true) {
348 SuccessorBlockInfo *successorBlockInfo =
349 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
350 if (successorBlockInfo == NULL) break;
351 BasicBlock* succBB = successorBlockInfo->block;
352 checkForDominanceFrontier(cUnit, bb, succBB);
353 }
354 }
buzbee67bf8852011-08-17 17:51:35 -0700355
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 /* Calculate DF_up */
357 ArenaBitVectorIterator bvIterator;
358 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
359 while (true) {
360 //TUNING: hot call to oatBitVectorIteratorNext
361 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
362 if (dominatedIdx == -1) break;
363 BasicBlock* dominatedBB = (BasicBlock* )
364 oatGrowableListGetElement(blockList, dominatedIdx);
365 ArenaBitVectorIterator dfIterator;
366 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
buzbee67bf8852011-08-17 17:51:35 -0700367 while (true) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 //TUNING: hot call to oatBitVectorIteratorNext
369 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
370 if (dfUpIdx == -1) break;
371 BasicBlock* dfUpBlock = (BasicBlock* )
372 oatGrowableListGetElement(blockList, dfUpIdx);
373 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700374 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 }
buzbee67bf8852011-08-17 17:51:35 -0700376
Bill Buzbeea114add2012-05-03 15:00:40 -0700377 return true;
buzbee67bf8852011-08-17 17:51:35 -0700378}
379
380/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800381bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700382{
Bill Buzbeea114add2012-05-03 15:00:40 -0700383 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700384
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 if (bb->dominators == NULL ) {
386 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
387 false /* expandable */,
388 kBitMapDominators);
389 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
390 false /* expandable */,
391 kBitMapIDominated);
392 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
393 false /* expandable */,
394 kBitMapDomFrontier);
395 } else {
396 oatClearAllBits(bb->dominators);
397 oatClearAllBits(bb->iDominated);
398 oatClearAllBits(bb->domFrontier);
399 }
400 /* Set all bits in the dominator vector */
401 oatSetInitialBits(bb->dominators, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700402
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 return true;
buzbee67bf8852011-08-17 17:51:35 -0700404}
405
buzbee5b537102012-01-17 17:33:47 -0800406/*
407 * Worker function to compute each block's dominators. This implementation
408 * is only used when kDebugVerifyDataflow is active and should compute
409 * the same dominator sets as computeBlockDominators.
410 */
buzbee31a4a6f2012-02-28 15:36:15 -0800411bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700412{
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 GrowableList* blockList = &cUnit->blockList;
414 int numTotalBlocks = blockList->numUsed;
415 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
416 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700417
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 /*
419 * The dominator of the entry block has been preset to itself and we need
420 * to skip the calculation here.
421 */
422 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700423
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 oatSetInitialBits(tempBlockV, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700425
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 /* Iterate through the predecessors */
427 oatGrowableListIteratorInit(bb->predecessors, &iter);
428 while (true) {
429 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
430 if (!predBB) break;
431 /* tempBlockV = tempBlockV ^ dominators */
432 if (predBB->dominators != NULL) {
433 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
buzbee67bf8852011-08-17 17:51:35 -0700434 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 }
436 oatSetBit(cUnit, tempBlockV, bb->id);
437 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
438 oatCopyBitVector(bb->dominators, tempBlockV);
439 return true;
440 }
441 return false;
buzbee67bf8852011-08-17 17:51:35 -0700442}
443
buzbee5b537102012-01-17 17:33:47 -0800444/*
445 * Worker function to compute the idom. This implementation is only
446 * used when kDebugVerifyDataflow is active and should compute the
447 * same iDom as computeBlockIDom.
448 */
buzbee31a4a6f2012-02-28 15:36:15 -0800449bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700450{
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 GrowableList* blockList = &cUnit->blockList;
452 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
453 ArenaBitVectorIterator bvIterator;
454 BasicBlock* iDom;
buzbee67bf8852011-08-17 17:51:35 -0700455
Bill Buzbeea114add2012-05-03 15:00:40 -0700456 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700457
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 oatCopyBitVector(tempBlockV, bb->dominators);
459 oatClearBit(tempBlockV, bb->id);
460 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
buzbee67bf8852011-08-17 17:51:35 -0700461
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 /* Should not see any dead block */
463 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
464 if (oatCountSetBits(tempBlockV) == 1) {
465 iDom = (BasicBlock* )
466 oatGrowableListGetElement(blockList,
467 oatBitVectorIteratorNext(&bvIterator));
468 bb->iDom = iDom;
469 } else {
470 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
471 DCHECK_NE(iDomIdx, -1);
472 while (true) {
473 int nextDom = oatBitVectorIteratorNext(&bvIterator);
474 if (nextDom == -1) break;
475 BasicBlock* nextDomBB = (BasicBlock* )
476 oatGrowableListGetElement(blockList, nextDom);
477 /* iDom dominates nextDom - set new iDom */
478 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
479 iDomIdx = nextDom;
480 }
buzbee67bf8852011-08-17 17:51:35 -0700481
buzbee67bf8852011-08-17 17:51:35 -0700482 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
484 /* Set the immediate dominator block for bb */
485 bb->iDom = iDom;
486 }
487 /* Add bb to the iDominated set of the immediate dominator block */
488 oatSetBit(cUnit, iDom->iDominated, bb->id);
489 return true;
buzbee67bf8852011-08-17 17:51:35 -0700490}
491
buzbee5b537102012-01-17 17:33:47 -0800492/*
493 * Walk through the ordered iDom list until we reach common parent.
494 * Given the ordering of iDomList, this common parent represents the
495 * last element of the intersection of block1 and block2 dominators.
496 */
497int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
498{
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 while (block1 != block2) {
500 while (block1 < block2) {
501 block1 = cUnit->iDomList[block1];
502 DCHECK_NE(block1, NOTVISITED);
buzbee5b537102012-01-17 17:33:47 -0800503 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 while (block2 < block1) {
505 block2 = cUnit->iDomList[block2];
506 DCHECK_NE(block2, NOTVISITED);
507 }
508 }
509 return block1;
buzbee5b537102012-01-17 17:33:47 -0800510}
511
512/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800513bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800514{
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 GrowableListIterator iter;
516 int idom = -1;
buzbee5b537102012-01-17 17:33:47 -0800517
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 /* Special-case entry block */
519 if (bb == cUnit->entryBlock) {
buzbee5b537102012-01-17 17:33:47 -0800520 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 }
522
523 /* Iterate through the predecessors */
524 oatGrowableListIteratorInit(bb->predecessors, &iter);
525
526 /* Find the first processed predecessor */
527 while (true) {
528 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
529 CHECK(predBB != NULL);
530 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
531 idom = predBB->dfsId;
532 break;
533 }
534 }
535
536 /* Scan the rest of the predecessors */
537 while (true) {
538 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
539 if (!predBB) break;
540 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
541 continue;
542 } else {
543 idom = findCommonParent(cUnit, predBB->dfsId, idom);
544 }
545 }
546
547 DCHECK_NE(idom, NOTVISITED);
548
549 /* Did something change? */
550 if (cUnit->iDomList[bb->dfsId] != idom) {
551 cUnit->iDomList[bb->dfsId] = idom;
552 return true;
553 }
554 return false;
buzbee5b537102012-01-17 17:33:47 -0800555}
556
557/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800558bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800559{
Bill Buzbeea114add2012-05-03 15:00:40 -0700560 if (bb == cUnit->entryBlock) {
561 oatClearAllBits(bb->dominators);
562 } else {
563 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
564 }
565 oatSetBit(cUnit, bb->dominators, bb->id);
566 return false;
buzbee5b537102012-01-17 17:33:47 -0800567}
568
buzbee31a4a6f2012-02-28 15:36:15 -0800569bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800570{
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 if (bb != cUnit->entryBlock) {
572 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
573 DCHECK_NE(iDomDFSIdx, NOTVISITED);
574 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
575 BasicBlock* iDom = (BasicBlock*)
576 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
577 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
578 DCHECK_EQ(bb->iDom->id, iDom->id);
buzbee5b537102012-01-17 17:33:47 -0800579 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 bb->iDom = iDom;
581 /* Add bb to the iDominated set of the immediate dominator block */
582 oatSetBit(cUnit, iDom->iDominated, bb->id);
583 }
584 return false;
buzbee5b537102012-01-17 17:33:47 -0800585}
586
buzbee67bf8852011-08-17 17:51:35 -0700587/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800588void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700589{
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 int numReachableBlocks = cUnit->numReachableBlocks;
591 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700592
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 /* Initialize domination-related data structures */
594 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
595 kReachableNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700596
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 /* Initalize & Clear iDomList */
598 if (cUnit->iDomList == NULL) {
599 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
600 false, kAllocDFInfo);
601 }
602 for (int i = 0; i < numReachableBlocks; i++) {
603 cUnit->iDomList[i] = NOTVISITED;
604 }
buzbee5b537102012-01-17 17:33:47 -0800605
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 /* For post-order, last block is entry block. Set its iDom to istelf */
607 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
608 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
buzbee5b537102012-01-17 17:33:47 -0800609
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 /* Compute the immediate dominators */
611 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
612 kReversePostOrderTraversal,
613 true /* isIterative */);
614
615 /* Set the dominator for the root node */
616 oatClearAllBits(cUnit->entryBlock->dominators);
617 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
618
619 if (cUnit->tempBlockV == NULL) {
620 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
621 false /* expandable */,
622 kBitMapTmpBlockV);
623 } else {
624 oatClearAllBits(cUnit->tempBlockV);
625 }
626 cUnit->entryBlock->iDom = NULL;
627
628 /* For testing, compute sets using alternate mechanism */
629 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
630 // Use alternate mechanism to compute dominators for comparison
631 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
632 kPreOrderDFSTraversal,
buzbee5b537102012-01-17 17:33:47 -0800633 true /* isIterative */);
634
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
636 kReachableNodes,
637 false /* isIterative */);
638 }
buzbee67bf8852011-08-17 17:51:35 -0700639
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
641 kReachableNodes,
642 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800643
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
645 kReversePostOrderTraversal,
646 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800647
Bill Buzbeea114add2012-05-03 15:00:40 -0700648 /*
649 * Now go ahead and compute the post order traversal based on the
650 * iDominated sets.
651 */
652 if (cUnit->domPostOrderTraversal.elemList == NULL) {
653 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
654 numReachableBlocks, kListDomPostOrderTraversal);
655 } else {
656 cUnit->domPostOrderTraversal.numUsed = 0;
657 }
buzbee5b537102012-01-17 17:33:47 -0800658
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
660 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
661 (unsigned) cUnit->numReachableBlocks);
buzbee5b537102012-01-17 17:33:47 -0800662
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 /* Now compute the dominance frontier for each block */
664 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
665 kPostOrderDOMTraversal,
666 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700667}
668
669/*
670 * Perform dest U= src1 ^ ~src2
671 * This is probably not general enough to be placed in BitVector.[ch].
672 */
buzbee31a4a6f2012-02-28 15:36:15 -0800673void computeSuccLiveIn(ArenaBitVector* dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 const ArenaBitVector* src1,
675 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700676{
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 if (dest->storageSize != src1->storageSize ||
678 dest->storageSize != src2->storageSize ||
679 dest->expandable != src1->expandable ||
680 dest->expandable != src2->expandable) {
681 LOG(FATAL) << "Incompatible set properties";
682 }
buzbee67bf8852011-08-17 17:51:35 -0700683
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 unsigned int idx;
685 for (idx = 0; idx < dest->storageSize; idx++) {
686 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
687 }
buzbee67bf8852011-08-17 17:51:35 -0700688}
689
690/*
691 * Iterate through all successor blocks and propagate up the live-in sets.
692 * The calculated result is used for phi-node pruning - where we only need to
693 * insert a phi node if the variable is live-in to the block.
694 */
buzbee31a4a6f2012-02-28 15:36:15 -0800695bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700696{
Bill Buzbeea114add2012-05-03 15:00:40 -0700697 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
buzbee67bf8852011-08-17 17:51:35 -0700698
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 if (bb->dataFlowInfo == NULL) return false;
700 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
701 if (bb->taken && bb->taken->dataFlowInfo)
702 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
703 bb->dataFlowInfo->defV);
704 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
705 computeSuccLiveIn(tempDalvikRegisterV,
706 bb->fallThrough->dataFlowInfo->liveInV,
707 bb->dataFlowInfo->defV);
708 if (bb->successorBlockList.blockListType != kNotUsed) {
709 GrowableListIterator iterator;
710 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
711 &iterator);
712 while (true) {
713 SuccessorBlockInfo *successorBlockInfo =
714 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
715 if (successorBlockInfo == NULL) break;
716 BasicBlock* succBB = successorBlockInfo->block;
717 if (succBB->dataFlowInfo) {
buzbee67bf8852011-08-17 17:51:35 -0700718 computeSuccLiveIn(tempDalvikRegisterV,
Bill Buzbeea114add2012-05-03 15:00:40 -0700719 succBB->dataFlowInfo->liveInV,
buzbee67bf8852011-08-17 17:51:35 -0700720 bb->dataFlowInfo->defV);
Bill Buzbeea114add2012-05-03 15:00:40 -0700721 }
buzbee67bf8852011-08-17 17:51:35 -0700722 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700723 }
724 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
725 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
726 return true;
727 }
728 return false;
buzbee67bf8852011-08-17 17:51:35 -0700729}
730
731/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800732void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700733{
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 int dalvikReg;
735 const GrowableList* blockList = &cUnit->blockList;
736 ArenaBitVector* phiBlocks =
737 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
738 ArenaBitVector* tmpBlocks =
739 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
740 ArenaBitVector* inputBlocks =
741 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700742
Bill Buzbeea114add2012-05-03 15:00:40 -0700743 cUnit->tempDalvikRegisterV =
744 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
745 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700746
Bill Buzbeea114add2012-05-03 15:00:40 -0700747 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
748 kPostOrderDFSTraversal, true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700749
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 /* Iterate through each Dalvik register */
751 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
752 bool change;
753 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700754
Bill Buzbeea114add2012-05-03 15:00:40 -0700755 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
756 oatClearAllBits(phiBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700757
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 /* Calculate the phi blocks for each Dalvik register */
759 do {
760 change = false;
761 oatClearAllBits(tmpBlocks);
762 oatBitVectorIteratorInit(inputBlocks, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700763
Bill Buzbeea114add2012-05-03 15:00:40 -0700764 while (true) {
765 int idx = oatBitVectorIteratorNext(&iterator);
766 if (idx == -1) break;
767 BasicBlock* defBB =
768 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
buzbee67bf8852011-08-17 17:51:35 -0700769
Bill Buzbeea114add2012-05-03 15:00:40 -0700770 /* Merge the dominance frontier to tmpBlocks */
771 //TUNING: hot call to oatUnifyBitVectors
772 if (defBB->domFrontier != NULL) {
773 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
774 }
buzbee67bf8852011-08-17 17:51:35 -0700775 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
777 change = true;
778 oatCopyBitVector(phiBlocks, tmpBlocks);
779
780 /*
781 * Iterate through the original blocks plus the new ones in
782 * the dominance frontier.
783 */
784 oatCopyBitVector(inputBlocks, phiBlocks);
785 oatUnifyBitVectors(inputBlocks, inputBlocks,
786 cUnit->defBlockMatrix[dalvikReg]);
787 }
788 } while (change);
789
790 /*
791 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
792 * register is in the live-in set.
793 */
794 oatBitVectorIteratorInit(phiBlocks, &iterator);
795 while (true) {
796 int idx = oatBitVectorIteratorNext(&iterator);
797 if (idx == -1) break;
798 BasicBlock* phiBB =
799 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
800 /* Variable will be clobbered before being used - no need for phi */
801 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
802 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
803 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
804 phi->dalvikInsn.vA = dalvikReg;
805 phi->offset = phiBB->startOffset;
806 phi->meta.phiNext = cUnit->phiList;
807 cUnit->phiList = phi;
808 oatPrependMIR(phiBB, phi);
buzbee67bf8852011-08-17 17:51:35 -0700809 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 }
buzbee67bf8852011-08-17 17:51:35 -0700811}
812
813/*
814 * Worker function to insert phi-operands with latest SSA names from
815 * predecessor blocks
816 */
buzbee31a4a6f2012-02-28 15:36:15 -0800817bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700818{
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 ArenaBitVector* ssaRegV = cUnit->tempSSARegisterV;
820 GrowableListIterator iter;
821 MIR *mir;
buzbee67bf8852011-08-17 17:51:35 -0700822
Bill Buzbeea114add2012-05-03 15:00:40 -0700823 /* Phi nodes are at the beginning of each block */
824 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
825 if (mir->dalvikInsn.opcode != (Instruction::Code)kMirOpPhi)
826 return true;
827 int ssaReg = mir->ssaRep->defs[0];
828 DCHECK_GE(ssaReg, 0); // Shouldn't see compiler temps here
829 int vReg = SRegToVReg(cUnit, ssaReg);
buzbee67bf8852011-08-17 17:51:35 -0700830
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 oatClearAllBits(ssaRegV);
buzbee67bf8852011-08-17 17:51:35 -0700832
Bill Buzbeea114add2012-05-03 15:00:40 -0700833 /* Iterate through the predecessors */
834 oatGrowableListIteratorInit(bb->predecessors, &iter);
835 while (true) {
836 BasicBlock* predBB =
837 (BasicBlock*)oatGrowableListIteratorNext(&iter);
838 if (!predBB) break;
839 int ssaReg = predBB->dataFlowInfo->vRegToSSAMap[vReg];
840 oatSetBit(cUnit, ssaRegV, ssaReg);
buzbee2cfc6392012-05-07 14:51:40 -0700841 cUnit->tempSSABlockIdV[ssaReg] = predBB->id;
buzbee67bf8852011-08-17 17:51:35 -0700842 }
843
Bill Buzbeea114add2012-05-03 15:00:40 -0700844 /* Count the number of SSA registers for a Dalvik register */
845 int numUses = oatCountSetBits(ssaRegV);
846 mir->ssaRep->numUses = numUses;
847 mir->ssaRep->uses =
buzbee2cfc6392012-05-07 14:51:40 -0700848 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
Bill Buzbeea114add2012-05-03 15:00:40 -0700849 mir->ssaRep->fpUse =
buzbee2cfc6392012-05-07 14:51:40 -0700850 (bool*) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
851 int* incoming =
852 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
853 // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
854 mir->dalvikInsn.vB = (intptr_t) incoming;
Bill Buzbeea114add2012-05-03 15:00:40 -0700855
856 ArenaBitVectorIterator phiIterator;
857
858 oatBitVectorIteratorInit(ssaRegV, &phiIterator);
859 int *usePtr = mir->ssaRep->uses;
860
861 /* Set the uses array for the phi node */
862 while (true) {
863 int ssaRegIdx = oatBitVectorIteratorNext(&phiIterator);
864 if (ssaRegIdx == -1) break;
865 *usePtr++ = ssaRegIdx;
buzbee2cfc6392012-05-07 14:51:40 -0700866 *incoming++ = cUnit->tempSSABlockIdV[ssaRegIdx];
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 }
868 }
869
870 return true;
buzbee67bf8852011-08-17 17:51:35 -0700871}
872
buzbee31a4a6f2012-02-28 15:36:15 -0800873void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700874{
875
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 if (block->visited || block->hidden) return;
877 block->visited = true;
buzbeef0cde542011-09-13 14:55:02 -0700878
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 /* Process this block */
880 oatDoSSAConversion(cUnit, block);
881 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700882
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 /* Save SSA map snapshot */
884 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
885 kAllocDalvikToSSAMap);
886 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700887
Bill Buzbeea114add2012-05-03 15:00:40 -0700888 if (block->fallThrough) {
889 doDFSPreOrderSSARename(cUnit, block->fallThrough);
890 /* Restore SSA map snapshot */
891 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
892 }
893 if (block->taken) {
894 doDFSPreOrderSSARename(cUnit, block->taken);
895 /* Restore SSA map snapshot */
896 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
897 }
898 if (block->successorBlockList.blockListType != kNotUsed) {
899 GrowableListIterator iterator;
900 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
901 &iterator);
902 while (true) {
903 SuccessorBlockInfo *successorBlockInfo =
904 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
905 if (successorBlockInfo == NULL) break;
906 BasicBlock* succBB = successorBlockInfo->block;
907 doDFSPreOrderSSARename(cUnit, succBB);
908 /* Restore SSA map snapshot */
909 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700910 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700911 }
912 cUnit->vRegToSSAMap = savedSSAMap;
913 return;
buzbeef0cde542011-09-13 14:55:02 -0700914}
915
buzbee67bf8852011-08-17 17:51:35 -0700916/* Perform SSA transformation for the whole method */
917void oatMethodSSATransformation(CompilationUnit* cUnit)
918{
Bill Buzbeea114add2012-05-03 15:00:40 -0700919 /* Compute the DFS order */
920 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700921
Bill Buzbeea114add2012-05-03 15:00:40 -0700922 if (!cUnit->disableDataflow) {
923 /* Compute the dominator info */
924 computeDominators(cUnit);
925 }
buzbee67bf8852011-08-17 17:51:35 -0700926
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 /* Allocate data structures in preparation for SSA conversion */
928 oatInitializeSSAConversion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700929
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 if (!cUnit->disableDataflow) {
931 /* Find out the "Dalvik reg def x block" relation */
932 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700933
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 /* Insert phi nodes to dominance frontiers for all variables */
935 insertPhiNodes(cUnit);
936 }
buzbee67bf8852011-08-17 17:51:35 -0700937
Bill Buzbeea114add2012-05-03 15:00:40 -0700938 /* Rename register names by local defs and phi nodes */
939 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
940 kAllNodes, false /* isIterative */);
941 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700942
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 if (!cUnit->disableDataflow) {
944 /*
945 * Shared temp bit vector used by each block to count the number of defs
946 * from all the predecessor blocks.
947 */
948 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
949 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700950
buzbee2cfc6392012-05-07 14:51:40 -0700951 cUnit->tempSSABlockIdV =
952 (int*)oatNew(cUnit, sizeof(int) * cUnit->numSSARegs, false,
953 kAllocDFInfo);
954
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 /* Insert phi-operands with latest SSA names from predecessor blocks */
956 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
957 kReachableNodes, false /* isIterative */);
958 }
buzbee67bf8852011-08-17 17:51:35 -0700959}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800960
961} // namespace art