changeset 22834:7129686d9f18

TraceRA: use data-flow resolver to insert spill moves on block boundaries.
author Josef Eisl <josef.eisl@jku.at>
date Tue, 13 Oct 2015 13:48:23 +0200
parents 054a187fc2cb
children 1b06a64e784f
files graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanResolveDataFlowPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java
diffstat 2 files changed, 48 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanResolveDataFlowPhase.java	Thu Oct 08 15:51:54 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanResolveDataFlowPhase.java	Tue Oct 13 13:48:23 2015 +0200
@@ -29,6 +29,7 @@
 import static jdk.vm.ci.code.ValueUtil.isStackSlotValue;
 import static jdk.vm.ci.code.ValueUtil.isVirtualStackSlot;
 
+import java.util.BitSet;
 import java.util.List;
 import java.util.ListIterator;
 
@@ -144,16 +145,44 @@
         @SuppressWarnings("try")
         private void resolveCollectMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, TraceLocalMoveResolver moveResolver) {
             try (Indent indent0 = Debug.logAndIndent("Edge %s -> %s", fromBlock, toBlock)) {
-                // collect all intervals that have been split between
-                // fromBlock and toBlock
-                SSIUtil.forEachValuePair(allocator.getLIR(), toBlock, fromBlock, new MyPhiValueVisitor(moveResolver, toBlock, fromBlock));
-                if (moveResolver.hasMappings()) {
-                    resolveFindInsertPos(fromBlock, toBlock, moveResolver);
-                    moveResolver.resolveAndAppendMoves();
+                collectLSRAMappings(fromBlock, toBlock, moveResolver);
+                collectSSIMappings(fromBlock, toBlock, moveResolver);
+            }
+        }
+
+        protected void collectLSRAMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, TraceLocalMoveResolver moveResolver) {
+            assert moveResolver.checkEmpty();
+
+            int toBlockFirstInstructionId = allocator.getFirstLirInstructionId(toBlock);
+            int fromBlockLastInstructionId = allocator.getLastLirInstructionId(fromBlock) + 1;
+            int numOperands = allocator.operandSize();
+            BitSet liveAtEdge = allocator.getBlockData(toBlock).liveIn;
+
+            // visit all variables for which the liveAtEdge bit is set
+            for (int operandNum = liveAtEdge.nextSetBit(0); operandNum >= 0; operandNum = liveAtEdge.nextSetBit(operandNum + 1)) {
+                assert operandNum < numOperands : "live information set for not exisiting interval";
+                assert allocator.getBlockData(fromBlock).liveOut.get(operandNum) && allocator.getBlockData(toBlock).liveIn.get(operandNum) : "interval not live at this edge";
+
+                TraceInterval fromInterval = allocator.splitChildAtOpId(allocator.intervalFor(operandNum), fromBlockLastInstructionId, LIRInstruction.OperandMode.DEF);
+                TraceInterval toInterval = allocator.splitChildAtOpId(allocator.intervalFor(operandNum), toBlockFirstInstructionId, LIRInstruction.OperandMode.DEF);
+
+                if (fromInterval != toInterval && !fromInterval.location().equals(toInterval.location())) {
+                    // need to insert move instruction
+                    moveResolver.addMapping(fromInterval, toInterval);
                 }
             }
         }
 
+        protected void collectSSIMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, TraceLocalMoveResolver moveResolver) {
+            // collect all intervals that have been split between
+            // fromBlock and toBlock
+            SSIUtil.forEachValuePair(allocator.getLIR(), toBlock, fromBlock, new MyPhiValueVisitor(moveResolver, toBlock, fromBlock));
+            if (moveResolver.hasMappings()) {
+                resolveFindInsertPos(fromBlock, toBlock, moveResolver);
+                moveResolver.resolveAndAppendMoves();
+            }
+        }
+
         private boolean containedInTrace(AbstractBlockBase<?> block) {
             return currentTrace() == traceBuilderResult.getTraceForBlock(block);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java	Thu Oct 08 15:51:54 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java	Tue Oct 13 13:48:23 2015 +0200
@@ -241,6 +241,7 @@
         }
     }
 
+    @SuppressWarnings("unused")
     private int insertIdAtBasicBlockBoundary(int opId) {
         assert allocator.isBlockBegin(opId) : "Not a block begin: " + opId;
         assert allocator.instructionForId(opId) instanceof LabelOp;
@@ -518,11 +519,10 @@
                 assert optimalSplitPos < interval.to() : "cannot split at end of interval";
                 assert optimalSplitPos >= interval.from() : "cannot split before start of interval";
 
-                if (allocator.isBlockBegin(optimalSplitPos)) {
-                    optimalSplitPos = insertIdAtBasicBlockBoundary(optimalSplitPos);
+                if (!allocator.isBlockBegin(optimalSplitPos)) {
+                    // move position before actual instruction (odd opId)
+                    optimalSplitPos = (optimalSplitPos - 1) | 1;
                 }
-                // move position before actual instruction (odd opId)
-                optimalSplitPos = (optimalSplitPos - 1) | 1;
 
                 try (Indent indent2 = Debug.logAndIndent("splitting at position %d", optimalSplitPos)) {
                     assert allocator.isBlockBegin(optimalSplitPos) || ((optimalSplitPos & 1) == 1) : "split pos must be odd when not on block boundary";
@@ -533,13 +533,16 @@
                     handleSpillSlot(spilledPart);
                     changeSpillState(spilledPart, optimalSplitPos);
 
-                    if (allocator.isBlockBegin(optimalSplitPos)) {
-                        optimalSplitPos = insertIdAtBasicBlockBoundary(optimalSplitPos);
+                    if (!allocator.isBlockBegin(optimalSplitPos)) {
+                        if (Debug.isLogEnabled()) {
+                            Debug.log("inserting move from interval %s to %s", interval, spilledPart);
+                        }
+                        insertMove(optimalSplitPos, interval, spilledPart);
+                    } else {
+                        if (Debug.isLogEnabled()) {
+                            Debug.log("no need to insert move. done by data-flow resolution");
+                        }
                     }
-                    if (Debug.isLogEnabled()) {
-                        Debug.log("inserting move from interval %s to %s", interval, spilledPart);
-                    }
-                    insertMove(optimalSplitPos, interval, spilledPart);
 
                     // the currentSplitChild is needed later when moves are inserted for reloading
                     assert spilledPart.currentSplitChild() == interval : "overwriting wrong currentSplitChild";