# HG changeset patch # User Christian Wimmer # Date 1325644952 28800 # Node ID f282e35ea8292c68779b5ec0be27da5dfee3ebc1 # Parent bf6d8bcde8a0afe69d06f9f45816624082cc5697 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. diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java --- 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); diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java --- 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 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(); diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java --- 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())); } diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/RegisterVerifier.java --- 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 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); diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java --- 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(); } diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java --- 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); diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- 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++; diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java --- 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) + " = "); } diff -r bf6d8bcde8a0 -r f282e35ea829 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java --- 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. + } + }; + } + } }