changeset 21236:8d21d631a82d

LinearScan: minor refactoring and comment cleanup.
author Josef Eisl <josef.eisl@jku.at>
date Thu, 30 Apr 2015 10:58:10 +0200
parents 7e9edc108b35
children cc6e6c3e0eb7
files graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java
diffstat 1 files changed, 105 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Tue May 05 13:08:05 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java	Thu Apr 30 10:58:10 2015 +0200
@@ -42,6 +42,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.alloc.lsra.Interval.RegisterBinding;
 import com.oracle.graal.lir.alloc.lsra.Interval.RegisterPriority;
@@ -522,6 +523,15 @@
         }
     };
 
+    /**
+     * @return the index of the first instruction that is of interest for
+     *         {@link #eliminateSpillMoves()}
+     */
+    protected int firstInstructionOfInterest() {
+        // skip the first because it is always a label
+        return 1;
+    }
+
     // called once before assignment of register numbers
     void eliminateSpillMoves() {
         try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves")) {
@@ -536,67 +546,78 @@
 
             LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer();
             for (AbstractBlockBase<?> block : sortedBlocks) {
-                List<LIRInstruction> instructions = ir.getLIRforBlock(block);
-                int numInst = instructions.size();
-
-                // iterate all instructions of the block. skip the first
-                // because it is always a label
-                for (int j = 1; j < numInst; j++) {
-                    LIRInstruction op = instructions.get(j);
-                    int opId = op.id();
+                try (Indent indent1 = Debug.logAndIndent("Handle %s", block)) {
+                    List<LIRInstruction> instructions = ir.getLIRforBlock(block);
+                    int numInst = instructions.size();
 
-                    if (opId == -1) {
-                        MoveOp move = (MoveOp) op;
-                        // remove move from register to stack if the stack slot is guaranteed to be
-                        // correct.
-                        // only moves that have been inserted by LinearScan can be removed.
-                        assert isVariable(move.getResult()) : "LinearScan inserts only moves to variables";
-
-                        Interval curInterval = intervalFor(move.getResult());
+                    // iterate all instructions of the block.
+                    for (int j = firstInstructionOfInterest(); j < numInst; j++) {
+                        LIRInstruction op = instructions.get(j);
+                        int opId = op.id();
 
-                        if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) {
-                            // move target is a stack slot that is always correct, so eliminate
-                            // instruction
-                            if (Debug.isLogEnabled()) {
-                                Debug.log("eliminating move from interval %d to %d", operandNumber(move.getInput()), operandNumber(move.getResult()));
-                            }
-                            // null-instructions are deleted by assignRegNum
-                            instructions.set(j, null);
-                        }
-
-                    } else {
-                        // insert move from register to stack just after
-                        // the beginning of the interval
-                        assert interval == Interval.EndMarker || interval.spillDefinitionPos() >= opId : "invalid order";
-                        assert interval == Interval.EndMarker || (interval.isSplitParent() && interval.spillState() == SpillState.StoreAtDefinition) : "invalid interval";
-
-                        while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) {
-                            if (!interval.canMaterialize()) {
-                                if (!insertionBuffer.initialized()) {
-                                    // prepare insertion buffer (appended when all instructions in
-                                    // the block are processed)
-                                    insertionBuffer.init(instructions);
+                        if (opId == -1) {
+                            MoveOp move = (MoveOp) op;
+                            /*
+                             * Remove move from register to stack if the stack slot is guaranteed to
+                             * be correct. Only moves that have been inserted by LinearScan can be
+                             * removed.
+                             */
+                            if (canEliminateSpillMove(block, move)) {
+                                /*
+                                 * Move target is a stack slot that is always correct, so eliminate
+                                 * instruction.
+                                 */
+                                if (Debug.isLogEnabled()) {
+                                    Debug.log("eliminating move from interval %d (%s) to %d (%s) in block %s", operandNumber(move.getInput()), move.getInput(), operandNumber(move.getResult()),
+                                                    move.getResult(), block);
                                 }
 
-                                AllocatableValue fromLocation = interval.location();
-                                AllocatableValue toLocation = canonicalSpillOpr(interval);
+                                // null-instructions are deleted by assignRegNum
+                                instructions.set(j, null);
+                            }
 
-                                assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState();
-                                assert isStackSlotValue(toLocation) : "to operand must be a stack slot";
+                        } else {
+                            /*
+                             * Insert move from register to stack just after the beginning of the
+                             * interval.
+                             */
+                            assert interval == Interval.EndMarker || interval.spillDefinitionPos() >= opId : "invalid order";
+                            assert interval == Interval.EndMarker || (interval.isSplitParent() && interval.spillState() == SpillState.StoreAtDefinition) : "invalid interval";
 
-                                insertionBuffer.append(j + 1, getSpillMoveFactory().createMove(toLocation, fromLocation));
+                            while (interval != Interval.EndMarker && interval.spillDefinitionPos() == opId) {
+                                if (!interval.canMaterialize()) {
+                                    if (!insertionBuffer.initialized()) {
+                                        /*
+                                         * prepare insertion buffer (appended when all instructions
+                                         * in the block are processed)
+                                         */
+                                        insertionBuffer.init(instructions);
+                                    }
 
-                                if (Debug.isLogEnabled()) {
-                                    Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId);
+                                    AllocatableValue fromLocation = interval.location();
+                                    AllocatableValue toLocation = canonicalSpillOpr(interval);
+                                    if (!fromLocation.equals(toLocation)) {
+
+                                        assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" +
+                                                        interval.spillState();
+                                        assert isStackSlotValue(toLocation) : "to operand must be a stack slot";
+
+                                        LIRInstruction move = getSpillMoveFactory().createMove(toLocation, fromLocation);
+                                        insertionBuffer.append(j + 1, move);
+
+                                        if (Debug.isLogEnabled()) {
+                                            Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId);
+                                        }
+                                    }
                                 }
+                                interval = interval.next;
                             }
-                            interval = interval.next;
                         }
-                    }
-                } // end of instruction iteration
+                    } // end of instruction iteration
 
-                if (insertionBuffer.initialized()) {
-                    insertionBuffer.finish();
+                    if (insertionBuffer.initialized()) {
+                        insertionBuffer.finish();
+                    }
                 }
             } // end of block iteration
 
@@ -604,6 +625,22 @@
         }
     }
 
