Mercurial > hg > truffle
comparison graal/GraalCompiler/src/com/sun/c1x/ir/ComputeLinearScanOrder.java @ 2778:2ac7b30b7290
Enabled new block finding algorithm.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Tue, 24 May 2011 21:39:45 +0200 |
parents | 27512ea6bbcb |
children | df4c5254c5cc |
comparison
equal
deleted
inserted
replaced
2777:3e4d992fd312 | 2778:2ac7b30b7290 |
---|---|
25 | 25 |
26 import java.util.*; | 26 import java.util.*; |
27 | 27 |
28 import com.sun.c1x.*; | 28 import com.sun.c1x.*; |
29 import com.sun.c1x.debug.*; | 29 import com.sun.c1x.debug.*; |
30 import com.sun.c1x.lir.*; | |
30 import com.sun.c1x.util.*; | 31 import com.sun.c1x.util.*; |
31 import com.sun.cri.ci.*; | 32 import com.sun.cri.ci.*; |
32 | 33 |
33 public final class ComputeLinearScanOrder { | 34 public final class ComputeLinearScanOrder { |
34 | 35 |
35 private final int maxBlockId; // the highest blockId of a block | 36 private final int maxBlockId; // the highest blockId of a block |
36 private int numBlocks; // total number of blocks (smaller than maxBlockId) | 37 private int numBlocks; // total number of blocks (smaller than maxBlockId) |
37 private int numLoops; // total number of loops | 38 private int numLoops; // total number of loops |
38 | 39 private boolean iterativeDominators; // method requires iterative computation of dominators |
39 List<BlockBegin> linearScanOrder; // the resulting list of blocks in correct order | 40 |
41 List<LIRBlock> linearScanOrder; // the resulting list of blocks in correct order | |
40 | 42 |
41 final CiBitMap visitedBlocks; // used for recursive processing of blocks | 43 final CiBitMap visitedBlocks; // used for recursive processing of blocks |
42 final CiBitMap activeBlocks; // used for recursive processing of blocks | 44 final CiBitMap activeBlocks; // used for recursive processing of blocks |
45 final CiBitMap dominatorBlocks; // temporary BitMap used for computation of dominator | |
43 final int[] forwardBranches; // number of incoming forward branches for each block | 46 final int[] forwardBranches; // number of incoming forward branches for each block |
44 final List<BlockBegin> loopEndBlocks; // list of all loop end blocks collected during countEdges | 47 final List<LIRBlock> loopEndBlocks; // list of all loop end blocks collected during countEdges |
45 BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop | 48 BitMap2D loopMap; // two-dimensional bit set: a bit is set if a block is contained in a loop |
46 final List<BlockBegin> workList; // temporary list (used in markLoops and computeOrder) | 49 final List<LIRBlock> workList; // temporary list (used in markLoops and computeOrder) |
47 | 50 |
48 // accessors for visitedBlocks and activeBlocks | 51 // accessors for visitedBlocks and activeBlocks |
49 private void initVisited() { | 52 void initVisited() { |
50 activeBlocks.clearAll(); | 53 activeBlocks.clearAll(); |
51 visitedBlocks.clearAll(); | 54 visitedBlocks.clearAll(); |
52 } | 55 } |
53 | 56 |
54 private boolean isVisited(BlockBegin b) { | 57 boolean isVisited(LIRBlock b) { |
55 return visitedBlocks.get(b.blockID); | 58 return visitedBlocks.get(b.blockID()); |
56 } | 59 } |
57 | 60 |
58 private boolean isActive(BlockBegin b) { | 61 boolean isActive(LIRBlock b) { |
59 return activeBlocks.get(b.blockID); | 62 return activeBlocks.get(b.blockID()); |
60 } | 63 } |
61 | 64 |
62 private void setVisited(BlockBegin b) { | 65 void setVisited(LIRBlock b) { |
63 assert !isVisited(b) : "already set"; | 66 assert !isVisited(b) : "already set"; |
64 visitedBlocks.set(b.blockID); | 67 visitedBlocks.set(b.blockID()); |
65 } | 68 } |
66 | 69 |
67 private void setActive(BlockBegin b) { | 70 void setActive(LIRBlock b) { |
68 assert !isActive(b) : "already set"; | 71 assert !isActive(b) : "already set"; |
69 activeBlocks.set(b.blockID); | 72 activeBlocks.set(b.blockID()); |
70 } | 73 } |
71 | 74 |
72 private void clearActive(BlockBegin b) { | 75 void clearActive(LIRBlock b) { |
73 assert isActive(b) : "not already"; | 76 assert isActive(b) : "not already"; |
74 activeBlocks.clear(b.blockID); | 77 activeBlocks.clear(b.blockID()); |
75 } | 78 } |
76 | 79 |
77 // accessors for forwardBranches | 80 // accessors for forwardBranches |
78 private void incForwardBranches(BlockBegin b) { | 81 void incForwardBranches(LIRBlock b) { |
79 forwardBranches[b.blockID]++; | 82 forwardBranches[b.blockID()]++; |
80 } | 83 } |
81 | 84 |
82 private int decForwardBranches(BlockBegin b) { | 85 int decForwardBranches(LIRBlock b) { |
83 return --forwardBranches[b.blockID]; | 86 return --forwardBranches[b.blockID()]; |
84 } | 87 } |
85 | 88 |
86 // accessors for loopMap | 89 // accessors for loopMap |
87 private boolean isBlockInLoop(int loopIdx, BlockBegin b) { | 90 boolean isBlockInLoop(int loopIdx, LIRBlock b) { |
88 return loopMap.at(loopIdx, b.blockID); | 91 return loopMap.at(loopIdx, b.blockID()); |
89 } | 92 } |
90 | 93 |
91 private void setBlockInLoop(int loopIdx, BlockBegin b) { | 94 void setBlockInLoop(int loopIdx, LIRBlock b) { |
92 loopMap.setBit(loopIdx, b.blockID); | 95 loopMap.setBit(loopIdx, b.blockID()); |
93 } | 96 } |
94 | 97 |
95 private void clearBlockInLoop(int loopIdx, int blockId) { | 98 void clearBlockInLoop(int loopIdx, int blockId) { |
96 loopMap.clearBit(loopIdx, blockId); | 99 loopMap.clearBit(loopIdx, blockId); |
97 } | 100 } |
98 | 101 |
99 // accessors for final result | 102 // accessors for final result |
100 public List<BlockBegin> linearScanOrder() { | 103 public List<LIRBlock> linearScanOrder() { |
101 return linearScanOrder; | 104 return linearScanOrder; |
102 } | 105 } |
103 | 106 |
104 public int numLoops() { | 107 public int numLoops() { |
105 return numLoops; | 108 return numLoops; |
106 } | 109 } |
107 | 110 |
108 public ComputeLinearScanOrder(int maxBlockId, BlockBegin startBlock) { | 111 public ComputeLinearScanOrder(int maxBlockId, LIRBlock startBlock) { |
109 | 112 |
110 this.maxBlockId = maxBlockId; | 113 this.maxBlockId = maxBlockId; |
111 visitedBlocks = new CiBitMap(maxBlockId); | 114 visitedBlocks = new CiBitMap(maxBlockId); |
112 activeBlocks = new CiBitMap(maxBlockId); | 115 activeBlocks = new CiBitMap(maxBlockId); |
116 dominatorBlocks = new CiBitMap(maxBlockId); | |
113 forwardBranches = new int[maxBlockId]; | 117 forwardBranches = new int[maxBlockId]; |
114 loopEndBlocks = new ArrayList<BlockBegin>(8); | 118 loopEndBlocks = new ArrayList<LIRBlock>(8); |
115 workList = new ArrayList<BlockBegin>(8); | 119 workList = new ArrayList<LIRBlock>(8); |
120 | |
121 splitCriticalEdges(); | |
116 | 122 |
117 countEdges(startBlock, null); | 123 countEdges(startBlock, null); |
118 | 124 |
125 if (numLoops > 0) { | |
126 markLoops(); | |
127 clearNonNaturalLoops(startBlock); | |
128 assignLoopDepth(startBlock); | |
129 } | |
130 | |
119 computeOrder(startBlock); | 131 computeOrder(startBlock); |
132 | |
133 printBlocks(); | |
134 assert verify(); | |
135 } | |
136 | |
137 void splitCriticalEdges() { | |
138 // TODO: move critical edge splitting from IR to here | |
120 } | 139 } |
121 | 140 |
122 /** | 141 /** |
123 * Traverses the CFG to analyze block and edge info. The analysis performed is: | 142 * Traverses the CFG to analyze block and edge info. The analysis performed is: |
124 * | 143 * |
125 * 1. Count of total number of blocks. | 144 * 1. Count of total number of blocks. |
126 * 2. Count of all incoming edges and backward incoming edges. | 145 * 2. Count of all incoming edges and backward incoming edges. |
127 * 3. Number loop header blocks. | 146 * 3. Number loop header blocks. |
128 * 4. Create a list with all loop end blocks. | 147 * 4. Create a list with all loop end blocks. |
129 */ | 148 */ |
130 private void countEdges(final BlockBegin cur, BlockBegin parent) { | 149 void countEdges(LIRBlock cur, LIRBlock parent) { |
131 if (C1XOptions.TraceLinearScanLevel >= 3) { | 150 if (C1XOptions.TraceLinearScanLevel >= 3) { |
132 TTY.println("Counting edges for block B%d%s", cur.blockID, parent == null ? "" : " coming from B" + parent.blockID); | 151 TTY.println("Counting edges for block B%d%s", cur.blockID(), parent == null ? "" : " coming from B" + parent.blockID()); |
133 } | 152 } |
134 | 153 |
135 if (isActive(cur)) { | 154 if (isActive(cur)) { |
136 if (C1XOptions.TraceLinearScanLevel >= 3) { | 155 if (C1XOptions.TraceLinearScanLevel >= 3) { |
137 TTY.println("backward branch"); | 156 TTY.println("backward branch"); |
138 } | 157 } |
139 assert isVisited(cur) : "block must be visited when block is active"; | 158 assert isVisited(cur) : "block must be visited when block is active"; |
140 assert parent != null : "must have parent"; | 159 assert parent != null : "must have parent"; |
141 | 160 |
142 //cur.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader); | 161 cur.setLinearScanLoopHeader(); |
143 | 162 cur.setBackwardBranchTarget(true); |
144 //parent.setBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd); | 163 parent.setLinearScanLoopEnd(); |
164 | |
165 // When a loop header is also the start of an exception handler, then the backward branch is | |
166 // an exception edge. Because such edges are usually critical edges which cannot be split, the | |
167 // loop must be excluded here from processing. | |
168 if (cur.isExceptionEntry()) { | |
169 // Make sure that dominators are correct in this weird situation | |
170 iterativeDominators = true; | |
171 return; | |
172 } | |
173 // assert parent.numberOfSux() == 1 && parent.suxAt(0) == cur : "loop end blocks must have one successor (critical edges are split)"; | |
145 | 174 |
146 loopEndBlocks.add(parent); | 175 loopEndBlocks.add(parent); |
147 return; | 176 return; |
148 } | 177 } |
149 | 178 |
160 numBlocks++; | 189 numBlocks++; |
161 setVisited(cur); | 190 setVisited(cur); |
162 setActive(cur); | 191 setActive(cur); |
163 | 192 |
164 // recursive call for all successors | 193 // recursive call for all successors |
165 cur.allSuccessorsDo(true, new BlockClosure() { | 194 int i; |
166 public void apply(BlockBegin block) { | 195 for (i = cur.numberOfSux() - 1; i >= 0; i--) { |
167 countEdges(block, cur); | 196 countEdges(cur.suxAt(i), cur); |
168 } | 197 } |
169 }); | 198 for (LIRBlock ex : cur.getExceptionHandlerSuccessors()) { |
199 countEdges(ex, cur); | |
200 } | |
170 | 201 |
171 clearActive(cur); | 202 clearActive(cur); |
172 | 203 |
204 // Each loop has a unique number. | |
205 // When multiple loops are nested, assignLoopDepth assumes that the | |
206 // innermost loop has the lowest number. This is guaranteed by setting | |
207 // the loop number after the recursive calls for the successors above | |
208 // have returned. | |
209 if (cur.isLinearScanLoopHeader()) { | |
210 assert cur.loopIndex() == -1 : "cannot set loop-index twice"; | |
211 if (C1XOptions.TraceLinearScanLevel >= 3) { | |
212 TTY.println("Block B%d is loop header of loop %d", cur.blockID(), numLoops); | |
213 } | |
214 | |
215 cur.setLoopIndex(numLoops); | |
216 numLoops++; | |
217 } | |
218 | |
173 if (C1XOptions.TraceLinearScanLevel >= 3) { | 219 if (C1XOptions.TraceLinearScanLevel >= 3) { |
174 TTY.println("Finished counting edges for block B%d", cur.blockID); | 220 TTY.println("Finished counting edges for block B%d", cur.blockID()); |
175 } | 221 } |
176 } | 222 } |
177 | 223 |
178 private int computeWeight(BlockBegin cur) { | 224 void markLoops() { |
179 BlockBegin singleSux = null; | 225 if (C1XOptions.TraceLinearScanLevel >= 3) { |
180 BlockEnd end = cur.end(); | 226 TTY.println("----- marking loops"); |
181 if (end.blockSuccessorCount() == 1) { | 227 } |
182 singleSux = end.blockSuccessor(0); | 228 |
229 loopMap = new BitMap2D(numLoops, maxBlockId); | |
230 | |
231 for (int i = loopEndBlocks.size() - 1; i >= 0; i--) { | |
232 LIRBlock loopEnd = loopEndBlocks.get(i); | |
233 LIRBlock loopStart = loopEnd.suxAt(0); | |
234 int loopIdx = loopStart.loopIndex(); | |
235 | |
236 if (C1XOptions.TraceLinearScanLevel >= 3) { | |
237 TTY.println("Processing loop from B%d to B%d (loop %d):", loopStart.blockID(), loopEnd.blockID(), loopIdx); | |
238 } | |
239 assert loopEnd.isLinearScanLoopEnd() : "loop end flag must be set"; | |
240 // assert loopEnd.numberOfSux() == 1 : "incorrect number of successors"; | |
241 assert loopStart.isLinearScanLoopHeader() : "loop header flag must be set"; | |
242 assert loopIdx >= 0 && loopIdx < numLoops : "loop index not set"; | |
243 assert workList.isEmpty() : "work list must be empty before processing"; | |
244 | |
245 // add the end-block of the loop to the working list | |
246 workList.add(loopEnd); | |
247 setBlockInLoop(loopIdx, loopEnd); | |
248 do { | |
249 LIRBlock cur = workList.remove(workList.size() - 1); | |
250 | |
251 if (C1XOptions.TraceLinearScanLevel >= 3) { | |
252 TTY.println(" processing B%d", cur.blockID()); | |
253 } | |
254 assert isBlockInLoop(loopIdx, cur) : "bit in loop map must be set when block is in work list"; | |
255 | |
256 // recursive processing of all predecessors ends when start block of loop is reached | |
257 if (cur != loopStart) { | |
258 for (int j = cur.numberOfPreds() - 1; j >= 0; j--) { | |
259 LIRBlock pred = cur.predAt(j); | |
260 | |
261 if (!isBlockInLoop(loopIdx, pred)) { | |
262 // this predecessor has not been processed yet, so add it to work list | |
263 if (C1XOptions.TraceLinearScanLevel >= 3) { | |
264 TTY.println(" pushing B%d", pred.blockID()); | |
265 } | |
266 workList.add(pred); | |
267 setBlockInLoop(loopIdx, pred); | |
268 } | |
269 } | |
270 } | |
271 } while (!workList.isEmpty()); | |
272 } | |
273 } | |
274 | |
275 // check for non-natural loops (loops where the loop header does not dominate | |
276 // all other loop blocks = loops with multiple entries). | |
277 // such loops are ignored | |
278 void clearNonNaturalLoops(LIRBlock startBlock) { | |
279 for (int i = numLoops - 1; i >= 0; i--) { | |
280 if (isBlockInLoop(i, startBlock)) { | |
281 // loop i contains the entry block of the method. | |
282 // this is not a natural loop, so ignore it | |
283 if (C1XOptions.TraceLinearScanLevel >= 2) { | |
284 TTY.println("Loop %d is non-natural, so it is ignored", i); | |
285 } | |
286 | |
287 for (int blockId = maxBlockId - 1; blockId >= 0; blockId--) { | |
288 clearBlockInLoop(i, blockId); | |
289 } | |
290 iterativeDominators = true; | |
291 } | |
292 } | |
293 } | |
294 | |
295 void assignLoopDepth(LIRBlock startBlock) { | |
296 if (C1XOptions.TraceLinearScanLevel >= 3) { | |
297 TTY.println("----- computing loop-depth and weight"); | |
298 } | |
299 initVisited(); | |
300 | |
301 assert workList.isEmpty() : "work list must be empty before processing"; | |
302 workList.add(startBlock); | |
303 | |
304 do { | |
305 LIRBlock cur = workList.remove(workList.size() - 1); | |
306 | |
307 if (!isVisited(cur)) { | |
308 setVisited(cur); | |
309 if (C1XOptions.TraceLinearScanLevel >= 4) { | |
310 TTY.println("Computing loop depth for block B%d", cur.blockID()); | |
311 } | |
312 | |
313 // compute loop-depth and loop-index for the block | |
314 assert cur.loopDepth() == 0 : "cannot set loop-depth twice"; | |
315 int i; | |
316 int loopDepth = 0; | |
317 int minLoopIdx = -1; | |
318 for (i = numLoops - 1; i >= 0; i--) { | |
319 if (isBlockInLoop(i, cur)) { | |
320 loopDepth++; | |
321 minLoopIdx = i; | |
322 } | |
323 } | |
324 cur.setLoopDepth(loopDepth); | |
325 cur.setLoopIndex(minLoopIdx); | |
326 | |
327 // append all unvisited successors to work list | |
328 for (i = cur.numberOfSux() - 1; i >= 0; i--) { | |
329 workList.add(cur.suxAt(i)); | |
330 } | |
331 for (LIRBlock ex : cur.getExceptionHandlerSuccessors()) { | |
332 workList.add(ex); | |
333 } | |
334 } | |
335 } while (!workList.isEmpty()); | |
336 } | |
337 | |
338 int computeWeight(LIRBlock cur) { | |
339 LIRBlock singleSux = null; | |
340 if (cur.numberOfSux() == 1) { | |
341 singleSux = cur.suxAt(0); | |
183 } | 342 } |
184 | 343 |
185 // limit loop-depth to 15 bit (only for security reason, it will never be so big) | 344 // limit loop-depth to 15 bit (only for security reason, it will never be so big) |
186 int loopDepth = 0; // TODO(tw): Assign loop depth | 345 int weight = (cur.loopDepth() & 0x7FFF) << 16; |
187 int weight = (loopDepth & 0x7FFF) << 16; | |
188 | 346 |
189 int curBit = 15; | 347 int curBit = 15; |
348 | |
349 // this is necessary for the (very rare) case that two successive blocks have | |
350 // the same loop depth, but a different loop index (can happen for endless loops | |
351 // with exception handlers) | |
352 if (!cur.isLinearScanLoopHeader()) { | |
353 weight |= 1 << curBit; | |
354 } | |
355 curBit--; | |
356 | |
357 // loop end blocks (blocks that end with a backward branch) are added | |
358 // after all other blocks of the loop. | |
359 if (!cur.isLinearScanLoopEnd()) { | |
360 weight |= 1 << curBit; | |
361 } | |
362 curBit--; | |
363 | |
364 // critical edge split blocks are preferred because then they have a greater | |
365 // probability to be completely empty | |
366 //if (cur.isCriticalEdgeSplit()) { | |
367 // weight |= 1 << curBit; | |
368 //} | |
369 //curBit--; | |
190 | 370 |
191 // exceptions should not be thrown in normal control flow, so these blocks | 371 // exceptions should not be thrown in normal control flow, so these blocks |
192 // are added as late as possible | 372 // are added as late as possible |
193 if (!(cur.end() instanceof Throw) && (singleSux == null || !(singleSux.end() instanceof Throw))) { | 373 // if (!(cur.end() instanceof Throw) && (singleSux == null || !(singleSux.end() instanceof Throw))) { |
194 weight |= (1 << curBit); | 374 // weight |= 1 << curBit; |
195 } | 375 // } |
196 curBit--; | 376 // curBit--; |
197 if (!(cur.end() instanceof Return) && (singleSux == null || !(singleSux.end() instanceof Return))) { | 377 // if (!(cur.end() instanceof Return) && (singleSux == null || !(singleSux.end() instanceof Return))) { |
198 weight |= (1 << curBit); | 378 // weight |= 1 << curBit; |
379 // } | |
380 // curBit--; | |
381 | |
382 // exceptions handlers are added as late as possible | |
383 if (!cur.isExceptionEntry()) { | |
384 weight |= 1 << curBit; | |
199 } | 385 } |
200 curBit--; | 386 curBit--; |
201 | 387 |
202 // guarantee that weight is > 0 | 388 // guarantee that weight is > 0 |
203 weight |= 1; | 389 weight |= 1; |
206 assert weight > 0 : "weight cannot become negative"; | 392 assert weight > 0 : "weight cannot become negative"; |
207 | 393 |
208 return weight; | 394 return weight; |
209 } | 395 } |
210 | 396 |
211 private boolean readyForProcessing(BlockBegin cur) { | 397 boolean readyForProcessing(LIRBlock cur) { |
212 // Discount the edge just traveled. | 398 // Discount the edge just traveled. |
213 // When the number drops to zero, all forward branches were processed | 399 // When the number drops to zero, all forward branches were processed |
214 if (decForwardBranches(cur) != 0) { | 400 if (decForwardBranches(cur) != 0) { |
215 return false; | 401 return false; |
216 } | 402 } |
218 assert !linearScanOrder.contains(cur) : "block already processed (block can be ready only once)"; | 404 assert !linearScanOrder.contains(cur) : "block already processed (block can be ready only once)"; |
219 assert !workList.contains(cur) : "block already in work-list (block can be ready only once)"; | 405 assert !workList.contains(cur) : "block already in work-list (block can be ready only once)"; |
220 return true; | 406 return true; |
221 } | 407 } |
222 | 408 |
223 private void sortIntoWorkList(BlockBegin cur) { | 409 void sortIntoWorkList(LIRBlock cur) { |
224 assert !workList.contains(cur) : "block already in work list"; | 410 assert !workList.contains(cur) : "block already in work list"; |
225 | 411 |
226 int curWeight = computeWeight(cur); | 412 int curWeight = computeWeight(cur); |
227 | 413 |
228 // the linearScanNumber is used to cache the weight of a block | 414 // the linearScanNumber is used to cache the weight of a block |
241 insertIdx--; | 427 insertIdx--; |
242 } | 428 } |
243 workList.set(insertIdx, cur); | 429 workList.set(insertIdx, cur); |
244 | 430 |
245 if (C1XOptions.TraceLinearScanLevel >= 3) { | 431 if (C1XOptions.TraceLinearScanLevel >= 3) { |
246 TTY.println("Sorted B%d into worklist. new worklist:", cur.blockID); | 432 TTY.println("Sorted B%d into worklist. new worklist:", cur.blockID()); |
247 for (int i = 0; i < workList.size(); i++) { | 433 for (int i = 0; i < workList.size(); i++) { |
248 TTY.println(String.format("%8d B%02d weight:%6x", i, workList.get(i).blockID, workList.get(i).linearScanNumber())); | 434 TTY.println(String.format("%8d B%02d weight:%6x", i, workList.get(i).blockID(), workList.get(i).linearScanNumber())); |
249 } | 435 } |
250 } | 436 } |
251 | 437 |
252 for (int i = 0; i < workList.size(); i++) { | 438 for (int i = 0; i < workList.size(); i++) { |
253 assert workList.get(i).linearScanNumber() > 0 : "weight not set"; | 439 assert workList.get(i).linearScanNumber() > 0 : "weight not set"; |
254 assert i == 0 || workList.get(i - 1).linearScanNumber() <= workList.get(i).linearScanNumber() : "incorrect order in worklist"; | 440 assert i == 0 || workList.get(i - 1).linearScanNumber() <= workList.get(i).linearScanNumber() : "incorrect order in worklist"; |
255 } | 441 } |
256 } | 442 } |
257 | 443 |
258 private void appendBlock(BlockBegin cur) { | 444 void appendBlock(LIRBlock cur) { |
259 if (C1XOptions.TraceLinearScanLevel >= 3) { | 445 if (C1XOptions.TraceLinearScanLevel >= 3) { |
260 TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID, cur.linearScanNumber()); | 446 TTY.println("appending block B%d (weight 0x%06x) to linear-scan order", cur.blockID(), cur.linearScanNumber()); |
261 } | 447 } |
262 assert !linearScanOrder.contains(cur) : "cannot add the same block twice"; | 448 assert !linearScanOrder.contains(cur) : "cannot add the same block twice"; |
263 | 449 |
264 // currently, the linear scan order and code emit order are equal. | 450 // currently, the linear scan order and code emit order are equal. |
265 // therefore the linearScanNumber and the weight of a block must also | 451 // therefore the linearScanNumber and the weight of a block must also |
266 // be equal. | 452 // be equal. |
267 cur.setLinearScanNumber(linearScanOrder.size()); | 453 cur.setLinearScanNumber(linearScanOrder.size()); |
268 linearScanOrder.add(cur); | 454 linearScanOrder.add(cur); |
269 } | 455 } |
270 | 456 |
271 private void computeOrder(BlockBegin startBlock) { | 457 void computeOrder(LIRBlock startBlock) { |
272 if (C1XOptions.TraceLinearScanLevel >= 3) { | 458 if (C1XOptions.TraceLinearScanLevel >= 3) { |
273 TTY.println("----- computing final block order"); | 459 TTY.println("----- computing final block order"); |
274 } | 460 } |
275 | 461 |
276 // the start block is always the first block in the linear scan order | 462 // the start block is always the first block in the linear scan order |
277 linearScanOrder = new ArrayList<BlockBegin>(numBlocks); | 463 linearScanOrder = new ArrayList<LIRBlock>(numBlocks); |
464 appendBlock(startBlock); | |
465 | |
466 LIRBlock stdEntry = startBlock.suxAt(0); | |
278 | 467 |
279 // start processing with standard entry block | 468 // start processing with standard entry block |
280 assert workList.isEmpty() : "list must be empty before processing"; | 469 assert workList.isEmpty() : "list must be empty before processing"; |
281 | 470 |
282 if (readyForProcessing(startBlock)) { | 471 if (readyForProcessing(stdEntry)) { |
283 sortIntoWorkList(startBlock); | 472 sortIntoWorkList(stdEntry); |
284 } else { | 473 } else { |
285 throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)"); | 474 throw new CiBailout("the stdEntry must be ready for processing (otherwise, the method has no start block)"); |
286 } | 475 } |
287 | 476 |
288 do { | 477 do { |
289 final BlockBegin cur = workList.remove(workList.size() - 1); | 478 LIRBlock cur = workList.remove(workList.size() - 1); |
479 | |
290 appendBlock(cur); | 480 appendBlock(cur); |
291 | 481 |
292 cur.allSuccessorsDo(false, new BlockClosure() { | 482 int i; |
293 public void apply(BlockBegin block) { | 483 int numSux = cur.numberOfSux(); |
294 if (readyForProcessing(block)) { | 484 // changed loop order to get "intuitive" order of if- and else-blocks |
295 sortIntoWorkList(block); | 485 for (i = 0; i < numSux; i++) { |
486 LIRBlock sux = cur.suxAt(i); | |
487 if (readyForProcessing(sux)) { | |
488 sortIntoWorkList(sux); | |
489 } | |
490 } | |
491 for (LIRBlock ex : cur.getExceptionHandlerSuccessors()) { | |
492 if (readyForProcessing(ex)) { | |
493 sortIntoWorkList(ex); | |
494 } | |
495 } | |
496 } while (workList.size() > 0); | |
497 } | |
498 | |
499 public void printBlocks() { | |
500 if (C1XOptions.TraceLinearScanLevel >= 2) { | |
501 TTY.println("----- loop information:"); | |
502 for (LIRBlock cur : linearScanOrder) { | |
503 TTY.print(String.format("%4d: B%02d: ", cur.linearScanNumber(), cur.blockID())); | |
504 for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { | |
505 TTY.print(String.format("%d = %b ", loopIdx, isBlockInLoop(loopIdx, cur))); | |
506 } | |
507 TTY.println(String.format(" . loopIndex: %2d, loopDepth: %2d", cur.loopIndex(), cur.loopDepth())); | |
508 } | |
509 } | |
510 | |
511 if (C1XOptions.TraceLinearScanLevel >= 1) { | |
512 TTY.println("----- linear-scan block order:"); | |
513 for (LIRBlock cur : linearScanOrder) { | |
514 TTY.print(String.format("%4d: B%02d loop: %2d depth: %2d", cur.linearScanNumber(), cur.blockID(), cur.loopIndex(), cur.loopDepth())); | |
515 | |
516 TTY.print(cur.isExceptionEntry() ? " ex" : " "); | |
517 TTY.print(cur.isLinearScanLoopHeader() ? " lh" : " "); | |
518 TTY.print(cur.isLinearScanLoopEnd() ? " le" : " "); | |
519 | |
520 TTY.print(" dom: null "); | |
521 | |
522 | |
523 if (cur.numberOfPreds() > 0) { | |
524 TTY.print(" preds: "); | |
525 for (int j = 0; j < cur.numberOfPreds(); j++) { | |
526 LIRBlock pred = cur.predAt(j); | |
527 TTY.print("B%d ", pred.blockID()); | |
296 } | 528 } |
297 } | 529 } |
298 }); | 530 if (cur.numberOfSux() > 0) { |
299 } while (workList.size() > 0); | 531 TTY.print(" sux: "); |
532 for (int j = 0; j < cur.numberOfSux(); j++) { | |
533 LIRBlock sux = cur.suxAt(j); | |
534 TTY.print("B%d ", sux.blockID()); | |
535 } | |
536 } | |
537 TTY.println(); | |
538 } | |
539 } | |
540 } | |
541 | |
542 boolean verify() { | |
543 /* assert linearScanOrder.size() == numBlocks : "wrong number of blocks in list"; | |
544 | |
545 if (C1XOptions.StressLinearScan) { | |
546 // blocks are scrambled when StressLinearScan is used | |
547 return true; | |
548 } | |
549 | |
550 // check that all successors of a block have a higher linear-scan-number | |
551 // and that all predecessors of a block have a lower linear-scan-number | |
552 // (only backward branches of loops are ignored) | |
553 int i; | |
554 for (i = 0; i < linearScanOrder.size(); i++) { | |
555 BlockBegin cur = linearScanOrder.get(i); | |
556 | |
557 assert cur.linearScanNumber() == i : "incorrect linearScanNumber"; | |
558 assert cur.linearScanNumber() >= 0 && cur.linearScanNumber() == linearScanOrder.indexOf(cur) : "incorrect linearScanNumber"; | |
559 | |
560 for (BlockBegin sux : cur.end().successors()) { | |
561 assert sux.linearScanNumber() >= 0 && sux.linearScanNumber() == linearScanOrder.indexOf(sux) : "incorrect linearScanNumber"; | |
562 if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopEnd)) { | |
563 assert cur.linearScanNumber() < sux.linearScanNumber() : "invalid order"; | |
564 } | |
565 if (cur.loopDepth() == sux.loopDepth()) { | |
566 assert cur.loopIndex() == sux.loopIndex() || sux.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; | |
567 } | |
568 } | |
569 | |
570 for (BlockBegin pred : cur.predecessors()) { | |
571 assert pred.linearScanNumber() >= 0 && pred.linearScanNumber() == linearScanOrder.indexOf(pred) : "incorrect linearScanNumber"; | |
572 if (!cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader)) { | |
573 assert cur.linearScanNumber() > pred.linearScanNumber() : "invalid order"; | |
574 } | |
575 if (cur.loopDepth() == pred.loopDepth()) { | |
576 assert cur.loopIndex() == pred.loopIndex() || cur.checkBlockFlag(BlockBegin.BlockFlag.LinearScanLoopHeader) : "successing blocks with same loop depth must have same loop index"; | |
577 } | |
578 | |
579 assert cur.dominator().linearScanNumber() <= pred.linearScanNumber() : "dominator must be before predecessors"; | |
580 } | |
581 | |
582 // check dominator | |
583 if (i == 0) { | |
584 assert cur.dominator() == null : "first block has no dominator"; | |
585 } else { | |
586 assert cur.dominator() != null : "all but first block must have dominator"; | |
587 } | |
588 assert cur.numberOfPreds() != 1 || cur.dominator() == cur.predAt(0) || cur.isExceptionEntry() : "Single predecessor must also be dominator"; | |
589 } | |
590 | |
591 // check that all loops are continuous | |
592 for (int loopIdx = 0; loopIdx < numLoops; loopIdx++) { | |
593 int blockIdx = 0; | |
594 assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "the first block must not be present in any loop"; | |
595 | |
596 // skip blocks before the loop | |
597 while (blockIdx < numBlocks && !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { | |
598 blockIdx++; | |
599 } | |
600 // skip blocks of loop | |
601 while (blockIdx < numBlocks && isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx))) { | |
602 blockIdx++; | |
603 } | |
604 // after the first non-loop block : there must not be another loop-block | |
605 while (blockIdx < numBlocks) { | |
606 assert !isBlockInLoop(loopIdx, linearScanOrder.get(blockIdx)) : "loop not continuous in linear-scan order"; | |
607 blockIdx++; | |
608 } | |
609 } | |
610 */ | |
611 return true; | |
300 } | 612 } |
301 } | 613 } |