changeset 4212:f282e35ea829

Define incoming parameters in a PARAMS instruction. This simplifies register allocation because the initial register state does not have to be inferred from the calling convention.
author Christian Wimmer <Christian.Wimmer@Oracle.com>
date Tue, 03 Jan 2012 18:42:32 -0800
parents bf6d8bcde8a0
children e4cfa571d8c4
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java
diffstat 9 files changed, 77 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java	Tue Jan 03 18:42:32 2012 -0800
@@ -39,13 +39,11 @@
     private final GraalContext context;
     private final LIR lir;
     private final RiRegisterConfig registerConfig;
-    private final CiCallingConvention incomingArguments;
 
-    public DataFlowAnalysis(GraalContext context, LIR lir, RiRegisterConfig registerConfig, CiCallingConvention incomingArguments) {
+    public DataFlowAnalysis(GraalContext context, LIR lir, RiRegisterConfig registerConfig) {
         this.context = context;
         this.lir = lir;
         this.registerConfig = registerConfig;
-        this.incomingArguments = incomingArguments;
     }
 
     public void execute() {
@@ -212,15 +210,6 @@
                 block.phis.forEachOutput(outputProc);
             }
 
-            if (block.numberOfPreds() == 0) {
-                curOpId = block.firstLirInstructionId();
-                trace(1, "  arguments %d  variableLive: %s  registerLive: %s", curOpId, variableLive, registerLive);
-                for (CiValue value : incomingArguments.locations) {
-                    def(value, false);
-                }
-                assert variableLive.isEmpty() : "no variables must be live at method entry";
-            }
-
             assert registerLive.isEmpty() : "no fixed register must be alive after processing a block";
             assert liveIn(block) == null;
             setLiveIn(block, variableLive);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java	Tue Jan 03 18:42:32 2012 -0800
@@ -43,22 +43,37 @@
     private final LIR lir;
     private final FrameMap frameMap;
     private final RiRegisterConfig registerConfig;
-    private final CiCallingConvention incomingArguments;
 
     private final DataFlowAnalysis dataFlow;
 
-    public SpillAllAllocator(GraalContext context, LIR lir, GraalCompilation compilation, RiRegisterConfig registerConfig, CiCallingConvention incomingArguments) {
+    public SpillAllAllocator(GraalContext context, LIR lir, GraalCompilation compilation, RiRegisterConfig registerConfig) {
         this.context = context;
         this.lir = lir;
         this.registerConfig = registerConfig;
         this.frameMap = compilation.frameMap();
-        this.incomingArguments = incomingArguments;
 
-        this.dataFlow = new DataFlowAnalysis(context, lir, registerConfig, incomingArguments);
+        this.dataFlow = new DataFlowAnalysis(context, lir, registerConfig);
         this.blockLocations = new LocationMap[lir.linearScanOrder().size()];
-        this.moveResolver = new MoveResolver(frameMap);
+        this.moveResolver = new MoveResolverImpl(frameMap);
     }
 
+    private class MoveResolverImpl extends MoveResolver {
+        public MoveResolverImpl(FrameMap frameMap) {
+            super(frameMap);
+        }
+
+        @Override
+        protected CiValue scratchRegister(Variable spilled) {
+            EnumMap<RegisterFlag, CiRegister[]> categorizedRegs = registerConfig.getCategorizedAllocatableRegisters();
+            CiRegister[] availableRegs = categorizedRegs.get(spilled.flag);
+            for (CiRegister reg : availableRegs) {
+                if (curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null) {
+                    return reg.asValue(spilled.kind);
+                }
+            }
+            throw new CiBailout("No register found");
+        }
+    }
 
     private class ResolveDataFlowImpl extends ResolveDataFlow {
         public ResolveDataFlowImpl(LIR lir, MoveResolver moveResolver) {
@@ -116,7 +131,7 @@
     private LIRInstruction curInstruction;
 
     public void execute() {
-        assert LIRVerifier.verify(true, lir, incomingArguments, frameMap, registerConfig);
+        assert LIRVerifier.verify(true, lir, frameMap, registerConfig);
 
         dataFlow.execute();
 
@@ -131,14 +146,14 @@
 
         context.observable.fireCompilationEvent("After resolve data flow", lir);
 
-        assert RegisterVerifier.verify(lir, incomingArguments, frameMap, registerConfig);
+        assert RegisterVerifier.verify(lir, frameMap, registerConfig);
 
         AssignRegisters assignRegisters = new AssignRegistersImpl(lir, frameMap);
         assignRegisters.execute();
 
         context.observable.fireCompilationEvent("After register asignment", lir);
 
-        assert LIRVerifier.verify(true, lir, incomingArguments, frameMap, registerConfig);
+        assert LIRVerifier.verify(true, lir, frameMap, registerConfig);
     }
 
     private void allocate() {
@@ -162,20 +177,15 @@
             trace(1, "start block %s  loop %d depth %d", block, block.loopIndex(), block.loopDepth());
             assert checkEmpty(curOutRegisterState);
 
-            if (block.numberOfPreds() == 0) {
-                curStackLocations = new LocationMap(lir.numVariables());
-                trace(1, "  arguments");
-                curInstruction = lir.startBlock().lir().get(0);
-                for (CiValue value : incomingArguments.locations) {
-                    block(value);
-                }
-            } else {
+            if (block.dominator() != null) {
                 LocationMap dominatorState = locationsFor(block.dominator());
                 curStackLocations = new LocationMap(dominatorState);
                 // Clear out all variables that are not live at the begin of this block
                 curLiveIn = dataFlow.liveIn(block);
                 curStackLocations.forEachLocation(killNonLiveProc);
                 assert checkInputState(block);
+            } else {
+                curStackLocations = new LocationMap(lir.numVariables());
             }
             traceState();
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java	Tue Jan 03 18:42:32 2012 -0800
@@ -61,9 +61,9 @@
     }
 
 
-    public static boolean verify(boolean beforeRegisterAllocation, LIR lir, CiCallingConvention incomingArguments, FrameMap frameMap, RiRegisterConfig registerConfig) {
+    public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap, RiRegisterConfig registerConfig) {
         LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap, registerConfig);
-        verifier.verify(incomingArguments);
+        verifier.verify();
         return true;
     }
 
@@ -82,7 +82,7 @@
     private LIRBlock curBlock;
     private Object curInstruction;
 
-    private void verify(CiCallingConvention incomingArguments) {
+    private void verify() {
         ValueProcedure useProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } };
         ValueProcedure tempProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, true); } };
         ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return def(value, false); } };
