changeset 23029:ccfa6d4d989b

TraceRA: replace TraceInterval.alwaysInMemory() with inMemoryAt(opId).
author Josef Eisl <josef.eisl@jku.at>
date Thu, 19 Nov 2015 16:51:23 +0100
parents f81a81808795
children 183221119491
files graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanAssignLocationsPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java
diffstat 3 files changed, 16 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java	Thu Nov 19 16:36:45 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java	Thu Nov 19 16:51:23 2015 +0100
@@ -530,9 +530,12 @@
         splitParent().spillDefinitionPos = pos;
     }
 
-    // returns true if this interval has a shadow copy on the stack that is always correct
-    public boolean alwaysInMemory() {
-        return SpillState.ALWAYS_IN_MEMORY.contains(spillState()) && !canMaterialize();
+    /**
+     * Returns true if this interval has a shadow copy on the stack that is correct after
+     * {@code opId}.
+     */
+    public boolean inMemoryAt(int opId) {
+        return SpillState.ALWAYS_IN_MEMORY.contains(spillState()) && !canMaterialize() && opId > spillDefinitionPos();
     }
 
     void removeFirstUsePos() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanAssignLocationsPhase.java	Thu Nov 19 16:36:45 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanAssignLocationsPhase.java	Thu Nov 19 16:51:23 2015 +0100
@@ -148,7 +148,7 @@
                  * instruction is a branch, spill moves are inserted before this branch and so the
                  * wrong operand would be returned (spill moves at block boundaries are not
                  * considered in the live ranges of intervals).
-                 *
+                 * 
                  * Solution: use the first opId of the branch target block instead.
                  */
                 final LIRInstruction instr = allocator.getLIR().getLIRforBlock(block).get(allocator.getLIR().getLIRforBlock(block).size() - 1);
@@ -264,7 +264,7 @@
                     assert interval != null : "interval must exist";
                     interval = allocator.splitChildAtOpId(interval, instruction.id(), mode);
 
-                    if (interval.alwaysInMemory() && isRegister(interval.location())) {
+                    if (interval.inMemoryAt(instruction.id()) && isRegister(interval.location())) {
                         return new ShadowedRegisterValue((RegisterValue) interval.location(), interval.spillSlot());
                     }
                 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java	Thu Nov 19 16:36:45 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java	Thu Nov 19 16:51:23 2015 +0100
@@ -88,6 +88,7 @@
                     List<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
                     int numInst = instructions.size();
 
+                    int lastOpId = -1;
                     // iterate all instructions of the block.
                     for (int j = 0; j < numInst; j++) {
                         LIRInstruction op = instructions.get(j);
@@ -100,7 +101,7 @@
                              * be correct. Only moves that have been inserted by LinearScan can be
                              * removed.
                              */
-                            if (shouldEliminateSpillMoves && canEliminateSpillMove(allocator, block, move)) {
+                            if (shouldEliminateSpillMoves && canEliminateSpillMove(allocator, block, move, lastOpId)) {
                                 /*
                                  * Move target is a stack slot that is always correct, so eliminate
                                  * instruction.
@@ -121,6 +122,7 @@
                             }
 
                         } else {
+                            lastOpId = opId;
                             /*
                              * Insert move from register to stack just after the beginning of the
                              * interval.
@@ -173,13 +175,16 @@
      * @param allocator
      * @param block The block {@code move} is located in.
      * @param move Spill move.
+     * @param lastOpId The id of last "normal" instruction before the spill move. (Spill moves have
+     *            no valid opId but -1.)
      */
-    private static boolean canEliminateSpillMove(TraceLinearScan allocator, AbstractBlockBase<?> block, MoveOp move) {
+    private static boolean canEliminateSpillMove(TraceLinearScan allocator, AbstractBlockBase<?> block, MoveOp move, int lastOpId) {
         assert isVariable(move.getResult()) : "LinearScan inserts only moves to variables: " + move;
+        assert lastOpId >= 0 : "Invalid lastOpId: " + lastOpId;
 
         TraceInterval curInterval = allocator.intervalFor(move.getResult());
 
-        if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory() && isPhiResolutionMove(allocator, move)) {
+        if (!isRegister(curInterval.location()) && curInterval.inMemoryAt(lastOpId) && isPhiResolutionMove(allocator, move)) {
             assert isStackSlotValue(curInterval.location()) : "Not a stack slot: " + curInterval.location();
             return true;
         }