changeset 23188:f59bbe75e773

TraceRA: add TraceRAreuseStackSlotsForMoveResolutionCycleBreaking optimization.
author Josef Eisl <josef.eisl@jku.at>
date Tue, 15 Dec 2015 18:28:51 +0100
parents e660e8431be0
children d223936249bd
files graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java
diffstat 4 files changed, 37 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java	Mon Dec 14 17:48:10 2015 +0100
+++ b/graal/com.oracle.graal.lir.test/src/com/oracle/graal/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java	Tue Dec 15 18:28:51 2015 +0100
@@ -109,7 +109,7 @@
         private final HashSet<Pair> mapping = new HashSet<>();
 
         @Override
-        public void addMapping(Value src, AllocatableValue dst) {
+        public void addMapping(Value src, AllocatableValue dst, Value srcStack) {
             mapping.add(new Pair(src, dst));
         }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Mon Dec 14 17:48:10 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Tue Dec 15 18:28:51 2015 +0100
@@ -54,7 +54,7 @@
      * Abstract move resolver interface for testing.
      */
     public abstract static class MoveResolver {
-        public abstract void addMapping(Value src, AllocatableValue dst);
+        public abstract void addMapping(Value src, AllocatableValue dst, Value fromStack);
     }
 
     @Override
@@ -123,9 +123,10 @@
     private static void addMappingToRegister(MoveResolver moveResolver, Value from, RegisterValue register) {
         if (isShadowedRegisterValue(from)) {
             RegisterValue fromReg = asShadowedRegisterValue(from).getRegister();
-            checkAndAddMapping(moveResolver, fromReg, register);
+            AllocatableValue fromStack = asShadowedRegisterValue(from).getStackSlot();
+            checkAndAddMapping(moveResolver, fromReg, register, fromStack);
         } else {
-            checkAndAddMapping(moveResolver, from, register);
+            checkAndAddMapping(moveResolver, from, register, null);
         }
     }
 
@@ -135,17 +136,17 @@
             RegisterValue fromReg = shadowedFrom.getRegister();
             AllocatableValue fromStack = shadowedFrom.getStackSlot();
             if (!fromStack.equals(stack)) {
-                checkAndAddMapping(moveResolver, fromReg, stack);
+                checkAndAddMapping(moveResolver, fromReg, stack, fromStack);
             }
         } else {
-            checkAndAddMapping(moveResolver, from, stack);
+            checkAndAddMapping(moveResolver, from, stack, null);
         }
 
     }
 