@@ -92,12 +92,7 @@
             curVariablesLive = new BitSet();
             curRegistersLive = new CiValue[maxRegisterNum()];
 
-            if (block.numberOfPreds() == 0) {
-                curInstruction = "Argument";
-                for (CiValue value : incomingArguments.locations) {
-                    def(value, false);
-                }
-            } else {
+            if (block.dominator() != null) {
                 curVariablesLive.or(liveOutFor(block.dominator()));
             }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java	Tue Jan 03 18:42:32 2012 -0800
@@ -70,9 +70,9 @@
         return new HashMap<>(inputState);
     }
 
-    public static boolean verify(LIR lir, CiCallingConvention incomingArguments, FrameMap frameMap, RiRegisterConfig registerConfig) {
+    public static boolean verify(LIR lir, FrameMap frameMap, RiRegisterConfig registerConfig) {
         RegisterVerifier verifier = new RegisterVerifier(lir, frameMap, registerConfig);
-        verifier.verify(lir.startBlock(), incomingArguments);
+        verifier.verify(lir.startBlock());
         return true;
     }
 
@@ -86,15 +86,12 @@
 
     private Map<Object, CiValue> curInputState;
 
-    private void verify(LIRBlock startBlock, CiCallingConvention incomingArguments) {
+    private void verify(LIRBlock startBlock) {
         ValueProcedure useProc =    new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value); } };
         ValueProcedure tempProc =   new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return temp(value); } };
         ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return output(value); } };
 
         curInputState = new HashMap<>();