+    /**
+     * @param block The block {@code move} is located in.
+     * @param move Spill move.
+     */
+    protected boolean canEliminateSpillMove(AbstractBlockBase<?> block, MoveOp move) {
+        assert isVariable(move.getResult()) : "LinearScan inserts only moves to variables: " + move;
+
+        Interval curInterval = intervalFor(move.getResult());
+
+        if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) {
+            assert isStackSlotValue(curInterval.location()) : "Not a stack slot: " + curInterval.location();
+            return true;
+        }
+        return false;
+    }
+
     private static void checkIntervals(Interval interval) {
         Interval prev = null;
         Interval temp = interval;
@@ -1058,7 +1095,7 @@
         }
 
         changeSpillDefinitionPos(interval, defPos);
-        if (registerPriority == RegisterPriority.None && interval.spillState().ordinal() <= SpillState.StartInMemory.ordinal()) {
+        if (registerPriority == RegisterPriority.None && interval.spillState().ordinal() <= SpillState.StartInMemory.ordinal() && isStackSlot(operand)) {
             // detection of method-parameters and roundfp-results
             interval.setSpillState(SpillState.StartInMemory);
         }
@@ -1078,6 +1115,11 @@
             if (optimizeMethodArgument(move.getInput())) {
                 return RegisterPriority.None;
             }
+        } else if (op instanceof LabelOp) {
+            LabelOp label = (LabelOp) op;
+            if (label.isPhiIn()) {
+                return RegisterPriority.None;
+            }
         }
 
         // all other operands require a register
@@ -1456,8 +1498,11 @@
         throw new BailoutException("LinearScan: interval is null");
     }
 
-    void resolveCollectMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, MoveResolver moveResolver) {
+    void resolveCollectMappings(AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock, AbstractBlockBase<?> midBlock, MoveResolver moveResolver) {
         assert moveResolver.checkEmpty();
+        assert midBlock == null ||
+                        (midBlock.getPredecessorCount() == 1 && midBlock.getSuccessorCount() == 1 && midBlock.getPredecessors().get(0).equals(fromBlock) && midBlock.getSuccessors().get(0).equals(
+                                        toBlock));
 
         int toBlockFirstInstructionId = getFirstLirInstructionId(toBlock);
         int fromBlockLastInstructionId = getLastLirInstructionId(fromBlock) + 1;
@@ -1551,7 +1596,7 @@
                             // directly resolve between pred and sux (without looking
                             // at the empty block
                             // between)
-                            resolveCollectMappings(pred, sux, moveResolver);
+                            resolveCollectMappings(pred, sux, block, moveResolver);
                             if (moveResolver.hasMappings()) {
                                 moveResolver.setInsertPosition(instructions, 1);
                                 moveResolver.resolveAndAppendMoves();
@@ -1579,7 +1624,7 @@
 
                             // collect all intervals that have been split between
                             // fromBlock and toBlock
-                            resolveCollectMappings(fromBlock, toBlock, moveResolver);
+                            resolveCollectMappings(fromBlock, toBlock, null, moveResolver);
                             if (moveResolver.hasMappings()) {
                                 resolveFindInsertPos(fromBlock, toBlock, moveResolver);
                                 moveResolver.resolveAndAppendMoves();
@@ -1588,6 +1633,7 @@
                     }
                 }
             }
+
         }
     }
 
@@ -1837,6 +1883,8 @@
                     verify();
                 }
 
+                beforeSpillMoveElimination();
+
                 try (Scope s1 = Debug.scope("EliminateSpillMove"); DebugCloseable a = eliminateSpillMoveTimer.start()) {
                     eliminateSpillMoves();
                 } catch (Throwable e) {
@@ -1861,6 +1909,9 @@
         }
     }
 
+    protected void beforeSpillMoveElimination() {
+    }
+
     private static final DebugMetric betterSpillPos = Debug.metric("BetterSpillPosition");
     private static final DebugMetric betterSpillPosWithLowerProbability = Debug.metric("BetterSpillPositionWithLowerProbability");