-    private static void checkAndAddMapping(MoveResolver moveResolver, Value from, AllocatableValue to) {
-        if (!from.equals(to)) {
-            moveResolver.addMapping(from, to);
+    private static void checkAndAddMapping(MoveResolver moveResolver, Value from, AllocatableValue to, AllocatableValue fromStack) {
+        if (!from.equals(to) && (fromStack == null || !fromStack.equals(to))) {
+            moveResolver.addMapping(from, to, fromStack);
         }
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java	Mon Dec 14 17:48:10 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceGlobalMoveResolver.java	Tue Dec 15 18:28:51 2015 +0100
@@ -64,11 +64,13 @@
 final class TraceGlobalMoveResolver extends TraceGlobalMoveResolutionPhase.MoveResolver {
 
     private static final DebugMetric cycleBreakingSlotsAllocated = Debug.metric("TraceRA[cycleBreakingSlotsAllocated(global)]");
+    private static final DebugMetric cycleBreakingSlotsReused = Debug.metric("TraceRA[cycleBreakingSlotsReused(global)]");
 
     private int insertIdx;
     private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted
 
     private final List<Value> mappingFrom;
+    private final List<Value> mappingFromStack;
     private final List<AllocatableValue> mappingTo;
     private final int[] registerBlocked;
     private static final int STACK_SLOT_IN_CALLER_FRAME_IDX = -1;
@@ -136,6 +138,7 @@
     public TraceGlobalMoveResolver(LIRGenerationResult res, MoveFactory spillMoveFactory, Architecture arch) {
 
         this.mappingFrom = new ArrayList<>(8);
+        this.mappingFromStack = new ArrayList<>(8);
         this.mappingTo = new ArrayList<>(8);
         this.insertIdx = -1;
         this.insertionBuffer = new LIRInsertionBuffer();
@@ -155,7 +158,7 @@
         for (int i = 0; i < stackBlocked.length; i++) {
             assert stackBlocked[i] == 0 : "stack map must be empty before and after processing";
         }
-        assert mappingFrom.size() == 0 && mappingTo.size() == 0 : "list must be empty before and after processing";
+        assert mappingFrom.size() == 0 && mappingTo.size() == 0 && mappingFromStack.size() == 0 : "list must be empty before and after processing";
         for (int i = 0; i < getRegisters().length; i++) {
             assert registerBlocked[i] == 0 : "register map must be empty before and after processing";
         }
@@ -163,7 +166,7 @@
     }
 
     private boolean verifyBeforeResolve() {
-        assert mappingFrom.size() == mappingTo.size() : "length must be equal";
+        assert mappingFrom.size() == mappingTo.size() && mappingFrom.size() == mappingFromStack.size() : "length must be equal";
         assert insertIdx != -1 : "insert position not set";
 
         int i;
@@ -358,6 +361,7 @@
                         insertMove(fromLocation, toLocation);
                         unblock(fromLocation);
                         mappingFrom.remove(i);
+                        mappingFromStack.remove(i);
                         mappingTo.remove(i);
 
                         processedInterval = true;
@@ -387,13 +391,22 @@
         // create a new spill interval and assign a stack slot to it
         Value from = mappingFrom.get(spillCandidate);
         try (Indent indent = Debug.logAndIndent("BreakCycle: %s", from)) {
-            VirtualStackSlot spillSlot = frameMapBuilder.allocateSpillSlot(from.getLIRKind());
-            cycleBreakingSlotsAllocated.increment();
-            if (Debug.isLogEnabled()) {
+            AllocatableValue spillSlot = null;
+            if (TraceRegisterAllocationPhase.Options.TraceRAreuseStackSlotsForMoveResolutionCycleBreaking.getValue()) {
+                Value fromStack = mappingFromStack.get(spillCandidate);
+                if (fromStack != null) {
+                    spillSlot = (AllocatableValue) fromStack;
+                    cycleBreakingSlotsReused.increment();
+                    Debug.log("reuse slot for spilling: %s", spillSlot);
+                }
+            }
+            if (spillSlot == null) {
+                spillSlot = frameMapBuilder.allocateSpillSlot(from.getLIRKind());
+                cycleBreakingSlotsAllocated.increment();
                 Debug.log("created new slot for spilling: %s", spillSlot);
+                // insert a move from register to stack and update the mapping
+                insertMove(from, spillSlot);
             }
-            // insert a move from register to stack and update the mapping
-            insertMove(from, spillSlot);
             block(spillSlot);
             mappingFrom.set(spillCandidate, spillSlot);
             unblock(from);
@@ -404,7 +417,7 @@
     private void printMapping() {
         try (Indent indent = Debug.logAndIndent("Mapping")) {
             for (int i = mappingFrom.size() - 1; i >= 0; i--) {
-                Debug.log("move %s <- %s", mappingTo.get(i), mappingFrom.get(i));
+                Debug.log("move %s <- %s (%s)", mappingTo.get(i), mappingFrom.get(i), mappingFromStack.get(i));
             }
         }
     }
@@ -417,14 +430,17 @@
     }
 
     @Override
-    public void addMapping(Value from, AllocatableValue to) {
+    public void addMapping(Value from, AllocatableValue to, Value fromStack) {
         if (Debug.isLogEnabled()) {
             Debug.log("add move mapping from %s to %s", from, to);
         }
 
         assert !from.equals(to) : "from and to interval equal: " + from;
         assert LIRKind.verifyMoveKinds(to.getLIRKind(), from.getLIRKind()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s", from.getLIRKind(), to.getLIRKind(), from, to);
+        assert fromStack == null || LIRKind.verifyMoveKinds(to.getLIRKind(), fromStack.getLIRKind()) : String.format("Kind mismatch: %s vs. %s, fromStack=%s, to=%s", fromStack.getLIRKind(),
+                        to.getLIRKind(), fromStack, to);
         mappingFrom.add(from);
+        mappingFromStack.add(fromStack);
         mappingTo.add(to);
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java	Mon Dec 14 17:48:10 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceRegisterAllocationPhase.java	Tue Dec 15 18:28:51 2015 +0100
@@ -63,6 +63,8 @@
         public static final OptionValue<Boolean> TraceRAtrivialBlockAllocator = new OptionValue<>(true);
         @Option(help = "Share information about spilled values to other traces.", type = OptionType.Debug)
         public static final OptionValue<Boolean> TraceRAshareSpillInformation = new OptionValue<>(true);
+        @Option(help = "Reuse spill slots for global move resolution cycle breaking.", type = OptionType.Debug)
+        public static final OptionValue<Boolean> TraceRAreuseStackSlotsForMoveResolutionCycleBreaking = new OptionValue<>(true);
         // @formatter:on
     }