-        for (CiValue value : incomingArguments.locations) {
-            curInputState.put(key(value), value);
-        }
         setStateFor(startBlock, curInputState);
         addToWorkList(startBlock);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java	Tue Jan 03 18:42:32 2012 -0800
@@ -350,7 +350,7 @@
                 }
 
                 if (GraalOptions.AllocSSA) {
-                    new SpillAllAllocator(context(), lir, this, registerConfig, lirGenerator.incomingArguments).execute();
+                    new SpillAllAllocator(context(), lir, this, registerConfig).execute();
                 } else {
                     new LinearScan(this, lir, lirGenerator, frameMap()).allocate();
                 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java	Tue Jan 03 18:42:32 2012 -0800
@@ -79,16 +79,6 @@
     void verify(LIRBlock start) {
         // setup input registers (method arguments) for first block
         Interval[] inputState = new Interval[stateSize()];
-        CiCallingConvention args = allocator.gen.incomingArguments;
-        for (int n = 0; n < args.locations.length; n++) {
-            CiValue operand = args.locations[n];
-            if (isRegister(operand)) {
-                CiValue reg = operand;
-                Interval interval = intervalAt(reg);
-                inputState[asRegister(reg).number] = interval;
-            }
-        }
-
         setStateForBlock(start, inputState);
         addToWorkList(start);
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jan 03 18:42:32 2012 -0800
@@ -22,6 +22,7 @@
  */
 package com.oracle.max.graal.compiler.gen;
 
+import static com.oracle.max.graal.compiler.lir.StandardOpcode.*;
 import static com.oracle.max.cri.ci.CiCallingConvention.Type.*;
 import static com.oracle.max.cri.ci.CiValue.*;
 import static com.oracle.max.cri.ci.CiValueUtil.*;
@@ -68,8 +69,6 @@
     protected final RiXirGenerator xir;
     private final DebugInfoBuilder debugInfoBuilder;
 
-    public final CiCallingConvention incomingArguments;
-
     private LIRBlock currentBlock;
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
@@ -82,8 +81,6 @@
         this.xir = xir;
         this.xirSupport = new XirSupport();
         this.debugInfoBuilder = new DebugInfoBuilder(compilation);
-
-        this.incomingArguments = compilation.registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(compilation.method), compilation.compiler.target, false);
     }
 
     @Override
