changeset 22971:6c37ffb6887b

TraceRA: add option for spill move elimination.
author Josef Eisl <josef.eisl@jku.at>
date Wed, 11 Nov 2015 17:14:06 +0100
parents 9e5a47e3c94c
children 0ce3d7818862
files graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java
diffstat 2 files changed, 54 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java	Fri Nov 06 17:50:57 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java	Wed Nov 11 17:14:06 2015 +0100
@@ -45,6 +45,10 @@
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.LIRKind;
 import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.options.NestedBooleanOptionValue;
+import jdk.vm.ci.options.Option;
+import jdk.vm.ci.options.OptionType;
+import jdk.vm.ci.options.OptionValue;
 
 import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig;
 import com.oracle.graal.compiler.common.alloc.TraceBuilder.TraceBuilderResult;
@@ -64,6 +68,7 @@
 import com.oracle.graal.lir.framemap.FrameMapBuilder;
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.lir.gen.LIRGeneratorTool.MoveFactory;
+import com.oracle.graal.lir.phases.LIRPhase;
 
 /**
  * An implementation of the linear scan register allocator algorithm described in <a
@@ -73,6 +78,13 @@
  */
 final class TraceLinearScan {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Enable spill position optimization", type = OptionType.Debug)
+        public static final OptionValue<Boolean> LIROptTraceRAEliminateSpillMoves = new NestedBooleanOptionValue(LIRPhase.Options.LIROptimization, true);
+        // @formatter:on
+    }
+
     private static final TraceLinearScanRegisterAllocationPhase TRACE_LINEAR_SCAN_REGISTER_ALLOCATION_PHASE = new TraceLinearScanRegisterAllocationPhase();
     private static final TraceLinearScanAssignLocationsPhase TRACE_LINEAR_SCAN_ASSIGN_LOCATIONS_PHASE = new TraceLinearScanAssignLocationsPhase();
     private static final TraceLinearScanEliminateSpillMovePhase TRACE_LINEAR_SCAN_ELIMINATE_SPILL_MOVE_PHASE = new TraceLinearScanEliminateSpillMovePhase();
@@ -736,8 +748,10 @@
                 Debug.dump(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL, sortedBlocks(), "%s", TRACE_LINEAR_SCAN_RESOLVE_DATA_FLOW_PHASE.getName());
 
                 // eliminate spill moves
-                TRACE_LINEAR_SCAN_ELIMINATE_SPILL_MOVE_PHASE.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false);
-                Debug.dump(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL, sortedBlocks(), "%s", TRACE_LINEAR_SCAN_ELIMINATE_SPILL_MOVE_PHASE.getName());
+                if (Options.LIROptTraceRAEliminateSpillMoves.getValue()) {
+                    TRACE_LINEAR_SCAN_ELIMINATE_SPILL_MOVE_PHASE.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false);
+                    Debug.dump(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL, sortedBlocks(), "%s", TRACE_LINEAR_SCAN_ELIMINATE_SPILL_MOVE_PHASE.getName());
+                }
 
                 TRACE_LINEAR_SCAN_ASSIGN_LOCATIONS_PHASE.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false);
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java	Fri Nov 06 17:50:57 2015 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java	Wed Nov 11 17:14:06 2015 +0100
@@ -559,44 +559,48 @@
 
     // called during register allocation
     private void changeSpillState(TraceInterval interval, int spillPos) {
-        switch (interval.spillState()) {
-            case NoSpillStore: {
-                int defLoopDepth = allocator.blockForId(interval.spillDefinitionPos()).getLoopDepth();
-                int spillLoopDepth = allocator.blockForId(spillPos).getLoopDepth();
+        if (TraceLinearScan.Options.LIROptTraceRAEliminateSpillMoves.getValue()) {
+            switch (interval.spillState()) {
+                case NoSpillStore: {
+                    int defLoopDepth = allocator.blockForId(interval.spillDefinitionPos()).getLoopDepth();
+                    int spillLoopDepth = allocator.blockForId(spillPos).getLoopDepth();
 
-                if (defLoopDepth < spillLoopDepth) {
-                    /*
-                     * The loop depth of the spilling position is higher then the loop depth at the
-                     * definition of the interval. Move write to memory out of loop.
-                     */
-                    // store at definition of the interval
+                    if (defLoopDepth < spillLoopDepth) {
+                        /*
+                         * The loop depth of the spilling position is higher then the loop depth at
+                         * the definition of the interval. Move write to memory out of loop.
+                         */
+                        // store at definition of the interval
+                        interval.setSpillState(SpillState.StoreAtDefinition);
+                    } else {
+                        /*
+                         * The interval is currently spilled only once, so for now there is no
+                         * reason to store the interval at the definition.
+                         */
+                        interval.setSpillState(SpillState.OneSpillStore);
+                    }
+                    break;
+                }
+
+                case OneSpillStore: {
+                    // It is better to store it to memory at the definition.
                     interval.setSpillState(SpillState.StoreAtDefinition);
-                } else {
-                    /*
-                     * The interval is currently spilled only once, so for now there is no reason to
-                     * store the interval at the definition.
-                     */
-                    interval.setSpillState(SpillState.OneSpillStore);
+                    break;
                 }
-                break;
+
+                case SpillInDominator:
+                case StoreAtDefinition:
+                case StartInMemory:
+                case NoOptimization:
+                case NoDefinitionFound:
+                    // nothing to do
+                    break;
+
+                default:
+                    throw new BailoutException("other states not allowed at this time");
             }
-
-            case OneSpillStore: {
-                // It is better to store it to memory at the definition.
-                interval.setSpillState(SpillState.StoreAtDefinition);
-                break;
-            }
-
-            case SpillInDominator:
-            case StoreAtDefinition:
-            case StartInMemory:
-            case NoOptimization:
-            case NoDefinitionFound:
-                // nothing to do
-                break;
-
-            default:
-                throw new BailoutException("other states not allowed at this time");
+        } else {
+            interval.setSpillState(SpillState.NoOptimization);
         }
     }