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