Mercurial > hg > truffle
comparison graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java @ 19560:4d70d150944f
Remove AbstractBlock interface.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Mon, 23 Feb 2015 18:37:20 +0100 |
parents | 95a7954ea155 |
children | a33fe10c4d93 |
comparison
equal
deleted
inserted
replaced
19559:08d94d9f0b0f | 19560:4d70d150944f |
---|---|
112 final BlockMap<BlockData> blockData; | 112 final BlockMap<BlockData> blockData; |
113 | 113 |
114 /** | 114 /** |
115 * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. | 115 * List of blocks in linear-scan order. This is only correct as long as the CFG does not change. |
116 */ | 116 */ |
117 final List<? extends AbstractBlock<?>> sortedBlocks; | 117 final List<? extends AbstractBlockBase<?>> sortedBlocks; |
118 | 118 |
119 /** | 119 /** |
120 * Map from {@linkplain #operandNumber(Value) operand numbers} to intervals. | 120 * Map from {@linkplain #operandNumber(Value) operand numbers} to intervals. |
121 */ | 121 */ |
122 Interval[] intervals; | 122 Interval[] intervals; |
143 * array. | 143 * array. |
144 */ | 144 */ |
145 LIRInstruction[] opIdToInstructionMap; | 145 LIRInstruction[] opIdToInstructionMap; |
146 | 146 |
147 /** | 147 /** |
148 * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain AbstractBlock | 148 * Map from an instruction {@linkplain LIRInstruction#id id} to the {@linkplain AbstractBlockBase |
149 * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)} | 149 * block} containing the instruction. Entries should be retrieved with {@link #blockForId(int)} |
150 * as the id is not simply an index into this array. | 150 * as the id is not simply an index into this array. |
151 */ | 151 */ |
152 AbstractBlock<?>[] opIdToBlockMap; | 152 AbstractBlockBase<?>[] opIdToBlockMap; |
153 | 153 |
154 /** | 154 /** |
155 * Bit set for each variable that is contained in each loop. | 155 * Bit set for each variable that is contained in each loop. |
156 */ | 156 */ |
157 BitMap2D intervalInLoop; | 157 BitMap2D intervalInLoop; |
176 // If all allocatable registers are caller saved, then no registers are live across a call | 176 // If all allocatable registers are caller saved, then no registers are live across a call |
177 // site. The register allocator can save time not trying to find a register at a call site. | 177 // site. The register allocator can save time not trying to find a register at a call site. |
178 this.callKillsRegisters = this.frameMapBuilder.getRegisterConfig().areAllAllocatableRegistersCallerSaved(); | 178 this.callKillsRegisters = this.frameMapBuilder.getRegisterConfig().areAllAllocatableRegistersCallerSaved(); |
179 } | 179 } |
180 | 180 |
181 int getFirstLirInstructionId(AbstractBlock<?> block) { | 181 int getFirstLirInstructionId(AbstractBlockBase<?> block) { |
182 int result = ir.getLIRforBlock(block).get(0).id(); | 182 int result = ir.getLIRforBlock(block).get(0).id(); |
183 assert result >= 0; | 183 assert result >= 0; |
184 return result; | 184 return result; |
185 } | 185 } |
186 | 186 |
187 int getLastLirInstructionId(AbstractBlock<?> block) { | 187 int getLastLirInstructionId(AbstractBlockBase<?> block) { |
188 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 188 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
189 int result = instructions.get(instructions.size() - 1).id(); | 189 int result = instructions.get(instructions.size() - 1).id(); |
190 assert result >= 0; | 190 assert result >= 0; |
191 return result; | 191 return result; |
192 } | 192 } |
310 // access to block list (sorted in linear scan order) | 310 // access to block list (sorted in linear scan order) |
311 int blockCount() { | 311 int blockCount() { |
312 return sortedBlocks.size(); | 312 return sortedBlocks.size(); |
313 } | 313 } |
314 | 314 |
315 AbstractBlock<?> blockAt(int index) { | 315 AbstractBlockBase<?> blockAt(int index) { |
316 return sortedBlocks.get(index); | 316 return sortedBlocks.get(index); |
317 } | 317 } |
318 | 318 |
319 /** | 319 /** |
320 * Gets the size of the {@link BlockData#liveIn} and {@link BlockData#liveOut} sets for a basic | 320 * Gets the size of the {@link BlockData#liveIn} and {@link BlockData#liveOut} sets for a basic |
386 * Gets the block containing a given instruction. | 386 * Gets the block containing a given instruction. |
387 * | 387 * |
388 * @param opId an instruction {@linkplain LIRInstruction#id id} | 388 * @param opId an instruction {@linkplain LIRInstruction#id id} |
389 * @return the block containing the instruction denoted by {@code opId} | 389 * @return the block containing the instruction denoted by {@code opId} |
390 */ | 390 */ |
391 AbstractBlock<?> blockForId(int opId) { | 391 AbstractBlockBase<?> blockForId(int opId) { |
392 assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range"; | 392 assert opIdToBlockMap.length > 0 && opId >= 0 && opId <= maxOpId() + 1 : "opId out of range"; |
393 return opIdToBlockMap[opIdToIndex(opId)]; | 393 return opIdToBlockMap[opIdToIndex(opId)]; |
394 } | 394 } |
395 | 395 |
396 boolean isBlockBegin(int opId) { | 396 boolean isBlockBegin(int opId) { |
520 if (DetailedAsserts.getValue()) { | 520 if (DetailedAsserts.getValue()) { |
521 checkIntervals(interval); | 521 checkIntervals(interval); |
522 } | 522 } |
523 | 523 |
524 LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); | 524 LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); |
525 for (AbstractBlock<?> block : sortedBlocks) { | 525 for (AbstractBlockBase<?> block : sortedBlocks) { |
526 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 526 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
527 int numInst = instructions.size(); | 527 int numInst = instructions.size(); |
528 | 528 |
529 // iterate all instructions of the block. skip the first | 529 // iterate all instructions of the block. skip the first |
530 // because it is always a label | 530 // because it is always a label |
625 } | 625 } |
626 }; | 626 }; |
627 | 627 |
628 // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node. | 628 // Assign IDs to LIR nodes and build a mapping, lirOps, from ID to LIRInstruction node. |
629 int numInstructions = 0; | 629 int numInstructions = 0; |
630 for (AbstractBlock<?> block : sortedBlocks) { | 630 for (AbstractBlockBase<?> block : sortedBlocks) { |
631 numInstructions += ir.getLIRforBlock(block).size(); | 631 numInstructions += ir.getLIRforBlock(block).size(); |
632 } | 632 } |
633 | 633 |
634 // initialize with correct length | 634 // initialize with correct length |
635 opIdToInstructionMap = new LIRInstruction[numInstructions]; | 635 opIdToInstructionMap = new LIRInstruction[numInstructions]; |
636 opIdToBlockMap = new AbstractBlock<?>[numInstructions]; | 636 opIdToBlockMap = new AbstractBlockBase<?>[numInstructions]; |
637 | 637 |
638 int opId = 0; | 638 int opId = 0; |
639 int index = 0; | 639 int index = 0; |
640 for (AbstractBlock<?> block : sortedBlocks) { | 640 for (AbstractBlockBase<?> block : sortedBlocks) { |
641 blockData.put(block, new BlockData()); | 641 blockData.put(block, new BlockData()); |
642 | 642 |
643 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 643 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
644 | 644 |
645 int numInst = instructions.size(); | 645 int numInst = instructions.size(); |
670 int liveSize = liveSetSize(); | 670 int liveSize = liveSetSize(); |
671 | 671 |
672 intervalInLoop = new BitMap2D(operandSize(), numLoops()); | 672 intervalInLoop = new BitMap2D(operandSize(), numLoops()); |
673 | 673 |
674 // iterate all blocks | 674 // iterate all blocks |
675 for (final AbstractBlock<?> block : sortedBlocks) { | 675 for (final AbstractBlockBase<?> block : sortedBlocks) { |
676 try (Indent indent = Debug.logAndIndent("compute local live sets for block %d", block.getId())) { | 676 try (Indent indent = Debug.logAndIndent("compute local live sets for block %d", block.getId())) { |
677 | 677 |
678 final BitSet liveGen = new BitSet(liveSize); | 678 final BitSet liveGen = new BitSet(liveSize); |
679 final BitSet liveKill = new BitSet(liveSize); | 679 final BitSet liveKill = new BitSet(liveSize); |
680 | 680 |
761 liveKill.set(operandNumber(operand)); | 761 liveKill.set(operandNumber(operand)); |
762 } | 762 } |
763 } | 763 } |
764 } | 764 } |
765 | 765 |
766 private void verifyInput(AbstractBlock<?> block, BitSet liveKill, Value operand) { | 766 private void verifyInput(AbstractBlockBase<?> block, BitSet liveKill, Value operand) { |
767 // fixed intervals are never live at block boundaries, so | 767 // fixed intervals are never live at block boundaries, so |
768 // they need not be processed in live sets. | 768 // they need not be processed in live sets. |
769 // this is checked by these assertions to be sure about it. | 769 // this is checked by these assertions to be sure about it. |
770 // the entry block may have incoming | 770 // the entry block may have incoming |
771 // values in registers, which is ok. | 771 // values in registers, which is ok. |
795 | 795 |
796 try (Indent indent2 = Debug.logAndIndent("new iteration %d", iterationCount)) { | 796 try (Indent indent2 = Debug.logAndIndent("new iteration %d", iterationCount)) { |
797 | 797 |
798 // iterate all blocks in reverse order | 798 // iterate all blocks in reverse order |
799 for (int i = numBlocks - 1; i >= 0; i--) { | 799 for (int i = numBlocks - 1; i >= 0; i--) { |
800 AbstractBlock<?> block = blockAt(i); | 800 AbstractBlockBase<?> block = blockAt(i); |
801 BlockData blockSets = blockData.get(block); | 801 BlockData blockSets = blockData.get(block); |
802 | 802 |
803 changeOccurredInBlock = false; | 803 changeOccurredInBlock = false; |
804 | 804 |
805 // liveOut(block) is the union of liveIn(sux), for successors sux of block | 805 // liveOut(block) is the union of liveIn(sux), for successors sux of block |
806 int n = block.getSuccessorCount(); | 806 int n = block.getSuccessorCount(); |
807 if (n > 0) { | 807 if (n > 0) { |
808 liveOut.clear(); | 808 liveOut.clear(); |
809 // block has successors | 809 // block has successors |
810 if (n > 0) { | 810 if (n > 0) { |
811 for (AbstractBlock<?> successor : block.getSuccessors()) { | 811 for (AbstractBlockBase<?> successor : block.getSuccessors()) { |
812 liveOut.or(blockData.get(successor).liveIn); | 812 liveOut.or(blockData.get(successor).liveIn); |
813 } | 813 } |
814 } | 814 } |
815 | 815 |
816 if (!blockSets.liveOut.equals(liveOut)) { | 816 if (!blockSets.liveOut.equals(liveOut)) { |
850 if (DetailedAsserts.getValue()) { | 850 if (DetailedAsserts.getValue()) { |
851 verifyLiveness(); | 851 verifyLiveness(); |
852 } | 852 } |
853 | 853 |
854 // check that the liveIn set of the first block is empty | 854 // check that the liveIn set of the first block is empty |
855 AbstractBlock<?> startBlock = ir.getControlFlowGraph().getStartBlock(); | 855 AbstractBlockBase<?> startBlock = ir.getControlFlowGraph().getStartBlock(); |
856 if (blockData.get(startBlock).liveIn.cardinality() != 0) { | 856 if (blockData.get(startBlock).liveIn.cardinality() != 0) { |
857 if (DetailedAsserts.getValue()) { | 857 if (DetailedAsserts.getValue()) { |
858 reportFailure(numBlocks); | 858 reportFailure(numBlocks); |
859 } | 859 } |
860 // bailout if this occurs in product mode. | 860 // bailout if this occurs in product mode. |
889 operand = interval.operand; | 889 operand = interval.operand; |
890 valueForOperandFromDebugContext = getSourceForOperandFromDebugContext(operand); | 890 valueForOperandFromDebugContext = getSourceForOperandFromDebugContext(operand); |
891 } | 891 } |
892 try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { | 892 try (Indent indent2 = Debug.logAndIndent("---- Detailed information for var %d; operand=%s; node=%s ----", operandNum, operand, valueForOperandFromDebugContext)) { |
893 | 893 |
894 Deque<AbstractBlock<?>> definedIn = new ArrayDeque<>(); | 894 Deque<AbstractBlockBase<?>> definedIn = new ArrayDeque<>(); |
895 HashSet<AbstractBlock<?>> usedIn = new HashSet<>(); | 895 HashSet<AbstractBlockBase<?>> usedIn = new HashSet<>(); |
896 for (AbstractBlock<?> block : sortedBlocks) { | 896 for (AbstractBlockBase<?> block : sortedBlocks) { |
897 if (blockData.get(block).liveGen.get(operandNum)) { | 897 if (blockData.get(block).liveGen.get(operandNum)) { |
898 usedIn.add(block); | 898 usedIn.add(block); |
899 try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) { | 899 try (Indent indent3 = Debug.logAndIndent("used in block B%d", block.getId())) { |
900 for (LIRInstruction ins : ir.getLIRforBlock(block)) { | 900 for (LIRInstruction ins : ir.getLIRforBlock(block)) { |
901 try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) { | 901 try (Indent indent4 = Debug.logAndIndent("%d: %s", ins.id(), ins)) { |
918 } | 918 } |
919 | 919 |
920 int[] hitCount = new int[numBlocks]; | 920 int[] hitCount = new int[numBlocks]; |
921 | 921 |
922 while (!definedIn.isEmpty()) { | 922 while (!definedIn.isEmpty()) { |
923 AbstractBlock<?> block = definedIn.removeFirst(); | 923 AbstractBlockBase<?> block = definedIn.removeFirst(); |
924 usedIn.remove(block); | 924 usedIn.remove(block); |
925 for (AbstractBlock<?> successor : block.getSuccessors()) { | 925 for (AbstractBlockBase<?> successor : block.getSuccessors()) { |
926 if (successor.isLoopHeader()) { | 926 if (successor.isLoopHeader()) { |
927 if (!block.isLoopEnd()) { | 927 if (!block.isLoopEnd()) { |
928 definedIn.add(successor); | 928 definedIn.add(successor); |
929 } | 929 } |
930 } else { | 930 } else { |
933 } | 933 } |
934 } | 934 } |
935 } | 935 } |
936 } | 936 } |
937 try (Indent indent3 = Debug.logAndIndent("**** offending usages are in: ")) { | 937 try (Indent indent3 = Debug.logAndIndent("**** offending usages are in: ")) { |
938 for (AbstractBlock<?> block : usedIn) { | 938 for (AbstractBlockBase<?> block : usedIn) { |
939 Debug.log("B%d", block.getId()); | 939 Debug.log("B%d", block.getId()); |
940 } | 940 } |
941 } | 941 } |
942 } | 942 } |
943 } | 943 } |
948 } | 948 } |
949 | 949 |
950 private void verifyLiveness() { | 950 private void verifyLiveness() { |
951 // check that fixed intervals are not live at block boundaries | 951 // check that fixed intervals are not live at block boundaries |
952 // (live set must be empty at fixed intervals) | 952 // (live set must be empty at fixed intervals) |
953 for (AbstractBlock<?> block : sortedBlocks) { | 953 for (AbstractBlockBase<?> block : sortedBlocks) { |
954 for (int j = 0; j <= maxRegisterNumber(); j++) { | 954 for (int j = 0; j <= maxRegisterNumber(); j++) { |
955 assert !blockData.get(block).liveIn.get(j) : "liveIn set of fixed register must be empty"; | 955 assert !blockData.get(block).liveIn.get(j) : "liveIn set of fixed register must be empty"; |
956 assert !blockData.get(block).liveOut.get(j) : "liveOut set of fixed register must be empty"; | 956 assert !blockData.get(block).liveOut.get(j) : "liveOut set of fixed register must be empty"; |
957 assert !blockData.get(block).liveGen.get(j) : "liveGen set of fixed register must be empty"; | 957 assert !blockData.get(block).liveGen.get(j) : "liveGen set of fixed register must be empty"; |
958 } | 958 } |
1165 Register[] callerSaveRegs = frameMapBuilder.getRegisterConfig().getCallerSaveRegisters(); | 1165 Register[] callerSaveRegs = frameMapBuilder.getRegisterConfig().getCallerSaveRegisters(); |
1166 | 1166 |
1167 // iterate all blocks in reverse order | 1167 // iterate all blocks in reverse order |
1168 for (int i = blockCount() - 1; i >= 0; i--) { | 1168 for (int i = blockCount() - 1; i >= 0; i--) { |
1169 | 1169 |
1170 AbstractBlock<?> block = blockAt(i); | 1170 AbstractBlockBase<?> block = blockAt(i); |
1171 try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) { | 1171 try (Indent indent2 = Debug.logAndIndent("handle block %d", block.getId())) { |
1172 | 1172 |
1173 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 1173 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
1174 final int blockFrom = getFirstLirInstructionId(block); | 1174 final int blockFrom = getFirstLirInstructionId(block); |
1175 int blockTo = getLastLirInstructionId(block); | 1175 int blockTo = getLastLirInstructionId(block); |
1409 } | 1409 } |
1410 | 1410 |
1411 throw new BailoutException("LinearScan: interval is null"); | 1411 throw new BailoutException("LinearScan: interval is null"); |
1412 } | 1412 } |
1413 | 1413 |
1414 Interval intervalAtBlockBegin(AbstractBlock<?> block, int operandNumber) { | 1414 Interval intervalAtBlockBegin(AbstractBlockBase<?> block, int operandNumber) { |
1415 return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); | 1415 return splitChildAtOpId(intervalFor(operandNumber), getFirstLirInstructionId(block), LIRInstruction.OperandMode.DEF); |
1416 } | 1416 } |
1417 | 1417 |
1418 Interval intervalAtBlockEnd(AbstractBlock<?> block, int operandNumber) { | 1418 Interval intervalAtBlockEnd(AbstractBlockBase<?> block, int operandNumber) { |
1419 return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); | 1419 return splitChildAtOpId(intervalFor(operandNumber), getLastLirInstructionId(block) + 1, LIRInstruction.OperandMode.DEF); |
1420 } | 1420 } |
1421 | 1421 |
1422 void resolveCollectMappings(AbstractBlock<?> fromBlock, AbstractBlock<?> toBlock, MoveResolver moveResolver) { | 1422 void resolveCollectMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, MoveResolver moveResolver) { |
1423 assert moveResolver.checkEmpty(); | 1423 assert moveResolver.checkEmpty(); |
1424 | 1424 |
1425 int numOperands = operandSize(); | 1425 int numOperands = operandSize(); |
1426 BitSet liveAtEdge = blockData.get(toBlock).liveIn; | 1426 BitSet liveAtEdge = blockData.get(toBlock).liveIn; |
1427 | 1427 |
1438 moveResolver.addMapping(fromInterval, toInterval); | 1438 moveResolver.addMapping(fromInterval, toInterval); |
1439 } | 1439 } |
1440 } | 1440 } |
1441 } | 1441 } |
1442 | 1442 |
1443 void resolveFindInsertPos(AbstractBlock<?> fromBlock, AbstractBlock<?> toBlock, MoveResolver moveResolver) { | 1443 void resolveFindInsertPos(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, MoveResolver moveResolver) { |
1444 if (fromBlock.getSuccessorCount() <= 1) { | 1444 if (fromBlock.getSuccessorCount() <= 1) { |
1445 Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); | 1445 Debug.log("inserting moves at end of fromBlock B%d", fromBlock.getId()); |
1446 | 1446 |
1447 List<LIRInstruction> instructions = ir.getLIRforBlock(fromBlock); | 1447 List<LIRInstruction> instructions = ir.getLIRforBlock(fromBlock); |
1448 LIRInstruction instr = instructions.get(instructions.size() - 1); | 1448 LIRInstruction instr = instructions.get(instructions.size() - 1); |
1461 | 1461 |
1462 // because the number of predecessor edges matches the number of | 1462 // because the number of predecessor edges matches the number of |
1463 // successor edges, blocks which are reached by switch statements | 1463 // successor edges, blocks which are reached by switch statements |
1464 // may have be more than one predecessor but it will be guaranteed | 1464 // may have be more than one predecessor but it will be guaranteed |
1465 // that all predecessors will be the same. | 1465 // that all predecessors will be the same. |
1466 for (AbstractBlock<?> predecessor : toBlock.getPredecessors()) { | 1466 for (AbstractBlockBase<?> predecessor : toBlock.getPredecessors()) { |
1467 assert fromBlock == predecessor : "all critical edges must be broken"; | 1467 assert fromBlock == predecessor : "all critical edges must be broken"; |
1468 } | 1468 } |
1469 } | 1469 } |
1470 | 1470 |
1471 moveResolver.setInsertPosition(ir.getLIRforBlock(toBlock), 1); | 1471 moveResolver.setInsertPosition(ir.getLIRforBlock(toBlock), 1); |
1482 int numBlocks = blockCount(); | 1482 int numBlocks = blockCount(); |
1483 MoveResolver moveResolver = new MoveResolver(this); | 1483 MoveResolver moveResolver = new MoveResolver(this); |
1484 BitSet blockCompleted = new BitSet(numBlocks); | 1484 BitSet blockCompleted = new BitSet(numBlocks); |
1485 BitSet alreadyResolved = new BitSet(numBlocks); | 1485 BitSet alreadyResolved = new BitSet(numBlocks); |
1486 | 1486 |
1487 for (AbstractBlock<?> block : sortedBlocks) { | 1487 for (AbstractBlockBase<?> block : sortedBlocks) { |
1488 | 1488 |
1489 // check if block has only one predecessor and only one successor | 1489 // check if block has only one predecessor and only one successor |
1490 if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) { | 1490 if (block.getPredecessorCount() == 1 && block.getSuccessorCount() == 1) { |
1491 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 1491 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
1492 assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; | 1492 assert instructions.get(0) instanceof StandardOp.LabelOp : "block must start with label"; |
1493 assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; | 1493 assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block with successor must end with unconditional jump"; |
1494 | 1494 |
1495 // check if block is empty (only label and branch) | 1495 // check if block is empty (only label and branch) |
1496 if (instructions.size() == 2) { | 1496 if (instructions.size() == 2) { |
1497 AbstractBlock<?> pred = block.getPredecessors().iterator().next(); | 1497 AbstractBlockBase<?> pred = block.getPredecessors().iterator().next(); |
1498 AbstractBlock<?> sux = block.getSuccessors().iterator().next(); | 1498 AbstractBlockBase<?> sux = block.getSuccessors().iterator().next(); |
1499 | 1499 |
1500 // prevent optimization of two consecutive blocks | 1500 // prevent optimization of two consecutive blocks |
1501 if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { | 1501 if (!blockCompleted.get(pred.getLinearScanNumber()) && !blockCompleted.get(sux.getLinearScanNumber())) { |
1502 Debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); | 1502 Debug.log(" optimizing empty block B%d (pred: B%d, sux: B%d)", block.getId(), pred.getId(), sux.getId()); |
1503 | 1503 |
1514 } | 1514 } |
1515 } | 1515 } |
1516 } | 1516 } |
1517 } | 1517 } |
1518 | 1518 |
1519 for (AbstractBlock<?> fromBlock : sortedBlocks) { | 1519 for (AbstractBlockBase<?> fromBlock : sortedBlocks) { |
1520 if (!blockCompleted.get(fromBlock.getLinearScanNumber())) { | 1520 if (!blockCompleted.get(fromBlock.getLinearScanNumber())) { |
1521 alreadyResolved.clear(); | 1521 alreadyResolved.clear(); |
1522 alreadyResolved.or(blockCompleted); | 1522 alreadyResolved.or(blockCompleted); |
1523 | 1523 |
1524 for (AbstractBlock<?> toBlock : fromBlock.getSuccessors()) { | 1524 for (AbstractBlockBase<?> toBlock : fromBlock.getSuccessors()) { |
1525 | 1525 |
1526 // check for duplicate edges between the same blocks (can happen with switch | 1526 // check for duplicate edges between the same blocks (can happen with switch |
1527 // blocks) | 1527 // blocks) |
1528 if (!alreadyResolved.get(toBlock.getLinearScanNumber())) { | 1528 if (!alreadyResolved.get(toBlock.getLinearScanNumber())) { |
1529 Debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); | 1529 Debug.log("processing edge between B%d and B%d", fromBlock.getId(), toBlock.getId()); |
1564 Interval interval = intervalFor(operand); | 1564 Interval interval = intervalFor(operand); |
1565 assert interval != null : "interval must exist"; | 1565 assert interval != null : "interval must exist"; |
1566 | 1566 |
1567 if (opId != -1) { | 1567 if (opId != -1) { |
1568 if (DetailedAsserts.getValue()) { | 1568 if (DetailedAsserts.getValue()) { |
1569 AbstractBlock<?> block = blockForId(opId); | 1569 AbstractBlockBase<?> block = blockForId(opId); |
1570 if (block.getSuccessorCount() <= 1 && opId == getLastLirInstructionId(block)) { | 1570 if (block.getSuccessorCount() <= 1 && opId == getLastLirInstructionId(block)) { |
1571 // check if spill moves could have been appended at the end of this block, but | 1571 // check if spill moves could have been appended at the end of this block, but |
1572 // before the branch instruction. So the split child information for this branch | 1572 // before the branch instruction. So the split child information for this branch |
1573 // would | 1573 // would |
1574 // be incorrect. | 1574 // be incorrect. |
1637 if (isVirtualStackSlot(operand)) { | 1637 if (isVirtualStackSlot(operand)) { |
1638 return operand; | 1638 return operand; |
1639 } | 1639 } |
1640 int tempOpId = op.id(); | 1640 int tempOpId = op.id(); |
1641 OperandMode mode = OperandMode.USE; | 1641 OperandMode mode = OperandMode.USE; |
1642 AbstractBlock<?> block = blockForId(tempOpId); | 1642 AbstractBlockBase<?> block = blockForId(tempOpId); |
1643 if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) { | 1643 if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) { |
1644 // generating debug information for the last instruction of a block. | 1644 // generating debug information for the last instruction of a block. |
1645 // if this instruction is a branch, spill moves are inserted before this branch | 1645 // if this instruction is a branch, spill moves are inserted before this branch |
1646 // and so the wrong operand would be returned (spill moves at block boundaries | 1646 // and so the wrong operand would be returned (spill moves at block boundaries |
1647 // are not | 1647 // are not |
1721 } | 1721 } |
1722 } | 1722 } |
1723 | 1723 |
1724 private void assignLocations() { | 1724 private void assignLocations() { |
1725 try (Indent indent = Debug.logAndIndent("assign locations")) { | 1725 try (Indent indent = Debug.logAndIndent("assign locations")) { |
1726 for (AbstractBlock<?> block : sortedBlocks) { | 1726 for (AbstractBlockBase<?> block : sortedBlocks) { |
1727 try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { | 1727 try (Indent indent2 = Debug.logAndIndent("assign locations in block B%d", block.getId())) { |
1728 assignLocations(ir.getLIRforBlock(block)); | 1728 assignLocations(ir.getLIRforBlock(block)); |
1729 } | 1729 } |
1730 } | 1730 } |
1731 } | 1731 } |
1809 | 1809 |
1810 private void optimizeSpillPosition() { | 1810 private void optimizeSpillPosition() { |
1811 LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[ir.linearScanOrder().size()]; | 1811 LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[ir.linearScanOrder().size()]; |
1812 for (Interval interval : intervals) { | 1812 for (Interval interval : intervals) { |
1813 if (interval != null && interval.isSplitParent() && interval.spillState() == SpillState.SpillInDominator) { | 1813 if (interval != null && interval.isSplitParent() && interval.spillState() == SpillState.SpillInDominator) { |
1814 AbstractBlock<?> defBlock = blockForId(interval.spillDefinitionPos()); | 1814 AbstractBlockBase<?> defBlock = blockForId(interval.spillDefinitionPos()); |
1815 AbstractBlock<?> spillBlock = null; | 1815 AbstractBlockBase<?> spillBlock = null; |
1816 Interval firstSpillChild = null; | 1816 Interval firstSpillChild = null; |
1817 try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) { | 1817 try (Indent indent = Debug.logAndIndent("interval %s (%s)", interval, defBlock)) { |
1818 for (Interval splitChild : interval.getSplitChildren()) { | 1818 for (Interval splitChild : interval.getSplitChildren()) { |
1819 if (isStackSlotValue(splitChild.location())) { | 1819 if (isStackSlotValue(splitChild.location())) { |
1820 if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) { | 1820 if (firstSpillChild == null || splitChild.from() < firstSpillChild.from()) { |
1821 firstSpillChild = splitChild; | 1821 firstSpillChild = splitChild; |
1822 } else { | 1822 } else { |
1823 assert firstSpillChild.from() < splitChild.from(); | 1823 assert firstSpillChild.from() < splitChild.from(); |
1824 } | 1824 } |
1825 // iterate all blocks where the interval has use positions | 1825 // iterate all blocks where the interval has use positions |
1826 for (AbstractBlock<?> splitBlock : blocksForInterval(splitChild)) { | 1826 for (AbstractBlockBase<?> splitBlock : blocksForInterval(splitChild)) { |
1827 if (dominates(defBlock, splitBlock)) { | 1827 if (dominates(defBlock, splitBlock)) { |
1828 Debug.log("Split interval %s, block %s", splitChild, splitBlock); | 1828 Debug.log("Split interval %s, block %s", splitChild, splitBlock); |
1829 if (spillBlock == null) { | 1829 if (spillBlock == null) { |
1830 spillBlock = splitBlock; | 1830 spillBlock = splitBlock; |
1831 } else { | 1831 } else { |
1849 * If the spill block is the begin of the first split child (aka the value | 1849 * If the spill block is the begin of the first split child (aka the value |
1850 * is on the stack) spill in the dominator. | 1850 * is on the stack) spill in the dominator. |
1851 */ | 1851 */ |
1852 assert firstSpillChild != null; | 1852 assert firstSpillChild != null; |
1853 if (!defBlock.equals(spillBlock) && spillBlock.equals(blockForId(firstSpillChild.from()))) { | 1853 if (!defBlock.equals(spillBlock) && spillBlock.equals(blockForId(firstSpillChild.from()))) { |
1854 AbstractBlock<?> dom = spillBlock.getDominator(); | 1854 AbstractBlockBase<?> dom = spillBlock.getDominator(); |
1855 Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); | 1855 Debug.log("Spill block (%s) is the beginning of a spill child -> use dominator (%s)", spillBlock, dom); |
1856 spillBlock = dom; | 1856 spillBlock = dom; |
1857 } | 1857 } |
1858 | 1858 |
1859 if (!defBlock.equals(spillBlock)) { | 1859 if (!defBlock.equals(spillBlock)) { |
1901 } | 1901 } |
1902 } | 1902 } |
1903 } | 1903 } |
1904 | 1904 |
1905 /** | 1905 /** |
1906 * Iterate over all {@link AbstractBlock blocks} of an interval. | 1906 * Iterate over all {@link AbstractBlockBase blocks} of an interval. |
1907 */ | 1907 */ |
1908 private class IntervalBlockIterator implements Iterator<AbstractBlock<?>> { | 1908 private class IntervalBlockIterator implements Iterator<AbstractBlockBase<?>> { |
1909 | 1909 |
1910 Range range; | 1910 Range range; |
1911 AbstractBlock<?> block; | 1911 AbstractBlockBase<?> block; |
1912 | 1912 |
1913 public IntervalBlockIterator(Interval interval) { | 1913 public IntervalBlockIterator(Interval interval) { |
1914 range = interval.first(); | 1914 range = interval.first(); |
1915 block = blockForId(range.from); | 1915 block = blockForId(range.from); |
1916 } | 1916 } |
1917 | 1917 |
1918 public AbstractBlock<?> next() { | 1918 public AbstractBlockBase<?> next() { |
1919 AbstractBlock<?> currentBlock = block; | 1919 AbstractBlockBase<?> currentBlock = block; |
1920 int nextBlockIndex = block.getLinearScanNumber() + 1; | 1920 int nextBlockIndex = block.getLinearScanNumber() + 1; |
1921 if (nextBlockIndex < sortedBlocks.size()) { | 1921 if (nextBlockIndex < sortedBlocks.size()) { |
1922 block = sortedBlocks.get(nextBlockIndex); | 1922 block = sortedBlocks.get(nextBlockIndex); |
1923 if (range.to <= getFirstLirInstructionId(block)) { | 1923 if (range.to <= getFirstLirInstructionId(block)) { |
1924 range = range.next; | 1924 range = range.next; |
1937 public boolean hasNext() { | 1937 public boolean hasNext() { |
1938 return block != null; | 1938 return block != null; |
1939 } | 1939 } |
1940 } | 1940 } |
1941 | 1941 |
1942 private Iterable<AbstractBlock<?>> blocksForInterval(Interval interval) { | 1942 private Iterable<AbstractBlockBase<?>> blocksForInterval(Interval interval) { |
1943 return new Iterable<AbstractBlock<?>>() { | 1943 return new Iterable<AbstractBlockBase<?>>() { |
1944 public Iterator<AbstractBlock<?>> iterator() { | 1944 public Iterator<AbstractBlockBase<?>> iterator() { |
1945 return new IntervalBlockIterator(interval); | 1945 return new IntervalBlockIterator(interval); |
1946 } | 1946 } |
1947 }; | 1947 }; |
1948 } | 1948 } |
1949 | 1949 |
1950 private static AbstractBlock<?> moveSpillOutOfLoop(AbstractBlock<?> defBlock, AbstractBlock<?> spillBlock) { | 1950 private static AbstractBlockBase<?> moveSpillOutOfLoop(AbstractBlockBase<?> defBlock, AbstractBlockBase<?> spillBlock) { |
1951 int defLoopDepth = defBlock.getLoopDepth(); | 1951 int defLoopDepth = defBlock.getLoopDepth(); |
1952 for (AbstractBlock<?> block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { | 1952 for (AbstractBlockBase<?> block = spillBlock.getDominator(); !defBlock.equals(block); block = block.getDominator()) { |
1953 assert block != null : "spill block not dominated by definition block?"; | 1953 assert block != null : "spill block not dominated by definition block?"; |
1954 if (block.getLoopDepth() <= defLoopDepth) { | 1954 if (block.getLoopDepth() <= defLoopDepth) { |
1955 assert block.getLoopDepth() == defLoopDepth : "Cannot spill an interval outside of the loop where it is defined!"; | 1955 assert block.getLoopDepth() == defLoopDepth : "Cannot spill an interval outside of the loop where it is defined!"; |
1956 return block; | 1956 return block; |
1957 } | 1957 } |
1968 } | 1968 } |
1969 } | 1969 } |
1970 | 1970 |
1971 try (Indent indent2 = Debug.logAndIndent("Basic Blocks")) { | 1971 try (Indent indent2 = Debug.logAndIndent("Basic Blocks")) { |
1972 for (int i = 0; i < blockCount(); i++) { | 1972 for (int i = 0; i < blockCount(); i++) { |
1973 AbstractBlock<?> block = blockAt(i); | 1973 AbstractBlockBase<?> block = blockAt(i); |
1974 Debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); | 1974 Debug.log("B%d [%d, %d, %s] ", block.getId(), getFirstLirInstructionId(block), getLastLirInstructionId(block), block.getLoop()); |
1975 } | 1975 } |
1976 } | 1976 } |
1977 } | 1977 } |
1978 } | 1978 } |
2101 // with a high operation id | 2101 // with a high operation id |
2102 otherIntervals = new Interval(Value.ILLEGAL, -1); | 2102 otherIntervals = new Interval(Value.ILLEGAL, -1); |
2103 otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1); | 2103 otherIntervals.addRange(Integer.MAX_VALUE - 2, Integer.MAX_VALUE - 1); |
2104 IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals); | 2104 IntervalWalker iw = new IntervalWalker(this, fixedIntervals, otherIntervals); |
2105 | 2105 |
2106 for (AbstractBlock<?> block : sortedBlocks) { | 2106 for (AbstractBlockBase<?> block : sortedBlocks) { |
2107 List<LIRInstruction> instructions = ir.getLIRforBlock(block); | 2107 List<LIRInstruction> instructions = ir.getLIRforBlock(block); |
2108 | 2108 |
2109 for (int j = 0; j < instructions.size(); j++) { | 2109 for (int j = 0; j < instructions.size(); j++) { |
2110 LIRInstruction op = instructions.get(j); | 2110 LIRInstruction op = instructions.get(j); |
2111 | 2111 |