blob: 7d6a733277da2081e066a11355e21da083050931 [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);
buzbeee5f01222012-06-14 15:19:35 -0700209 LOG(INFO) << "New dfs";
210 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
211 LOG(INFO) << i << " - " << cUnit->dfsOrder.elemList[i];
212 }
213 LOG(INFO) << "Recursive dfs";
214 for (unsigned int i = 0; i < recursiveDfsOrder.numUsed; i++) {
215 LOG(INFO) << i << " - " << recursiveDfsOrder.elemList[i];
216 }
217 LOG(INFO) << "New post dfs";
218 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
219 LOG(INFO) << i << " - " << cUnit->dfsPostOrder.elemList[i];
220 }
221 LOG(INFO) << "Recursive post dfs";
222 for (unsigned int i = 0; i < recursiveDfsPostOrder.numUsed; i++) {
223 LOG(INFO) << i << " - " << recursiveDfsPostOrder.elemList[i];
224 }
225 }
226 CHECK_EQ(cUnit->dfsOrder.numUsed, recursiveDfsOrder.numUsed);
227 for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
228 CHECK_EQ(cUnit->dfsOrder.elemList[i], recursiveDfsOrder.elemList[i]);
229 }
230 CHECK_EQ(cUnit->dfsPostOrder.numUsed, recursiveDfsPostOrder.numUsed);
231 for (unsigned int i = 0; i < cUnit->dfsPostOrder.numUsed; i++) {
232 CHECK_EQ(cUnit->dfsPostOrder.elemList[i],
233 recursiveDfsPostOrder.elemList[i]);
234 }
235#endif
236
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700238}
239
240/*
241 * Mark block bit on the per-Dalvik register vector to denote that Dalvik
242 * register idx is defined in BasicBlock bb.
243 */
buzbee31a4a6f2012-02-28 15:36:15 -0800244bool fillDefBlockMatrix(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700245{
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -0700247
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700249
Bill Buzbeea114add2012-05-03 15:00:40 -0700250 oatBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
251 while (true) {
252 int idx = oatBitVectorIteratorNext(&iterator);
253 if (idx == -1) break;
254 /* Block bb defines register idx */
255 oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
256 }
257 return true;
buzbee67bf8852011-08-17 17:51:35 -0700258}
259
buzbee31a4a6f2012-02-28 15:36:15 -0800260void computeDefBlockMatrix(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700261{
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 int numRegisters = cUnit->numDalvikRegisters;
263 /* Allocate numDalvikRegisters bit vector pointers */
264 cUnit->defBlockMatrix = (ArenaBitVector **)
265 oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
266 kAllocDFInfo);
267 int i;
buzbee67bf8852011-08-17 17:51:35 -0700268
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 /* Initialize numRegister vectors with numBlocks bits each */
270 for (i = 0; i < numRegisters; i++) {
271 cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
272 false, kBitMapBMatrix);
273 }
274 oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
275 kAllNodes, false /* isIterative */);
276 oatDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
277 kAllNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700278
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 /*
280 * Also set the incoming parameters as defs in the entry block.
281 * Only need to handle the parameters for the outer method.
282 */
283 int numRegs = cUnit->numDalvikRegisters;
284 int inReg = numRegs - cUnit->numIns;
285 for (; inReg < numRegs; inReg++) {
286 oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
287 }
buzbee67bf8852011-08-17 17:51:35 -0700288}
289
290/* Compute the post-order traversal of the CFG */
buzbee31a4a6f2012-02-28 15:36:15 -0800291void computeDomPostOrderTraversal(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700292{
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 ArenaBitVectorIterator bvIterator;
294 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
295 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700296
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 /* Iterate through the dominated blocks first */
298 while (true) {
299 //TUNING: hot call to oatBitVectorIteratorNext
300 int bbIdx = oatBitVectorIteratorNext(&bvIterator);
301 if (bbIdx == -1) break;
302 BasicBlock* dominatedBB =
303 (BasicBlock* ) oatGrowableListGetElement(blockList, bbIdx);
304 computeDomPostOrderTraversal(cUnit, dominatedBB);
305 }
buzbee67bf8852011-08-17 17:51:35 -0700306
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 /* Enter the current block id */
308 oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
buzbee67bf8852011-08-17 17:51:35 -0700309
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 /* hacky loop detection */
311 if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
312 cUnit->hasLoop = true;
313 }
buzbee67bf8852011-08-17 17:51:35 -0700314}
315
buzbee31a4a6f2012-02-28 15:36:15 -0800316void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 const BasicBlock* succBB)
buzbee67bf8852011-08-17 17:51:35 -0700318{
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 /*
320 * TODO - evaluate whether phi will ever need to be inserted into exit
321 * blocks.
322 */
323 if (succBB->iDom != domBB &&
324 succBB->blockType == kDalvikByteCode &&
325 succBB->hidden == false) {
326 oatSetBit(cUnit, domBB->domFrontier, succBB->id);
327 }
buzbee67bf8852011-08-17 17:51:35 -0700328}
329
330/* Worker function to compute the dominance frontier */
buzbee31a4a6f2012-02-28 15:36:15 -0800331bool computeDominanceFrontier(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700332{
Bill Buzbeea114add2012-05-03 15:00:40 -0700333 GrowableList* blockList = &cUnit->blockList;
buzbee67bf8852011-08-17 17:51:35 -0700334
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 /* Calculate DF_local */
336 if (bb->taken) {
337 checkForDominanceFrontier(cUnit, bb, bb->taken);
338 }
339 if (bb->fallThrough) {
340 checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
341 }
342 if (bb->successorBlockList.blockListType != kNotUsed) {
343 GrowableListIterator iterator;
344 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
345 &iterator);
346 while (true) {
347 SuccessorBlockInfo *successorBlockInfo =
348 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
349 if (successorBlockInfo == NULL) break;
350 BasicBlock* succBB = successorBlockInfo->block;
351 checkForDominanceFrontier(cUnit, bb, succBB);
352 }
353 }
buzbee67bf8852011-08-17 17:51:35 -0700354
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 /* Calculate DF_up */
356 ArenaBitVectorIterator bvIterator;
357 oatBitVectorIteratorInit(bb->iDominated, &bvIterator);
358 while (true) {
359 //TUNING: hot call to oatBitVectorIteratorNext
360 int dominatedIdx = oatBitVectorIteratorNext(&bvIterator);
361 if (dominatedIdx == -1) break;
362 BasicBlock* dominatedBB = (BasicBlock* )
363 oatGrowableListGetElement(blockList, dominatedIdx);
364 ArenaBitVectorIterator dfIterator;
365 oatBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
buzbee67bf8852011-08-17 17:51:35 -0700366 while (true) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 //TUNING: hot call to oatBitVectorIteratorNext
368 int dfUpIdx = oatBitVectorIteratorNext(&dfIterator);
369 if (dfUpIdx == -1) break;
370 BasicBlock* dfUpBlock = (BasicBlock* )
371 oatGrowableListGetElement(blockList, dfUpIdx);
372 checkForDominanceFrontier(cUnit, bb, dfUpBlock);
buzbee67bf8852011-08-17 17:51:35 -0700373 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700374 }
buzbee67bf8852011-08-17 17:51:35 -0700375
Bill Buzbeea114add2012-05-03 15:00:40 -0700376 return true;
buzbee67bf8852011-08-17 17:51:35 -0700377}
378
379/* Worker function for initializing domination-related data structures */
buzbee31a4a6f2012-02-28 15:36:15 -0800380bool initializeDominationInfo(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700381{
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700383
Bill Buzbeea114add2012-05-03 15:00:40 -0700384 if (bb->dominators == NULL ) {
385 bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
386 false /* expandable */,
387 kBitMapDominators);
388 bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
389 false /* expandable */,
390 kBitMapIDominated);
391 bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
392 false /* expandable */,
393 kBitMapDomFrontier);
394 } else {
395 oatClearAllBits(bb->dominators);
396 oatClearAllBits(bb->iDominated);
397 oatClearAllBits(bb->domFrontier);
398 }
399 /* Set all bits in the dominator vector */
400 oatSetInitialBits(bb->dominators, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700401
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 return true;
buzbee67bf8852011-08-17 17:51:35 -0700403}
404
buzbee5b537102012-01-17 17:33:47 -0800405/*
406 * Worker function to compute each block's dominators. This implementation
407 * is only used when kDebugVerifyDataflow is active and should compute
408 * the same dominator sets as computeBlockDominators.
409 */
buzbee31a4a6f2012-02-28 15:36:15 -0800410bool slowComputeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700411{
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 GrowableList* blockList = &cUnit->blockList;
413 int numTotalBlocks = blockList->numUsed;
414 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
415 GrowableListIterator iter;
buzbee67bf8852011-08-17 17:51:35 -0700416
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 /*
418 * The dominator of the entry block has been preset to itself and we need
419 * to skip the calculation here.
420 */
421 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700422
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 oatSetInitialBits(tempBlockV, numTotalBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700424
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 /* Iterate through the predecessors */
426 oatGrowableListIteratorInit(bb->predecessors, &iter);
427 while (true) {
428 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
429 if (!predBB) break;
430 /* tempBlockV = tempBlockV ^ dominators */
431 if (predBB->dominators != NULL) {
432 oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
buzbee67bf8852011-08-17 17:51:35 -0700433 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 }
435 oatSetBit(cUnit, tempBlockV, bb->id);
436 if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
437 oatCopyBitVector(bb->dominators, tempBlockV);
438 return true;
439 }
440 return false;
buzbee67bf8852011-08-17 17:51:35 -0700441}
442
buzbee5b537102012-01-17 17:33:47 -0800443/*
444 * Worker function to compute the idom. This implementation is only
445 * used when kDebugVerifyDataflow is active and should compute the
446 * same iDom as computeBlockIDom.
447 */
buzbee31a4a6f2012-02-28 15:36:15 -0800448bool slowComputeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700449{
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 GrowableList* blockList = &cUnit->blockList;
451 ArenaBitVector* tempBlockV = cUnit->tempBlockV;
452 ArenaBitVectorIterator bvIterator;
453 BasicBlock* iDom;
buzbee67bf8852011-08-17 17:51:35 -0700454
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 if (bb == cUnit->entryBlock) return false;
buzbee67bf8852011-08-17 17:51:35 -0700456
Bill Buzbeea114add2012-05-03 15:00:40 -0700457 oatCopyBitVector(tempBlockV, bb->dominators);
458 oatClearBit(tempBlockV, bb->id);
459 oatBitVectorIteratorInit(tempBlockV, &bvIterator);
buzbee67bf8852011-08-17 17:51:35 -0700460
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 /* Should not see any dead block */
462 DCHECK_NE(oatCountSetBits(tempBlockV), 0);
463 if (oatCountSetBits(tempBlockV) == 1) {
464 iDom = (BasicBlock* )
465 oatGrowableListGetElement(blockList,
466 oatBitVectorIteratorNext(&bvIterator));
467 bb->iDom = iDom;
468 } else {
469 int iDomIdx = oatBitVectorIteratorNext(&bvIterator);
470 DCHECK_NE(iDomIdx, -1);
471 while (true) {
472 int nextDom = oatBitVectorIteratorNext(&bvIterator);
473 if (nextDom == -1) break;
474 BasicBlock* nextDomBB = (BasicBlock* )
475 oatGrowableListGetElement(blockList, nextDom);
476 /* iDom dominates nextDom - set new iDom */
477 if (oatIsBitSet(nextDomBB->dominators, iDomIdx)) {
478 iDomIdx = nextDom;
479 }
buzbee67bf8852011-08-17 17:51:35 -0700480
buzbee67bf8852011-08-17 17:51:35 -0700481 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 iDom = (BasicBlock* ) oatGrowableListGetElement(blockList, iDomIdx);
483 /* Set the immediate dominator block for bb */
484 bb->iDom = iDom;
485 }
486 /* Add bb to the iDominated set of the immediate dominator block */
487 oatSetBit(cUnit, iDom->iDominated, bb->id);
488 return true;
buzbee67bf8852011-08-17 17:51:35 -0700489}
490
buzbee5b537102012-01-17 17:33:47 -0800491/*
492 * Walk through the ordered iDom list until we reach common parent.
493 * Given the ordering of iDomList, this common parent represents the
494 * last element of the intersection of block1 and block2 dominators.
495 */
496int findCommonParent(CompilationUnit *cUnit, int block1, int block2)
497{
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 while (block1 != block2) {
499 while (block1 < block2) {
500 block1 = cUnit->iDomList[block1];
501 DCHECK_NE(block1, NOTVISITED);
buzbee5b537102012-01-17 17:33:47 -0800502 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 while (block2 < block1) {
504 block2 = cUnit->iDomList[block2];
505 DCHECK_NE(block2, NOTVISITED);
506 }
507 }
508 return block1;
buzbee5b537102012-01-17 17:33:47 -0800509}
510
511/* Worker function to compute each block's immediate dominator */
buzbee31a4a6f2012-02-28 15:36:15 -0800512bool computeBlockIDom(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800513{
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 GrowableListIterator iter;
515 int idom = -1;
buzbee5b537102012-01-17 17:33:47 -0800516
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 /* Special-case entry block */
518 if (bb == cUnit->entryBlock) {
buzbee5b537102012-01-17 17:33:47 -0800519 return false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 }
521
522 /* Iterate through the predecessors */
523 oatGrowableListIteratorInit(bb->predecessors, &iter);
524
525 /* Find the first processed predecessor */
526 while (true) {
527 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
528 CHECK(predBB != NULL);
529 if (cUnit->iDomList[predBB->dfsId] != NOTVISITED) {
530 idom = predBB->dfsId;
531 break;
532 }
533 }
534
535 /* Scan the rest of the predecessors */
536 while (true) {
537 BasicBlock* predBB = (BasicBlock*)oatGrowableListIteratorNext(&iter);
538 if (!predBB) break;
539 if (cUnit->iDomList[predBB->dfsId] == NOTVISITED) {
540 continue;
541 } else {
542 idom = findCommonParent(cUnit, predBB->dfsId, idom);
543 }
544 }
545
546 DCHECK_NE(idom, NOTVISITED);
547
548 /* Did something change? */
549 if (cUnit->iDomList[bb->dfsId] != idom) {
550 cUnit->iDomList[bb->dfsId] = idom;
551 return true;
552 }
553 return false;
buzbee5b537102012-01-17 17:33:47 -0800554}
555
556/* Worker function to compute each block's domintors */
buzbee31a4a6f2012-02-28 15:36:15 -0800557bool computeBlockDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800558{
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 if (bb == cUnit->entryBlock) {
560 oatClearAllBits(bb->dominators);
561 } else {
562 oatCopyBitVector(bb->dominators, bb->iDom->dominators);
563 }
564 oatSetBit(cUnit, bb->dominators, bb->id);
565 return false;
buzbee5b537102012-01-17 17:33:47 -0800566}
567
buzbee31a4a6f2012-02-28 15:36:15 -0800568bool setDominators(CompilationUnit* cUnit, BasicBlock* bb)
buzbee5b537102012-01-17 17:33:47 -0800569{
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 if (bb != cUnit->entryBlock) {
571 int iDomDFSIdx = cUnit->iDomList[bb->dfsId];
572 DCHECK_NE(iDomDFSIdx, NOTVISITED);
573 int iDomIdx = cUnit->dfsPostOrder.elemList[iDomDFSIdx];
574 BasicBlock* iDom = (BasicBlock*)
575 oatGrowableListGetElement(&cUnit->blockList, iDomIdx);
576 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
577 DCHECK_EQ(bb->iDom->id, iDom->id);
buzbee5b537102012-01-17 17:33:47 -0800578 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700579 bb->iDom = iDom;
580 /* Add bb to the iDominated set of the immediate dominator block */
581 oatSetBit(cUnit, iDom->iDominated, bb->id);
582 }
583 return false;
buzbee5b537102012-01-17 17:33:47 -0800584}
585
buzbee67bf8852011-08-17 17:51:35 -0700586/* Compute dominators, immediate dominator, and dominance fronter */
buzbee31a4a6f2012-02-28 15:36:15 -0800587void computeDominators(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700588{
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 int numReachableBlocks = cUnit->numReachableBlocks;
590 int numTotalBlocks = cUnit->blockList.numUsed;
buzbee67bf8852011-08-17 17:51:35 -0700591
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 /* Initialize domination-related data structures */
593 oatDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
594 kReachableNodes, false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700595
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 /* Initalize & Clear iDomList */
597 if (cUnit->iDomList == NULL) {
598 cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
599 false, kAllocDFInfo);
600 }
601 for (int i = 0; i < numReachableBlocks; i++) {
602 cUnit->iDomList[i] = NOTVISITED;
603 }
buzbee5b537102012-01-17 17:33:47 -0800604
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 /* For post-order, last block is entry block. Set its iDom to istelf */
606 DCHECK_EQ(cUnit->entryBlock->dfsId, numReachableBlocks-1);
607 cUnit->iDomList[cUnit->entryBlock->dfsId] = cUnit->entryBlock->dfsId;
buzbee5b537102012-01-17 17:33:47 -0800608
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 /* Compute the immediate dominators */
610 oatDataFlowAnalysisDispatcher(cUnit, computeBlockIDom,
611 kReversePostOrderTraversal,
612 true /* isIterative */);
613
614 /* Set the dominator for the root node */
615 oatClearAllBits(cUnit->entryBlock->dominators);
616 oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
617
618 if (cUnit->tempBlockV == NULL) {
619 cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
620 false /* expandable */,
621 kBitMapTmpBlockV);
622 } else {
623 oatClearAllBits(cUnit->tempBlockV);
624 }
625 cUnit->entryBlock->iDom = NULL;
626
627 /* For testing, compute sets using alternate mechanism */
628 if (cUnit->enableDebug & (1 << kDebugVerifyDataflow)) {
629 // Use alternate mechanism to compute dominators for comparison
630 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockDominators,
631 kPreOrderDFSTraversal,
buzbee5b537102012-01-17 17:33:47 -0800632 true /* isIterative */);
633
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 oatDataFlowAnalysisDispatcher(cUnit, slowComputeBlockIDom,
635 kReachableNodes,
636 false /* isIterative */);
637 }
buzbee67bf8852011-08-17 17:51:35 -0700638
Bill Buzbeea114add2012-05-03 15:00:40 -0700639 oatDataFlowAnalysisDispatcher(cUnit, setDominators,
640 kReachableNodes,
641 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800642
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 oatDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
644 kReversePostOrderTraversal,
645 false /* isIterative */);
buzbee5b537102012-01-17 17:33:47 -0800646
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 /*
648 * Now go ahead and compute the post order traversal based on the
649 * iDominated sets.
650 */
651 if (cUnit->domPostOrderTraversal.elemList == NULL) {
652 oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
653 numReachableBlocks, kListDomPostOrderTraversal);
654 } else {
655 cUnit->domPostOrderTraversal.numUsed = 0;
656 }
buzbee5b537102012-01-17 17:33:47 -0800657
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
659 DCHECK_EQ(cUnit->domPostOrderTraversal.numUsed,
660 (unsigned) cUnit->numReachableBlocks);
buzbee5b537102012-01-17 17:33:47 -0800661
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 /* Now compute the dominance frontier for each block */
663 oatDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
664 kPostOrderDOMTraversal,
665 false /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700666}
667
668/*
669 * Perform dest U= src1 ^ ~src2
670 * This is probably not general enough to be placed in BitVector.[ch].
671 */
buzbee31a4a6f2012-02-28 15:36:15 -0800672void computeSuccLiveIn(ArenaBitVector* dest,
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 const ArenaBitVector* src1,
674 const ArenaBitVector* src2)
buzbee67bf8852011-08-17 17:51:35 -0700675{
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 if (dest->storageSize != src1->storageSize ||
677 dest->storageSize != src2->storageSize ||
678 dest->expandable != src1->expandable ||
679 dest->expandable != src2->expandable) {
680 LOG(FATAL) << "Incompatible set properties";
681 }
buzbee67bf8852011-08-17 17:51:35 -0700682
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 unsigned int idx;
684 for (idx = 0; idx < dest->storageSize; idx++) {
685 dest->storage[idx] |= src1->storage[idx] & ~src2->storage[idx];
686 }
buzbee67bf8852011-08-17 17:51:35 -0700687}
688
689/*
690 * Iterate through all successor blocks and propagate up the live-in sets.
691 * The calculated result is used for phi-node pruning - where we only need to
692 * insert a phi node if the variable is live-in to the block.
693 */
buzbee31a4a6f2012-02-28 15:36:15 -0800694bool computeBlockLiveIns(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700695{
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 ArenaBitVector* tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
buzbee67bf8852011-08-17 17:51:35 -0700697
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 if (bb->dataFlowInfo == NULL) return false;
699 oatCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
700 if (bb->taken && bb->taken->dataFlowInfo)
701 computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
702 bb->dataFlowInfo->defV);
703 if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
704 computeSuccLiveIn(tempDalvikRegisterV,
705 bb->fallThrough->dataFlowInfo->liveInV,
706 bb->dataFlowInfo->defV);
707 if (bb->successorBlockList.blockListType != kNotUsed) {
708 GrowableListIterator iterator;
709 oatGrowableListIteratorInit(&bb->successorBlockList.blocks,
710 &iterator);
711 while (true) {
712 SuccessorBlockInfo *successorBlockInfo =
713 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
714 if (successorBlockInfo == NULL) break;
715 BasicBlock* succBB = successorBlockInfo->block;
716 if (succBB->dataFlowInfo) {
buzbee67bf8852011-08-17 17:51:35 -0700717 computeSuccLiveIn(tempDalvikRegisterV,
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 succBB->dataFlowInfo->liveInV,
buzbee67bf8852011-08-17 17:51:35 -0700719 bb->dataFlowInfo->defV);
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 }
buzbee67bf8852011-08-17 17:51:35 -0700721 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700722 }
723 if (oatCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
724 oatCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
725 return true;
726 }
727 return false;
buzbee67bf8852011-08-17 17:51:35 -0700728}
729
730/* Insert phi nodes to for each variable to the dominance frontiers */
buzbee31a4a6f2012-02-28 15:36:15 -0800731void insertPhiNodes(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700732{
Bill Buzbeea114add2012-05-03 15:00:40 -0700733 int dalvikReg;
734 const GrowableList* blockList = &cUnit->blockList;
735 ArenaBitVector* phiBlocks =
736 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
737 ArenaBitVector* tmpBlocks =
738 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
739 ArenaBitVector* inputBlocks =
740 oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700741
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 cUnit->tempDalvikRegisterV =
743 oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
744 kBitMapRegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700745
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
747 kPostOrderDFSTraversal, true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700748
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 /* Iterate through each Dalvik register */
750 for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
751 bool change;
752 ArenaBitVectorIterator iterator;
buzbee67bf8852011-08-17 17:51:35 -0700753
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 oatCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
755 oatClearAllBits(phiBlocks);
buzbee67bf8852011-08-17 17:51:35 -0700756
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 /* Calculate the phi blocks for each Dalvik register */
758 do {
759 change = false;
760 oatClearAllBits(tmpBlocks);
761 oatBitVectorIteratorInit(inputBlocks, &iterator);
buzbee67bf8852011-08-17 17:51:35 -0700762
Bill Buzbeea114add2012-05-03 15:00:40 -0700763 while (true) {
764 int idx = oatBitVectorIteratorNext(&iterator);
765 if (idx == -1) break;
766 BasicBlock* defBB =
767 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
buzbee67bf8852011-08-17 17:51:35 -0700768
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 /* Merge the dominance frontier to tmpBlocks */
770 //TUNING: hot call to oatUnifyBitVectors
771 if (defBB->domFrontier != NULL) {
772 oatUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
773 }
buzbee67bf8852011-08-17 17:51:35 -0700774 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 if (oatCompareBitVectors(phiBlocks, tmpBlocks)) {
776 change = true;
777 oatCopyBitVector(phiBlocks, tmpBlocks);
778
779 /*
780 * Iterate through the original blocks plus the new ones in
781 * the dominance frontier.
782 */
783 oatCopyBitVector(inputBlocks, phiBlocks);
784 oatUnifyBitVectors(inputBlocks, inputBlocks,
785 cUnit->defBlockMatrix[dalvikReg]);
786 }
787 } while (change);
788
789 /*
790 * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
791 * register is in the live-in set.
792 */
793 oatBitVectorIteratorInit(phiBlocks, &iterator);
794 while (true) {
795 int idx = oatBitVectorIteratorNext(&iterator);
796 if (idx == -1) break;
797 BasicBlock* phiBB =
798 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
799 /* Variable will be clobbered before being used - no need for phi */
800 if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
801 MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
802 phi->dalvikInsn.opcode = (Instruction::Code)kMirOpPhi;
803 phi->dalvikInsn.vA = dalvikReg;
804 phi->offset = phiBB->startOffset;
805 phi->meta.phiNext = cUnit->phiList;
806 cUnit->phiList = phi;
807 oatPrependMIR(phiBB, phi);
buzbee67bf8852011-08-17 17:51:35 -0700808 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 }
buzbee67bf8852011-08-17 17:51:35 -0700810}
811
812/*
813 * Worker function to insert phi-operands with latest SSA names from
814 * predecessor blocks
815 */
buzbee31a4a6f2012-02-28 15:36:15 -0800816bool insertPhiNodeOperands(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -0700817{
Bill Buzbeea114add2012-05-03 15:00:40 -0700818 GrowableListIterator iter;
819 MIR *mir;
buzbee6969d502012-06-15 16:40:31 -0700820 std::vector<int> uses;
821 std::vector<int> incomingArc;
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
buzbee6969d502012-06-15 16:40:31 -0700831 uses.clear();
832 incomingArc.clear();
buzbee67bf8852011-08-17 17:51:35 -0700833
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 /* Iterate through the predecessors */
835 oatGrowableListIteratorInit(bb->predecessors, &iter);
836 while (true) {
837 BasicBlock* predBB =
838 (BasicBlock*)oatGrowableListIteratorNext(&iter);
839 if (!predBB) break;
840 int ssaReg = predBB->dataFlowInfo->vRegToSSAMap[vReg];
buzbee6969d502012-06-15 16:40:31 -0700841 uses.push_back(ssaReg);
842 incomingArc.push_back(predBB->id);
buzbee67bf8852011-08-17 17:51:35 -0700843 }
844
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 /* Count the number of SSA registers for a Dalvik register */
buzbee6969d502012-06-15 16:40:31 -0700846 int numUses = uses.size();
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 mir->ssaRep->numUses = numUses;
848 mir->ssaRep->uses =
buzbee2cfc6392012-05-07 14:51:40 -0700849 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
Bill Buzbeea114add2012-05-03 15:00:40 -0700850 mir->ssaRep->fpUse =
buzbee2cfc6392012-05-07 14:51:40 -0700851 (bool*) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
852 int* incoming =
853 (int*) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
854 // TODO: Ugly, rework (but don't burden each MIR/LIR for Phi-only needs)
855 mir->dalvikInsn.vB = (intptr_t) incoming;
Bill Buzbeea114add2012-05-03 15:00:40 -0700856
Bill Buzbeea114add2012-05-03 15:00:40 -0700857 /* Set the uses array for the phi node */
buzbee6969d502012-06-15 16:40:31 -0700858 int *usePtr = mir->ssaRep->uses;
859 for (int i = 0; i < numUses; i++) {
860 *usePtr++ = uses[i];
861 *incoming++ = incomingArc[i];
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 }
863 }
864
865 return true;
buzbee67bf8852011-08-17 17:51:35 -0700866}
867
buzbee31a4a6f2012-02-28 15:36:15 -0800868void doDFSPreOrderSSARename(CompilationUnit* cUnit, BasicBlock* block)
buzbeef0cde542011-09-13 14:55:02 -0700869{
870
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 if (block->visited || block->hidden) return;
872 block->visited = true;
buzbeef0cde542011-09-13 14:55:02 -0700873
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 /* Process this block */
875 oatDoSSAConversion(cUnit, block);
876 int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
buzbeef0cde542011-09-13 14:55:02 -0700877
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 /* Save SSA map snapshot */
879 int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
880 kAllocDalvikToSSAMap);
881 memcpy(savedSSAMap, cUnit->vRegToSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700882
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 if (block->fallThrough) {
884 doDFSPreOrderSSARename(cUnit, block->fallThrough);
885 /* Restore SSA map snapshot */
886 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
887 }
888 if (block->taken) {
889 doDFSPreOrderSSARename(cUnit, block->taken);
890 /* Restore SSA map snapshot */
891 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
892 }
893 if (block->successorBlockList.blockListType != kNotUsed) {
894 GrowableListIterator iterator;
895 oatGrowableListIteratorInit(&block->successorBlockList.blocks,
896 &iterator);
897 while (true) {
898 SuccessorBlockInfo *successorBlockInfo =
899 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
900 if (successorBlockInfo == NULL) break;
901 BasicBlock* succBB = successorBlockInfo->block;
902 doDFSPreOrderSSARename(cUnit, succBB);
903 /* Restore SSA map snapshot */
904 memcpy(cUnit->vRegToSSAMap, savedSSAMap, mapSize);
buzbeef0cde542011-09-13 14:55:02 -0700905 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 }
907 cUnit->vRegToSSAMap = savedSSAMap;
908 return;
buzbeef0cde542011-09-13 14:55:02 -0700909}
910
buzbee67bf8852011-08-17 17:51:35 -0700911/* Perform SSA transformation for the whole method */
912void oatMethodSSATransformation(CompilationUnit* cUnit)
913{
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 /* Compute the DFS order */
915 computeDFSOrders(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700916
Bill Buzbeea114add2012-05-03 15:00:40 -0700917 if (!cUnit->disableDataflow) {
918 /* Compute the dominator info */
919 computeDominators(cUnit);
920 }
buzbee67bf8852011-08-17 17:51:35 -0700921
Bill Buzbeea114add2012-05-03 15:00:40 -0700922 /* Allocate data structures in preparation for SSA conversion */
923 oatInitializeSSAConversion(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700924
Bill Buzbeea114add2012-05-03 15:00:40 -0700925 if (!cUnit->disableDataflow) {
926 /* Find out the "Dalvik reg def x block" relation */
927 computeDefBlockMatrix(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700928
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 /* Insert phi nodes to dominance frontiers for all variables */
930 insertPhiNodes(cUnit);
931 }
buzbee67bf8852011-08-17 17:51:35 -0700932
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 /* Rename register names by local defs and phi nodes */
934 oatDataFlowAnalysisDispatcher(cUnit, oatClearVisitedFlag,
935 kAllNodes, false /* isIterative */);
936 doDFSPreOrderSSARename(cUnit, cUnit->entryBlock);
buzbee67bf8852011-08-17 17:51:35 -0700937
Bill Buzbeea114add2012-05-03 15:00:40 -0700938 if (!cUnit->disableDataflow) {
939 /*
940 * Shared temp bit vector used by each block to count the number of defs
941 * from all the predecessor blocks.
942 */
943 cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
944 false, kBitMapTempSSARegisterV);
buzbee67bf8852011-08-17 17:51:35 -0700945
buzbee2cfc6392012-05-07 14:51:40 -0700946 cUnit->tempSSABlockIdV =
947 (int*)oatNew(cUnit, sizeof(int) * cUnit->numSSARegs, false,
948 kAllocDFInfo);
949
Bill Buzbeea114add2012-05-03 15:00:40 -0700950 /* Insert phi-operands with latest SSA names from predecessor blocks */
951 oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
952 kReachableNodes, false /* isIterative */);
953 }
buzbee67bf8852011-08-17 17:51:35 -0700954}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800955
956} // namespace art