@@ -226,11 +223,7 @@
         }
 
         if (block == lir.startBlock()) {
-            XirSnippet prologue = xir.genPrologue(null, compilation.method);
-            if (prologue != null) {
-                emitXir(prologue, null, null, null, false);
-            }
-            setOperandsForParameters();
+            emitPrologue();
         } else if (block.getPredecessors().size() > 0) {
             FrameState fs = null;
             for (Block p : block.getPredecessors()) {
@@ -349,14 +342,24 @@
         return !(location instanceof IndexedLocationNode) && location.displacement() < 4096;
     }
 
-    private void setOperandsForParameters() {
-        CiCallingConvention args = incomingArguments;
+    private void emitPrologue() {
+        CiCallingConvention incomingArguments = compilation.registerConfig.getCallingConvention(JavaCallee, CiUtil.signatureToKinds(compilation.method), compilation.compiler.target, false);
+
+        CiValue[] params = new CiValue[incomingArguments.locations.length];
+        for (int i = 0; i < params.length; i++) {
+            params[i] = toStackKind(incomingArguments.locations[i]);
+        }
+        append(PARAMS.create(params));
+
+        XirSnippet prologue = xir.genPrologue(null, compilation.method);
+        if (prologue != null) {
+            emitXir(prologue, null, null, null, false);
+        }
+
         for (LocalNode local : compilation.graph.getNodes(LocalNode.class)) {
-            int i = local.index();
-            CiValue src = toStackKind(args.locations[i]);
-            Variable dest = emitMove(src);
-            assert src.kind == local.kind().stackKind() : "local type check failed";
-            setResult(local, dest);
+            CiValue param = params[local.index()];
+            assert param.kind == local.kind().stackKind();
+            setResult(local, emitMove(param));
         }
     }
 
@@ -1205,7 +1208,7 @@
             // XIR instruction is only needed when the operand is not a constant!
             append(StandardOpcode.XIR.create(snippet, operandsArray, allocatedResultOperand,
                     inputOperandArray, tempOperandArray, inputOperandIndicesArray, tempOperandIndicesArray,
-                    (operandsArray[resultOperand.index] == IllegalValue) ? -1 : resultOperand.index,
+                    (allocatedResultOperand == IllegalValue) ? -1 : resultOperand.index,
                     info, infoAfter, method));
             if (GraalOptions.Meter) {
                 context.metrics.LIRXIRInstructions++;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java	Tue Jan 03 18:42:32 2012 -0800
@@ -54,7 +54,7 @@
                              RiMethod method) {
         // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands
         // are used at any time, even when the temp operands and the actual output operands have already be assigned.
-        super(opcode, new CiValue[] {outputOperand}, info, LIRInstruction.NO_OPERANDS, inputs, temps);
+        super(opcode, isLegal(outputOperand) ? new CiValue[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps);
         this.infoAfter = infoAfter;
         this.method = method;
         this.snippet = snippet;
@@ -62,6 +62,7 @@
         this.tempOperandIndices = tempOperandIndices;
         this.outputOperandIndex = outputOperandIndex;
         this.originalOperands = originalOperands;
+        assert isLegal(outputOperand) || outputOperandIndex == -1;
     }
 
 
@@ -108,7 +109,7 @@
         StringBuilder sb = new StringBuilder();
         sb.append("XIR: ");
 
-        if (isLegal(output(0))) {
+        if (operandCount(LIRInstruction.OperandMode.Output) > 0) {
             sb.append(output(0) + " = ");
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java	Tue Jan 03 18:41:01 2012 -0800
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java	Tue Jan 03 18:42:32 2012 -0800
@@ -24,11 +24,12 @@
 
 import java.util.*;
 
+import com.oracle.max.cri.ci.CiTargetMethod.Mark;
 import com.oracle.max.cri.ci.*;
-import com.oracle.max.cri.ci.CiTargetMethod.*;
 import com.oracle.max.cri.ri.*;
+import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
 import com.oracle.max.cri.xir.*;
-import com.oracle.max.cri.xir.CiXirAssembler.*;
+import com.oracle.max.graal.compiler.asm.*;
 
 public class StandardOpcode {
     // Checkstyle: stop
@@ -40,6 +41,7 @@
     public static LIROpcode JUMP;
     public static ReturnOpcode RETURN;
     public static XirOpcode XIR;
+    public static ParametersOpcode PARAMS = ParametersOpcode.PARAMS;
     // Checkstyle: resume
 
     public interface MoveOpcode extends LIROpcode {
@@ -62,4 +64,19 @@
         LIRInstruction create(XirSnippet snippet, CiValue[] operands, CiValue outputOperand, CiValue[] inputs, CiValue[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
                         LIRDebugInfo info, LIRDebugInfo infoAfter, RiMethod method);
     }
+
+
+    public enum ParametersOpcode implements LIROpcode {
+        @SuppressWarnings("hiding")
+        PARAMS;
+
+        public LIRInstruction create(CiValue[] params) {
+            return new LIRInstruction(this, params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) {
+                @Override
+                public void emitCode(TargetMethodAssembler tasm) {
+                    // No code to emit. This is not the actual method prologue, but only a meta-instruction that defines the incoming method parameters.
+                }
+            };
+        }
+    }
 }