# HG changeset patch # User Christian Wimmer # Date 1325981107 28800 # Node ID b019b2ebe03ef795ab49a727f6297955f2ae1df5 # Parent 75c620f90ab9f2add893e550f4b839d8ae500dc3# Parent a69889e5a8a57d9d54c1c1c30d3c2a5446fa9b4d Merge diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java --- a/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.cri/src/com/oracle/max/cri/ci/CiValueUtil.java Sat Jan 07 16:05:07 2012 -0800 @@ -47,6 +47,11 @@ return value instanceof CiConstant; } + public static CiConstant asConstant(CiValue value) { + assert value != null; + return (CiConstant) value; + } + public static boolean isStackSlot(CiValue value) { assert value != null; diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/DataFlowAnalysis.java Sat Jan 07 16:05:07 2012 -0800 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.alloc.simple; +import static com.oracle.max.graal.compiler.lir.LIRPhiMapping.*; import static com.oracle.max.graal.alloc.util.ValueUtil.*; import java.util.*; @@ -98,13 +99,13 @@ if (entry == null) { // Nothing to do } else if (entry instanceof CiValue) { - CiValue newValue = proc.doValue((CiValue) entry); + CiValue newValue = proc.doValue((CiValue) entry, null, null); assert newValue == entry : "procedure does not allow to change values"; } else { CiValue[] values = (CiValue[]) entry; for (int i = 0; i < values.length; i++) { if (values[i] != null) { - CiValue newValue = proc.doValue(values[i]); + CiValue newValue = proc.doValue(values[i], null, null); assert newValue == values[i] : "procedure does not allow to change values"; } } @@ -161,11 +162,11 @@ private int curOpId; private void backwardDataFlow() { - ValueProcedure inputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } }; - ValueProcedure aliveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } }; - ValueProcedure phiInputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, -1); } }; - 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); } }; + ValueProcedure inputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId); } }; + ValueProcedure aliveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, curOpId + 1); } }; + PhiValueProcedure phiInputProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return use(value, -1); } }; + 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); } }; blockLiveIn = new BitSet[blocks().size()]; registerLive = new BitSet(); diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/ResolveDataFlow.java Sat Jan 07 16:05:07 2012 -0800 @@ -48,7 +48,7 @@ public void execute() { ValueProcedure locMappingProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return locMapping(value); } }; - PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public void doValue(CiValue input, CiValue output) { phiMapping(input, output); } }; + PhiValueProcedure phiMappingProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue input, CiValue output) { return phiMapping(input, output); } }; trace(1, "==== start resolve data flow ===="); for (LIRBlock toBlock : lir.linearScanOrder()) { @@ -86,11 +86,12 @@ return value; } - private void phiMapping(CiValue input, CiValue output) { + private CiValue phiMapping(CiValue input, CiValue output) { Location to = asLocation(output); if (input != to) { moveResolver.add(input, to); } + return input; } private void findInsertPos(LIRBlock fromBlock, LIRBlock toBlock) { diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/simple/SpillAllAllocator.java Sat Jan 07 16:05:07 2012 -0800 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.alloc.simple; +import static com.oracle.max.graal.compiler.lir.LIRPhiMapping.*; import static com.oracle.max.cri.ci.CiValueUtil.*; import static com.oracle.max.graal.alloc.util.ValueUtil.*; @@ -34,7 +35,7 @@ import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; +import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; @@ -134,40 +135,34 @@ assert LIRVerifier.verify(true, lir, frameMap, registerConfig); dataFlow.execute(); - allocate(); + frameMap.finish(); context.observable.fireCompilationEvent("After spill all allocation", lir); - frameMap.finish(); - ResolveDataFlow resolveDataFlow = new ResolveDataFlowImpl(lir, moveResolver); resolveDataFlow.execute(); context.observable.fireCompilationEvent("After resolve data flow", lir); - 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, frameMap, registerConfig); } private void allocate() { - ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; - ValueProcedure killBeginProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } }; - ValueProcedure killEndProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } }; - ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } }; - ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; - ValueProcedure inputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return load(value, false); } }; - ValueProcedure aliveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return load(value, true); } }; - ValueProcedure tempProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return spill(value, true); } }; - ValueProcedure outputProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return spill(value, false); } }; - ValueProcedure useSlotProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } }; - ValueProcedure defSlotProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return defSlot(value); } }; + ValueProcedure killNonLiveProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killNonLive(value); } }; + ValueProcedure killBeginProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, false); } }; + ValueProcedure killEndProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return kill(value, true); } }; + ValueProcedure killLocationProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return killLocation(value); } }; + ValueProcedure blockProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return block(value); } }; + ValueProcedure loadProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return load(value, mode, flags); } }; + ValueProcedure spillProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return spill(value, mode, flags); } }; + PhiValueProcedure useSlotProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value) { return useSlot(value); } }; + ValueProcedure defSlotProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value) { return defSlot(value); } }; trace(1, "==== start spill all allocation ===="); curInRegisterState = new Object[maxRegisterNum()]; @@ -209,8 +204,8 @@ moveResolver.init(block.lir(), opIdx); // Process Alive before Input because they are more restricted and the same variable can be Alive and Input. - op.forEachAlive(aliveProc); - op.forEachInput(inputProc); + op.forEachAlive(loadProc); + op.forEachInput(loadProc); moveResolver.resolve(); op.forEachState(useSlotProc); @@ -218,8 +213,8 @@ assert !op.hasCall() || checkNoCallerSavedRegister() : "caller saved register in use accross call site"; moveResolver.init(block.lir(), opIdx + 1); - op.forEachTemp(tempProc); - op.forEachOutput(outputProc); + op.forEachTemp(spillProc); + op.forEachOutput(spillProc); moveResolver.resolve(); dataFlow.forEachKilled(op, true, killEndProc); @@ -315,7 +310,11 @@ return value; } - private CiValue load(CiValue value, boolean isAlive) { + private CiValue load(CiValue value, OperandMode mode, EnumSet flags) { + assert mode == OperandMode.Input || mode == OperandMode.Alive; + if (flags.contains(OperandFlag.Stack)) { + return useSlot(value); + } if (isVariable(value)) { trace(3, " load %s", value); Location regLoc = curRegisterLocations.get(asVariable(value)); @@ -323,7 +322,7 @@ // This variable has already been processed before. trace(3, " found location %s", regLoc); } else { - regLoc = allocateRegister(asVariable(value), curInRegisterState, isAlive ? curOutRegisterState : null); + regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.Alive ? curOutRegisterState : null, mode, flags); Location stackLoc = curStackLocations.get(asVariable(value)); assert stackLoc != null; moveResolver.add(stackLoc, regLoc); @@ -335,12 +334,16 @@ } } - private CiValue spill(CiValue value, boolean isTemp) { + private CiValue spill(CiValue value, OperandMode mode, EnumSet flags) { + assert mode == OperandMode.Temp || mode == OperandMode.Output; + if (flags.contains(OperandFlag.Stack)) { + return defSlot(value); + } if (isVariable(value)) { trace(3, " spill %s", value); assert curStackLocations.get(asVariable(value)) == null; - Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState); - if (!isTemp) { + Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags); + if (mode == OperandMode.Output) { Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind)); curStackLocations.put(stackLoc); moveResolver.add(regLoc, stackLoc); @@ -377,28 +380,59 @@ } } - private Location allocateRegister(Variable variable, Object[] inRegisterState, Object[] outRegisterState) { + private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet flags) { + if (flags.contains(OperandFlag.RegisterHint)) { + CiValue result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() { + @Override + public CiValue doValue(CiValue registerHint) { + trace(3, " registerHint %s", registerHint); + CiRegister hint = null; + if (isRegister(registerHint)) { + hint = asRegister(registerHint); + } else if (isLocation(registerHint) && isRegister(asLocation(registerHint).location)) { + hint = asRegister(asLocation(registerHint).location); + } + if (hint != null && hint.isSet(variable.flag) && isFree(hint, inRegisterState, outRegisterState)) { + return selectRegister(hint, variable, inRegisterState, outRegisterState); + } + return null; + } + }); + + if (result != null) { + return asLocation(result); + } + } + EnumMap categorizedRegs = registerConfig.getCategorizedAllocatableRegisters(); CiRegister[] availableRegs = categorizedRegs.get(variable.flag); for (CiRegister reg : availableRegs) { - if ((inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null)) { - Location loc = new Location(variable, reg.asValue(variable.kind)); - if (inRegisterState != null) { - inRegisterState[reg.number] = loc; - } - if (outRegisterState != null) { - outRegisterState[reg.number] = loc; - } - assert curRegisterLocations.get(variable) == null; - curRegisterLocations.put(loc); - trace(3, " selected register %s", loc); - return loc; + if (isFree(reg, inRegisterState, outRegisterState)) { + return selectRegister(reg, variable, inRegisterState, outRegisterState); } + } throw new CiBailout("No register found"); } + private static boolean isFree(CiRegister reg, Object[] inRegisterState, Object[] outRegisterState) { + return (inRegisterState == null || inRegisterState[reg.number] == null) && (outRegisterState == null || outRegisterState[reg.number] == null); + } + + private Location selectRegister(CiRegister reg, Variable variable, Object[] inRegisterState, Object[] outRegisterState) { + Location loc = new Location(variable, reg.asValue(variable.kind)); + if (inRegisterState != null) { + inRegisterState[reg.number] = loc; + } + if (outRegisterState != null) { + outRegisterState[reg.number] = loc; + } + assert curRegisterLocations.get(variable) == null; + curRegisterLocations.put(loc); + trace(3, " selected register %s", loc); + return loc; + } private boolean checkInputState(final LIRBlock block) { final BitSet liveState = new BitSet(); @@ -422,19 +456,9 @@ return true; } -// private boolean checkBlocked(CiValue value, Object[] inRegisterState, Object[] outRegisterState) { -// if (isAllocatableRegister(value)) { -// int regNum = asRegister(value).number; -// assert inRegisterState == null || inRegisterState[regNum] instanceof LIRInstruction; -// } -// return !isAllocatableRegister(value) || asRegister(curRegisterState[asRegister(value).number]) == asRegister(value); -// } -// private boolean checkNoCallerSavedRegister() { for (CiRegister reg : registerConfig.getCallerSaveRegisters()) { assert curOutRegisterState[reg.number] == null || curOutRegisterState[reg.number] == curInstruction : "caller saved register in use accross call site"; - // TODO check if that assertion holds, otherwise the code below is necessary (outside of an assertion!) - // curRegisterState[reg.number] = null; } return true; } diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LIRVerifier.java Sat Jan 07 16:05:07 2012 -0800 @@ -31,7 +31,10 @@ import com.oracle.max.cri.ri.*; import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; +import com.oracle.max.graal.compiler.lir.LIRPhiMapping.PhiValueProcedure; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; @@ -60,6 +63,16 @@ return isRegister(value) && registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable; } + public static boolean verify(final LIRInstruction op) { + ValueProcedure allowedProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return allowed(op, value, mode, flags); } }; + + op.forEachInput(allowedProc); + op.forEachAlive(allowedProc); + op.forEachState(allowedProc); + op.forEachTemp(allowedProc); + op.forEachOutput(allowedProc); + return true; + } public static boolean verify(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap, RiRegisterConfig registerConfig) { LIRVerifier verifier = new LIRVerifier(beforeRegisterAllocation, lir, frameMap, registerConfig); @@ -67,6 +80,7 @@ return true; } + private LIRVerifier(boolean beforeRegisterAllocation, LIR lir, FrameMap frameMap, RiRegisterConfig registerConfig) { this.beforeRegisterAllocation = beforeRegisterAllocation; this.lir = lir; @@ -83,9 +97,8 @@ private Object curInstruction; 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); } }; + PhiValueProcedure useProc = new PhiValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return use(value, mode, flags); } }; + ValueProcedure defProc = new ValueProcedure() { @Override public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { return def(value, mode, flags); } }; for (LIRBlock block : lir.linearScanOrder()) { curBlock = block; @@ -96,13 +109,10 @@ curVariablesLive.or(liveOutFor(block.dominator())); } - if (beforeRegisterAllocation) { - if (block.phis != null) { - curInstruction = block.phis; - block.phis.forEachOutput(outputProc); - } - } else { - assert block.phis == null; + if (block.phis != null) { + assert beforeRegisterAllocation; + curInstruction = block.phis; + block.phis.forEachOutput(defProc); } for (LIRInstruction op : block.lir()) { @@ -116,17 +126,27 @@ } op.forEachAlive(useProc); op.forEachState(useProc); - op.forEachTemp(tempProc); - op.forEachOutput(outputProc); + op.forEachTemp(defProc); + op.forEachOutput(defProc); curInstruction = null; } + for (LIRBlock sux : block.getLIRSuccessors()) { + if (sux.phis != null) { + assert beforeRegisterAllocation; + curInstruction = sux.phis; + sux.phis.forEachInput(block, useProc); + } + } + setLiveOutFor(block, curVariablesLive); } } - private CiValue use(CiValue value) { + private CiValue use(CiValue value, OperandMode mode, EnumSet flags) { + allowed(curInstruction, value, mode, flags); + if (beforeRegisterAllocation && isVariable(value)) { int variableIdx = asVariable(value).index; if (!curVariablesLive.get(variableIdx)) { @@ -147,23 +167,13 @@ TTY.println("ERROR: Use of fixed register %s that is not defined in this block", value); throw Util.shouldNotReachHere(); } - } else if (isRegister(value)) { - // Register usage cannot be checked. - } else if (isStackSlot(value)) { - // TODO check if stack slot is allowed for this operand. - } else if (isConstant(value)) { - // TODO check if constant is allowed for this operand. - } else if (value == CiValue.IllegalValue) { - // TODO check if illegal is allowed for this operand. - } else { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); - throw Util.shouldNotReachHere(); } return value; } - private CiValue def(CiValue value, boolean isTemp) { + private CiValue def(CiValue value, OperandMode mode, EnumSet flags) { + allowed(curInstruction, value, mode, flags); + if (beforeRegisterAllocation && isVariable(value)) { int variableIdx = asVariable(value).index; if (variableDefinitions[variableIdx] != null) { @@ -176,26 +186,32 @@ assert curInstruction != null; variableDefinitions[variableIdx] = curInstruction; assert !curVariablesLive.get(variableIdx); - if (!isTemp) { + if (mode == OperandMode.Output) { curVariablesLive.set(variableIdx); } } else if (beforeRegisterAllocation && isAllocatableRegister(value)) { int regNum = asRegister(value).number; - if (isTemp) { + if (mode == OperandMode.Output) { + curRegistersLive[regNum] = value; + } else { curRegistersLive[regNum] = null; - } else { - curRegistersLive[regNum] = value; } - } else if (isRegister(value)) { - // Register definition cannot be checked. - } else if (isStackSlot(value)) { - // TODO check if stack slot is allowed for this operand. - } else { - TTY.println("block %s instruction %s", curBlock, curInstruction); - TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); - throw Util.shouldNotReachHere(); } return value; } + + private static CiValue allowed(Object op, CiValue value, OperandMode mode, EnumSet flags) { + if ((isVariable(value) && flags.contains(OperandFlag.Register)) || + (isRegister(value) && flags.contains(OperandFlag.Register)) || + (isStackSlot(value) && flags.contains(OperandFlag.Stack)) || + (isConstant(value) && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) || + (isIllegal(value) && flags.contains(OperandFlag.Illegal))) { + return value; + } + TTY.println("instruction %s", op); + TTY.println("mode: %s flags: %s", mode, flags); + TTY.println("Unexpected value: %s %s", value.getClass().getSimpleName(), value); + throw Util.shouldNotReachHere(); + } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/LocationMap.java Sat Jan 07 16:05:07 2012 -0800 @@ -57,7 +57,7 @@ public void forEachLocation(ValueProcedure proc) { for (int i = 0; i < locations.length; i++) { if (locations[i] != null) { - CiValue newValue = proc.doValue(locations[i]); + CiValue newValue = proc.doValue(locations[i], null, null); assert newValue == null || asLocation(newValue).variable == locations[i].variable; locations[i] = (Location) newValue; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Sat Jan 07 16:05:07 2012 -0800 @@ -292,14 +292,14 @@ } else { trace(3, "mr MOV %s -> %s", src, dst); - insertionBuffer.append(insertPos, StandardOpcode.MOVE.create(dst, src)); + insertionBuffer.append(insertPos, StandardOpcode.SPILL_MOVE.create(dst, src)); } } /** - * Provides a register that can be used by the move resolver. If the returned value is a + * Provides a register that can be used by the move resolver. If the returned value is a * {@link CiRegisterValue}, the register can be overwritten without precautions. If the - * returned value is a {@link Location}, it needs to be spilled and rescued itself. + * returned value is a {@link Location}, it needs to be spilled and rescued itself. */ protected abstract CiValue scratchRegister(Variable spilled); diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/ControlFlowOptimizer.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.schedule.*; @@ -45,7 +44,7 @@ //optimizer.reorderShortLoops(code); optimizer.deleteEmptyBlocks(code); ControlFlowOptimizer.deleteUnnecessaryJumps(code); - ControlFlowOptimizer.deleteJumpsToReturn(code); + //ControlFlowOptimizer.deleteJumpsToReturn(code); } private final LIR ir; @@ -175,6 +174,7 @@ assert verify(code); } +/* private static void deleteJumpsToReturn(List code) { for (int i = code.size() - 1; i >= 0; i--) { LIRBlock block = code.get(i); @@ -212,6 +212,7 @@ } } } +*/ private static boolean verify(List code) { for (LIRBlock block : code) { diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/EdgeMoveOptimizer.java Sat Jan 07 16:05:07 2012 -0800 @@ -88,8 +88,10 @@ assert op1 != null; assert op2 != null; - if (op1.code == StandardOpcode.MOVE && op2.code == StandardOpcode.MOVE) { - if (op1.info == op2.info && op1.input(0).equals(op2.input(0)) && op1.output(0).equals(op2.output(0))) { + if (op1 instanceof MoveInstruction && op2 instanceof MoveInstruction) { + MoveInstruction move1 = (MoveInstruction) op1; + MoveInstruction move2 = (MoveInstruction) op2; + if (move1.getSource() == move2.getSource() && move1.getDest() == move2.getDest()) { // these moves are exactly equal and can be optimized return true; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Sat Jan 07 16:05:07 2012 -0800 @@ -37,8 +37,7 @@ import com.oracle.max.graal.compiler.alloc.Interval.SpillState; import com.oracle.max.graal.compiler.gen.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; -import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; +import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; @@ -464,18 +463,17 @@ int opId = op.id(); if (opId == -1) { - CiValue resultOperand = op.output(0); + MoveInstruction move = (MoveInstruction) op; // remove move from register to stack if the stack slot is guaranteed to be correct. // only moves that have been inserted by LinearScan can be removed. - assert op.code == StandardOpcode.MOVE : "only moves can have a opId of -1"; - assert isVariable(resultOperand) : "LinearScan inserts only moves to variables"; + assert isVariable(move.getDest()) : "LinearScan inserts only moves to variables"; - Interval curInterval = intervalFor(resultOperand); + Interval curInterval = intervalFor(move.getDest()); if (!isRegister(curInterval.location()) && curInterval.alwaysInMemory()) { // move target is a stack slot that is always correct, so eliminate instruction if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("eliminating move from interval %d to %d", operandNumber(op.input(0)), operandNumber(op.output(0))); + TTY.println("eliminating move from interval %d to %d", operandNumber(move.getSource()), operandNumber(move.getDest())); } instructions.set(j, null); // null-instructions are deleted by assignRegNum } @@ -497,7 +495,7 @@ assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + interval.spillState(); assert isStackSlot(toLocation) : "to operand must be a stack slot"; - insertionBuffer.append(j + 1, StandardOpcode.MOVE.create(toLocation, fromLocation)); + insertionBuffer.append(j + 1, StandardOpcode.SPILL_MOVE.create(toLocation, fromLocation)); if (GraalOptions.TraceLinearScanLevel >= 4) { CiStackSlot slot = interval.spillSlot(); @@ -613,11 +611,11 @@ int numBlocks = blockCount(); int liveSize = liveSetSize(); - BitMap2D localIntervalInLoop = new BitMap2D(operandSize(), numLoops()); + intervalInLoop = new BitMap2D(operandSize(), numLoops()); // iterate all blocks for (int i = 0; i < numBlocks; i++) { - LIRBlock block = blockAt(i); + final LIRBlock block = blockAt(i); final BitMap liveGen = new BitMap(liveSize); final BitMap liveKill = new BitMap(liveSize); @@ -629,107 +627,68 @@ for (int j = 1; j < numInst; j++) { final LIRInstruction op = instructions.get(j); - // iterate input operands of instruction - int n = op.operandCount(LIRInstruction.OperandMode.Input); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k); - - if (isVariable(operand)) { - int operandNum = operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" Setting liveGen for operand %d at instruction %d", operandNum, op.id()); + ValueProcedure useProc = new ValueProcedure() { + @Override + protected CiValue doValue(CiValue operand) { + if (isVariable(operand)) { + int operandNum = operandNumber(operand); + if (!liveKill.get(operandNum)) { + liveGen.set(operandNum); + if (GraalOptions.TraceLinearScanLevel >= 4) { + TTY.println(" Setting liveGen for operand %d at instruction %d", operandNum, op.id()); + } + } + if (block.loopIndex() >= 0) { + intervalInLoop.setBit(operandNum, block.loopIndex()); } } - if (block.loopIndex() >= 0) { - localIntervalInLoop.setBit(operandNum, block.loopIndex()); + + if (GraalOptions.DetailedAsserts) { + verifyInput(block, liveKill, operand); } - } - - if (GraalOptions.DetailedAsserts) { - verifyInput(block, liveKill, operand); + return operand; } - } - - n = op.operandCount(LIRInstruction.OperandMode.Alive); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Alive, k); - - if (isVariable(operand)) { + }; + ValueProcedure stateProc = new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand) { int operandNum = operandNumber(operand); if (!liveKill.get(operandNum)) { liveGen.set(operandNum); if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" Setting liveGen for operand %d at instruction %d", operandNum, op.id()); + TTY.println(" Setting liveGen for LIR opId %d, operand %d because of state for %s", op.id(), operandNum, op); + } + } + return operand; + } + }; + ValueProcedure defProc = new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand) { + if (isVariable(operand)) { + int varNum = operandNumber(operand); + liveKill.set(varNum); + if (block.loopIndex() >= 0) { + intervalInLoop.setBit(varNum, block.loopIndex()); } } - if (block.loopIndex() >= 0) { - localIntervalInLoop.setBit(operandNum, block.loopIndex()); - } - } - - if (GraalOptions.DetailedAsserts) { - verifyInput(block, liveKill, operand); - } - } - - // Add uses of live locals from interpreter's point of view for proper debug information generation - LIRDebugInfo info = op.info; - if (info != null) { - info.forEachState(new ValueProcedure() { - @Override - public CiValue doValue(CiValue operand) { - int operandNum = operandNumber(operand); - if (!liveKill.get(operandNum)) { - liveGen.set(operandNum); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println(" Setting liveGen for LIR opId %d, operand %d because of state for %s", op.id(), operandNum, op); - } - } - return operand; - } - }); - } - - // iterate temp operands of instruction - n = op.operandCount(LIRInstruction.OperandMode.Temp); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k); - if (isVariable(operand)) { - int varNum = operandNumber(operand); - liveKill.set(varNum); - if (block.loopIndex() >= 0) { - localIntervalInLoop.setBit(varNum, block.loopIndex()); + if (GraalOptions.DetailedAsserts) { + // fixed intervals are never live at block boundaries, so + // they need not be processed in live sets + // process them only in debug mode so that this can be checked + verifyTemp(liveKill, operand); } + return operand; } - - if (GraalOptions.DetailedAsserts) { - verifyTemp(liveKill, operand); - } - } + }; - // iterate output operands of instruction - n = op.operandCount(LIRInstruction.OperandMode.Output); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k); - - if (isVariable(operand)) { - int varNum = operandNumber(operand); - liveKill.set(varNum); - if (block.loopIndex() >= 0) { - localIntervalInLoop.setBit(varNum, block.loopIndex()); - } - } - - if (GraalOptions.DetailedAsserts) { - // fixed intervals are never live at block boundaries, so - // they need not be processed in live sets - // process them only in debug mode so that this can be checked - verifyTemp(liveKill, operand); - } - } + op.forEachInput(useProc); + op.forEachAlive(useProc); + // Add uses of live locals from interpreter's point of view for proper debug information generation + op.forEachState(stateProc); + op.forEachTemp(defProc); + op.forEachOutput(defProc); } // end of instruction iteration block.liveGen = liveGen; @@ -742,8 +701,6 @@ TTY.println("liveKill B%d %s", block.blockID(), block.liveKill); } } // end of block iteration - - intervalInLoop = localIntervalInLoop; } private void verifyTemp(BitMap liveKill, CiValue operand) { @@ -877,6 +834,7 @@ LIRDebugInfo info = ins.info; if (info != null) { info.forEachState(new ValueProcedure() { + @Override public CiValue doValue(CiValue liveStateOperand) { TTY.println(" operand=" + liveStateOperand); return liveStateOperand; @@ -944,6 +902,9 @@ if (!isProcessed(operand)) { return; } + if (GraalOptions.TraceLinearScanLevel >= 2) { + TTY.println(" temp %s tempPos %d (%s)", operand, tempPos, RegisterPriority.MustHaveRegister.name()); + } Interval interval = intervalFor(operand); if (interval == null) { interval = createInterval(operand); @@ -1019,8 +980,9 @@ * Determines the register priority for an instruction's output/result operand. */ static RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op) { - if (op.code == StandardOpcode.MOVE) { - if (isStackSlot(op.input(0)) && op.input(0).kind != CiKind.Object) { + if (op instanceof MoveInstruction) { + MoveInstruction move = (MoveInstruction) op; + if (isStackSlot(move.getSource()) && move.getSource().kind != CiKind.Object) { // method argument (condition must be equal to handleMethodArguments) return RegisterPriority.None; } @@ -1033,16 +995,8 @@ /** * Determines the priority which with an instruction's input operand will be allocated a register. */ - static RegisterPriority registerPriorityOfInputOperand(LIRInstruction op, int operandIndex) { - if (op.code == StandardOpcode.MOVE) { - if (isVariableOrRegister(op.input(0)) && isVariableOrRegister(op.output(0))) { - // The input operand is not forced to a register (moves from stack to register are allowed), - // but it is faster if the input operand is in a register - return RegisterPriority.ShouldHaveRegister; - } - } - - if (op.inputCanBeMemory(operandIndex)) { + static RegisterPriority registerPriorityOfInputOperand(EnumSet flags) { + if (flags.contains(OperandFlag.Stack)) { return RegisterPriority.ShouldHaveRegister; } // all other operands require a register @@ -1056,41 +1010,47 @@ * spill slot. */ void handleMethodArguments(LIRInstruction op) { - if (op.code == StandardOpcode.MOVE) { - if (isStackSlot(op.input(0)) && op.input(0).kind != CiKind.Object) { - CiStackSlot slot = (CiStackSlot) op.input(0); + if (op instanceof MoveInstruction) { + MoveInstruction move = (MoveInstruction) op; + if (isStackSlot(move.getSource()) && move.getSource().kind != CiKind.Object) { + CiStackSlot slot = (CiStackSlot) move.getSource(); if (GraalOptions.DetailedAsserts) { - assert op.id() > 0 : "invalid id"; - assert blockForId(op.id()).numberOfPreds() == 0 : "move from stack must be in first block"; - assert isVariable(op.output(0)) : "result of move must be a variable"; + assert move.id() > 0 : "invalid id"; + assert blockForId(move.id()).numberOfPreds() == 0 : "move from stack must be in first block"; + assert isVariable(move.getDest()) : "result of move must be a variable"; if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("found move from stack slot %s to %s", slot, op.output(0)); + TTY.println("found move from stack slot %s to %s", slot, move.getDest()); } } - Interval interval = intervalFor(op.output(0)); + Interval interval = intervalFor(move.getDest()); interval.setSpillSlot(slot); interval.assignLocation(slot); } } } - void addRegisterHints(LIRInstruction op) { - CiValue moveFrom = op.registerHint(); - if (moveFrom != null) { - CiValue moveTo = op.output(0); + void addRegisterHint(final LIRInstruction op, final CiValue target, OperandMode mode, EnumSet flags) { + if (flags.contains(OperandFlag.RegisterHint) && isVariableOrRegister(target)) { - if (isVariableOrRegister(moveTo) && isVariableOrRegister(moveFrom)) { - Interval from = intervalFor(moveFrom); - Interval to = intervalFor(moveTo); - if (from != null && to != null) { - to.setLocationHint(from); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + op.forEachRegisterHint(target, mode, new ValueProcedure() { + @Override + protected CiValue doValue(CiValue registerHint) { + if (isVariableOrRegister(registerHint)) { + Interval from = intervalFor(registerHint); + Interval to = intervalFor(target); + if (from != null && to != null) { + to.setLocationHint(from); + if (GraalOptions.TraceLinearScanLevel >= 4) { + TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + } + return registerHint; + } } + return null; } - } + }); } } @@ -1137,7 +1097,7 @@ // definitions of intervals are processed before uses assert !instructions.get(0).hasOperands() : "first operation must always be a label"; for (int j = instructions.size() - 1; j >= 1; j--) { - LIRInstruction op = instructions.get(j); + final LIRInstruction op = instructions.get(j); final int opId = op.id(); // add a temp range for each register if operation destroys caller-save registers @@ -1152,63 +1112,63 @@ } } - // visit definitions (output and temp operands) - int k; - int n; - n = op.operandCount(LIRInstruction.OperandMode.Output); - for (k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, k); - if (isVariableOrRegister(operand)) { - addDef(operand, opId, registerPriorityOfOutputOperand(op), operand.kind.stackKind()); + op.forEachOutput(new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + addDef(operand, opId, registerPriorityOfOutputOperand(op), operand.kind.stackKind()); + addRegisterHint(op, operand, mode, flags); + } + return operand; } - } - - n = op.operandCount(LIRInstruction.OperandMode.Temp); - for (k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, k); - if (isVariableOrRegister(operand)) { - if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println(" temp %s tempPos %d (%s)", operand, opId, RegisterPriority.MustHaveRegister.name()); + }); + op.forEachTemp(new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.kind.stackKind()); + addRegisterHint(op, operand, mode, flags); } - addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.kind.stackKind()); + return operand; } - } - - n = op.operandCount(LIRInstruction.OperandMode.Alive); - for (k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Alive, k); - if (isVariableOrRegister(operand)) { - addUse(operand, blockFrom, opId + 1, RegisterPriority.MustHaveRegister, operand.kind.stackKind()); + }); + op.forEachAlive(new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + RegisterPriority p = registerPriorityOfInputOperand(flags); + addUse(operand, blockFrom, opId + 1, p, operand.kind.stackKind()); + addRegisterHint(op, operand, mode, flags); + } + return operand; } - } - - // visit uses (input operands) - n = op.operandCount(LIRInstruction.OperandMode.Input); - for (k = 0; k < n; k++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, k); - if (isVariableOrRegister(operand)) { - RegisterPriority p = registerPriorityOfInputOperand(op, k); - addUse(operand, blockFrom, opId, p, operand.kind.stackKind()); + }); + op.forEachInput(new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (isVariableOrRegister(operand)) { + RegisterPriority p = registerPriorityOfInputOperand(flags); + addUse(operand, blockFrom, opId, p, operand.kind.stackKind()); + addRegisterHint(op, operand, mode, flags); + } + return operand; } - } + }); // Add uses of live locals from interpreter's point of view for proper // debug information generation // Treat these operands as temp values (if the live range is extended // to a call site, the value would be in a register at the call otherwise) - LIRDebugInfo info = op.info; - if (info != null) { - info.forEachState(new ValueProcedure() { - public CiValue doValue(CiValue operand) { - addUse(operand, blockFrom, (opId + 1), RegisterPriority.None, operand.kind.stackKind()); - return operand; - } - }); - } + op.forEachState(new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand) { + addUse(operand, blockFrom, opId + 1, RegisterPriority.None, operand.kind.stackKind()); + return operand; + } + }); // special steps for some instructions (especially moves) handleMethodArguments(op); - addRegisterHints(op); } // end of instruction iteration } // end of block iteration @@ -1760,22 +1720,26 @@ boolean hasDead = false; for (int j = 0; j < numInst; j++) { - LIRInstruction op = instructions.get(j); + final LIRInstruction op = instructions.get(j); if (op == null) { // this can happen when spill-moves are removed in eliminateSpillMoves hasDead = true; continue; } - // iterate all modes of the visitor and process all virtual operands - for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) { - int n = op.operandCount(mode); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(mode, k); + ValueProcedure assignProc = new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { if (isVariable(operand)) { - op.setOperandAt(mode, k, colorLirOperand((Variable) operand, op.id(), mode)); + return colorLirOperand((Variable) operand, op.id(), mode); } + return operand; } - } + }; + + op.forEachInput(assignProc); + op.forEachAlive(assignProc); + op.forEachTemp(assignProc); + op.forEachOutput(assignProc); if (op.info != null) { // compute reference map and debug information @@ -1783,11 +1747,9 @@ } // remove useless moves - if (op.code == StandardOpcode.MOVE) { - CiValue src = op.input(0); - CiValue dst = op.output(0); - if (dst == src || src.equals(dst)) { - // TODO: what about o.f = o.f and exceptions? + if (op instanceof MoveInstruction) { + MoveInstruction move = (MoveInstruction) op; + if (move.getSource() == move.getDest()) { instructions.set(j, null); hasDead = true; } @@ -2035,7 +1997,24 @@ } } + class CheckProcedure extends ValueProcedure { + boolean ok; + Interval curInterval; + + @Override + protected CiValue doValue(CiValue operand) { + if (isRegister(operand)) { + if (intervalFor(operand) == curInterval) { + ok = true; + } + } + return operand; + } + } + void verifyNoOopsInFixedIntervals() { + CheckProcedure checkProc = new CheckProcedure(); + Interval fixedIntervals; Interval otherIntervals; fixedIntervals = createUnhandledLists(IS_PRECOLORED_INTERVAL, null).first; @@ -2065,20 +2044,15 @@ // This interval is live out of this op so make sure // that this interval represents some value that's // referenced by this op either as an input or output. - boolean ok = false; - for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) { - int n = op.operandCount(mode); - for (int k = 0; k < n; k++) { - CiValue operand = op.operandAt(mode, k); - if (isRegister(operand)) { - if (intervalFor(operand) == interval) { - ok = true; - break; - } - } - } - } - assert ok : "fixed intervals should never be live across an oopmap point"; + checkProc.curInterval = interval; + checkProc.ok = false; + + op.forEachInput(checkProc); + op.forEachAlive(checkProc); + op.forEachTemp(checkProc); + op.forEachOutput(checkProc); + + assert checkProc.ok : "fixed intervals should never be live across an oopmap point"; } } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScanWalker.java Sat Jan 07 16:05:07 2012 -0800 @@ -820,13 +820,11 @@ } static boolean isMove(LIRInstruction op, Interval from, Interval to) { - if (op.code != StandardOpcode.MOVE) { - return false; + if (op instanceof MoveInstruction) { + MoveInstruction move = (MoveInstruction) op; + return isVariable(move.getSource()) && isVariable(move.getDest()) && move.getSource() == from.operand && move.getDest() == to.operand; } - - CiValue input = op.input(0); - CiValue result = op.output(0); - return isVariable(input) && isVariable(result) && input == from.operand && result == to.operand; + return false; } // optimization (especially for phi functions of nested loops): diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/MoveResolver.java Sat Jan 07 16:05:07 2012 -0800 @@ -199,7 +199,7 @@ CiValue fromOpr = fromInterval.operand; CiValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, StandardOpcode.MOVE.create(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, StandardOpcode.SPILL_MOVE.create(toOpr, fromOpr)); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.println("MoveResolver: inserted move from %d (%s) to %d (%s)", fromInterval.operandNumber, fromInterval.location(), toInterval.operandNumber, toInterval.location()); @@ -211,7 +211,7 @@ assert insertIdx != -1 : "must setup insert position first"; CiValue toOpr = toInterval.operand; - insertionBuffer.append(insertIdx, StandardOpcode.MOVE.create(toOpr, fromOpr)); + insertionBuffer.append(insertIdx, StandardOpcode.SPILL_MOVE.create(toOpr, fromOpr)); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.print("MoveResolver: inserted move from constant %s to %d (%s)", fromOpr, toInterval.operandNumber, toInterval.location()); diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/RegisterVerifier.java Sat Jan 07 16:05:07 2012 -0800 @@ -30,6 +30,7 @@ import com.oracle.max.criutils.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.lir.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.*; import com.oracle.max.graal.compiler.util.*; /** @@ -205,76 +206,58 @@ return true; } - void processOperations(List ops, Interval[] inputState) { + void processOperations(List ops, final Interval[] inputState) { // visit all instructions of the block for (int i = 0; i < ops.size(); i++) { - LIRInstruction op = ops.get(i); + final LIRInstruction op = ops.get(i); if (GraalOptions.TraceLinearScanLevel >= 4) { TTY.println(op.toStringWithIdPrefix()); } - // check if input operands are correct - int n = op.operandCount(LIRInstruction.OperandMode.Input); - for (int j = 0; j < n; j++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Input, j); - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Input, allocator); + ValueProcedure useProc = new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { + Interval interval = intervalAt(operand); + if (op.id() != -1) { + interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); + } + + assert checkState(inputState, interval.location(), interval.splitParent()); } - - assert checkState(inputState, interval.location(), interval.splitParent()); + return operand; } - } - n = op.operandCount(LIRInstruction.OperandMode.Alive); - for (int j = 0; j < n; j++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Alive, j); - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Input, allocator); + }; + + ValueProcedure defProc = new ValueProcedure() { + @Override + public CiValue doValue(CiValue operand, OperandMode mode, EnumSet flags) { + if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { + Interval interval = intervalAt(operand); + if (op.id() != -1) { + interval = interval.getSplitChildAtOpId(op.id(), mode, allocator); + } + + statePut(inputState, interval.location(), interval.splitParent()); } - - assert checkState(inputState, interval.location(), interval.splitParent()); + return operand; } - } + }; + // check if input operands are correct + op.forEachInput(useProc); // invalidate all caller save registers at calls if (op.hasCall()) { for (CiRegister r : allocator.compilation.registerConfig.getCallerSaveRegisters()) { statePut(inputState, r.asValue(), null); } } - + op.forEachAlive(useProc); // set temp operands (some operations use temp operands also as output operands, so can't set them null) - n = op.operandCount(LIRInstruction.OperandMode.Temp); - for (int j = 0; j < n; j++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Temp, j); - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - assert interval != null : "Could not find interval for operand " + operand; - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Temp, allocator); - } - - statePut(inputState, interval.location(), interval.splitParent()); - } - } - + op.forEachTemp(defProc); // set output operands - n = op.operandCount(LIRInstruction.OperandMode.Output); - for (int j = 0; j < n; j++) { - CiValue operand = op.operandAt(LIRInstruction.OperandMode.Output, j); - if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) { - Interval interval = intervalAt(operand); - if (op.id() != -1) { - interval = interval.getSplitChildAtOpId(op.id(), LIRInstruction.OperandMode.Output, allocator); - } - - statePut(inputState, interval.location(), interval.splitParent()); - } - } + op.forEachOutput(defProc); } } } diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Sat Jan 07 16:05:07 2012 -0800 @@ -44,6 +44,7 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirTemp; import com.oracle.max.cri.xir.*; import com.oracle.max.criutils.*; +import com.oracle.max.graal.alloc.util.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.schedule.*; @@ -258,6 +259,7 @@ public void append(LIRInstruction op) { + assert LIRVerifier.verify(op); if (GraalOptions.PrintIRWithLIR && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRCall.java Sat Jan 07 16:05:07 2012 -0800 @@ -30,6 +30,7 @@ import com.oracle.max.cri.ci.CiTargetMethod.*; import com.oracle.max.cri.ri.*; import com.oracle.max.cri.xir.CiXirAssembler.*; +import com.oracle.max.graal.compiler.util.*; /** * This class represents a call instruction; either to a {@linkplain CiRuntimeCall runtime method}, @@ -91,4 +92,14 @@ } return null; } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } else if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + throw Util.shouldNotReachHere(); + } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java Sat Jan 07 16:05:07 2012 -0800 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.lir; +import static com.oracle.max.graal.compiler.lir.LIRInstruction.*; import static com.oracle.max.graal.alloc.util.ValueUtil.*; import java.util.*; @@ -71,17 +72,22 @@ } } + /** + * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#Constant} and {@link OperandFlag#Illegal} need not be set. + */ + private static final EnumSet STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + private void processValues(CiValue[] values, ValueProcedure proc) { for (int i = 0; i < values.length; i++) { CiValue value = values[i]; if (value instanceof CiMonitorValue) { CiMonitorValue monitor = (CiMonitorValue) value; if (processed(monitor.owner)) { - monitor.owner = proc.doValue(monitor.owner); + monitor.owner = proc.doValue(monitor.owner, OperandMode.Alive, STATE_FLAGS); } } else if (processed(value)) { - values[i] = proc.doValue(value); + values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS); } } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Sat Jan 07 16:05:07 2012 -0800 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.lir; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.util.*; @@ -33,19 +35,34 @@ public static final CiValue[] NO_OPERANDS = {}; - public static final OperandMode[] OPERAND_MODES = OperandMode.values(); - /** - * Iterator interface for iterating over a list of values. + * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods. + * Clients of the class must only call the doValue method that takes additional parameters. */ - public interface ValueProcedure { + public abstract static class ValueProcedure { /** - * The iterator method. + * Iterator method to be overwritten. This version of the iterator does not take additional parameters + * to keep the signature short. * * @param value The value that is iterated. * @return The new value to replace the value that was passed in. */ - CiValue doValue(CiValue value); + protected CiValue doValue(CiValue value) { + throw Util.shouldNotReachHere("One of the doValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters about the + * processed value. + * + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + public CiValue doValue(CiValue value, OperandMode mode, EnumSet flags) { + return doValue(value); + } } @@ -82,6 +99,37 @@ } /** + * Flags for an operand. + */ + public enum OperandFlag { + /** + * The value can be a {@link CiRegisterValue}. + */ + Register, + + /** + * The value can be a {@link CiStackSlot}. + */ + Stack, + + /** + * The value can be a {@link CiConstant}. + */ + Constant, + + /** + * The value can be {@link CiValue#IllegalValue}. + */ + Illegal, + + /** + * The register allocator should try to assign a certain register to improve code quality. + * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints. + */ + RegisterHint, + } + + /** * The opcode of this instruction. */ public final LIROpcode code; @@ -152,7 +200,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th input operand. */ - public final CiValue input(int index) { + protected final CiValue input(int index) { return inputs[index]; } @@ -162,7 +210,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th alive operand. */ - public final CiValue alive(int index) { + protected final CiValue alive(int index) { return alives[index]; } @@ -172,7 +220,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th temp operand. */ - public final CiValue temp(int index) { + protected final CiValue temp(int index) { return temps[index]; } @@ -181,7 +229,7 @@ * * @return return the result operand */ - public final CiValue output(int index) { + protected final CiValue output(int index) { return outputs[index]; } @@ -196,62 +244,26 @@ return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall(); } - public final int operandCount(OperandMode mode) { - switch (mode) { - case Output: return outputs.length; - case Input: return inputs.length; - case Alive: return alives.length; - case Temp: return temps.length; - default: throw Util.shouldNotReachHere(); - } - } - - public final CiValue operandAt(OperandMode mode, int index) { - assert index < operandCount(mode); - switch (mode) { - case Output: return outputs[index]; - case Input: return inputs[index]; - case Alive: return alives[index]; - case Temp: return temps[index]; - default: throw Util.shouldNotReachHere(); - } - } - - public final void setOperandAt(OperandMode mode, int index, CiValue location) { - assert index < operandCount(mode); - assert location.kind != CiKind.Illegal; - assert operandAt(mode, index).kind == location.kind; - switch (mode) { - case Output: outputs[index] = location; break; - case Input: inputs[index] = location; break; - case Alive: alives[index] = location; break; - case Temp: temps[index] = location; break; - default: throw Util.shouldNotReachHere(); + private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + values[i] = proc.doValue(values[i], mode, flagsFor(mode, i)); } } public final void forEachInput(ValueProcedure proc) { - for (int i = 0; i < inputs.length; i++) { - inputs[i] = proc.doValue(inputs[i]); - } + forEach(inputs, OperandMode.Input, proc); } public final void forEachAlive(ValueProcedure proc) { - for (int i = 0; i < alives.length; i++) { - alives[i] = proc.doValue(alives[i]); - } + forEach(alives, OperandMode.Alive, proc); } public final void forEachTemp(ValueProcedure proc) { - for (int i = 0; i < temps.length; i++) { - temps[i] = proc.doValue(temps[i]); - } + forEach(temps, OperandMode.Temp, proc); } public final void forEachOutput(ValueProcedure proc) { - for (int i = 0; i < outputs.length; i++) { - outputs[i] = proc.doValue(outputs[i]); - } + forEach(outputs, OperandMode.Output, proc); } public final void forEachState(ValueProcedure proc) { @@ -275,22 +287,46 @@ } /** - * Used by the register allocator. The result operand of this instruction should get - * the same register assigned as the returned operand. - * @return The register hint for the output operand, or null if no register hint should be defined. + * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be + * assigned to the value. + *
+ * Subclasses can override this method. The default implementation processes all Input operands as the hints for + * an Output operand, and all Output operands as the hints for an Input operand. + * + * @param value The value the hints are needed for. + * @param mode The operand mode of the value. + * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped + * and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found. + * @return The non-null value returned by the procedure, or null. */ - public CiValue registerHint() { + public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) { + CiValue[] hints; + if (mode == OperandMode.Input) { + hints = outputs; + } else if (mode == OperandMode.Output) { + hints = inputs; + } else { + return null; + } + + for (int i = 0; i < hints.length; i++) { + CiValue result = proc.doValue(hints[i], null, null); + if (result != null) { + return result; + } + } return null; } /** - * Used by the register allocator to decide whether an input operand can be assigned a stack slot. - * Subclasses should override this method when an input can be memory. - * @param index The index of the operand in {@link #inputs}. - * @return true if the input operand with the given index can be assigned a stack slot. + * Used by the register allocator to decide which kind of location can be assigned to the operand. + * @param mode The kind of operand. + * @param index The index of the operand. + * @return The flags for the operand. */ - public boolean inputCanBeMemory(int index) { - return false; + // TODO this method will go away when we have named operands, the flags will be specified as annotations instead. + protected EnumSet flagsFor(OperandMode mode, int index) { + return EnumSet.of(OperandFlag.Register); } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRPhiMapping.java Sat Jan 07 16:05:07 2012 -0800 @@ -26,6 +26,8 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFlag; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandMode; import com.oracle.max.graal.compiler.lir.LIRInstruction.ValueProcedure; import com.oracle.max.graal.nodes.*; import com.oracle.max.graal.nodes.PhiNode.*; @@ -91,30 +93,36 @@ return inputs[block.getPredecessors().indexOf(pred)]; } - public void forEachInput(LIRBlock pred, ValueProcedure proc) { + private static final EnumSet INPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + private static final EnumSet OUTPUT_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + + public void forEachInput(LIRBlock pred, PhiValueProcedure proc) { CiValue[] predInputs = inputs(pred); for (int i = 0; i < predInputs.length; i++) { - predInputs[i] = proc.doValue(predInputs[i]); + predInputs[i] = proc.doValue(predInputs[i], results[i]); } } public void forEachOutput(ValueProcedure proc) { for (int i = 0; i < results.length; i++) { - results[i] = proc.doValue(results[i]); + results[i] = proc.doValue(results[i], OperandMode.Output, OUTPUT_FLAGS); } } - public void forEachInput(LIRBlock pred, PhiValueProcedure proc) { - CiValue[] predInputs = inputs(pred); - for (int i = 0; i < predInputs.length; i++) { - proc.doValue(predInputs[i], results[i]); + public abstract static class PhiValueProcedure extends ValueProcedure { + /** + * Iterator method to be overwritten. This version of the iterator has both the input and output of the phi function as parameters. + * to keep the signature short. + * + * @param input The input value that is iterated. + * @param output The output value that is iterated. + * @return The new value to replace the input value that was passed in. + */ + protected CiValue doValue(CiValue input, CiValue output) { + return doValue(input, OperandMode.Input, INPUT_FLAGS); } } - public interface PhiValueProcedure { - void doValue(CiValue input, CiValue output); - } - @Override public String toString() { return "PhiMapping for " + block + ": " + Arrays.toString(results); diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRXirInstruction.java Sat Jan 07 16:05:07 2012 -0800 @@ -65,6 +65,13 @@ assert isLegal(outputOperand) || outputOperandIndex == -1; } + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Alive || mode == OperandMode.Temp) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal); + } + return super.flagsFor(mode, index); + } public void setFalseSuccessor(LabelRef falseSuccessor) { this.falseSuccessor = falseSuccessor; @@ -96,69 +103,8 @@ return originalOperands; } - /** - * Prints this instruction. - */ @Override - public String operationString() { - return toString(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("XIR: "); - - if (operandCount(LIRInstruction.OperandMode.Output) > 0) { - sb.append(output(0) + " = "); - } - - sb.append(snippet.template); - sb.append("("); - for (int i = 0; i < snippet.arguments.length; i++) { - XirArgument a = snippet.arguments[i]; - if (i > 0) { - sb.append(", "); - } - if (a.constant != null) { - sb.append(a.constant); - } else { - sb.append(a.object); - } - } - sb.append(')'); - - if (method != null) { - sb.append(" method="); - sb.append(method.toString()); - } - - - for (LIRInstruction.OperandMode mode : LIRInstruction.OPERAND_MODES) { - int n = operandCount(mode); - if (mode == OperandMode.Output && n <= 1) { - // Already printed single output (i.e. result()) - continue; - } - if (n != 0) { - sb.append(' ').append(mode.name().toLowerCase()).append("=("); - HashSet operands = new HashSet<>(); - for (int i = 0; i < n; i++) { - String operand = operandAt(mode, i).toString(); - if (!operands.contains(operand)) { - if (!operands.isEmpty()) { - sb.append(", "); - } - operands.add(operand); - sb.append(operand); - } - } - sb.append(')'); - } - } - - appendDebugInfo(sb); - - return sb.toString(); + public String name() { + return "XIR: " + snippet.template; } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/MoveInstruction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/MoveInstruction.java Sat Jan 07 16:05:07 2012 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.compiler.lir; + +import com.oracle.max.cri.ci.*; + +public abstract class MoveInstruction extends LIRInstruction { + public MoveInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + super(opcode, outputs, info, inputs, alives, temps); + } + + public abstract CiValue getSource(); + public abstract CiValue getDest(); +} diff -r a69889e5a8a5 -r b019b2ebe03e 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 Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/StandardOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -30,10 +30,11 @@ import com.oracle.max.cri.xir.CiXirAssembler.XirMark; import com.oracle.max.cri.xir.*; import com.oracle.max.graal.compiler.asm.*; +import com.oracle.max.graal.compiler.util.*; public class StandardOpcode { // Checkstyle: stop - public static MoveOpcode MOVE; + public static MoveOpcode SPILL_MOVE; public static NullCheckOpcode NULL_CHECK; public static CallOpcode DIRECT_CALL; public static CallOpcode INDIRECT_CALL; @@ -45,7 +46,7 @@ // Checkstyle: resume public interface MoveOpcode extends LIROpcode { - LIRInstruction create(CiValue result, CiValue input); + MoveInstruction create(CiValue result, CiValue input); } public interface NullCheckOpcode extends LIROpcode { @@ -76,6 +77,14 @@ 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. } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } }; } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ArithmeticOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ArithmeticOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ArithmeticOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -55,13 +57,15 @@ } @Override - public boolean inputCanBeMemory(int index) { - return true; - } - - @Override - public CiValue registerHint() { - return input(0); + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64CompareOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -49,8 +51,11 @@ } @Override - public boolean inputCanBeMemory(int index) { - return index == 1; + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 1) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } + return super.flagsFor(mode, index); } }; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlowOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlowOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ControlFlowOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,12 +24,14 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.*; import com.oracle.max.asm.target.amd64.*; import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag; import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiAddress.*; -import com.oracle.max.cri.ci.CiTargetMethod.*; +import com.oracle.max.cri.ci.CiAddress.Scale; +import com.oracle.max.cri.ci.CiTargetMethod.JumpTable; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; @@ -70,6 +72,14 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { masm.ret(0); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + throw Util.shouldNotReachHere(); + } }; } } @@ -178,8 +188,13 @@ } @Override - public CiValue registerHint() { - return input(0); + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } @Override diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ConvertOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ConvertOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ConvertOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -48,8 +50,11 @@ } @Override - public CiValue registerHint() { - return input(0); + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Sat Jan 07 16:05:07 2012 -0800 @@ -63,7 +63,7 @@ private static final CiRegisterValue RCX_I = AMD64.rcx.asValue(CiKind.Int); static { - StandardOpcode.MOVE = AMD64StandardOpcode.MOVE; + StandardOpcode.SPILL_MOVE = AMD64MoveOpcode.SpillMoveOpcode.SPILL_MOVE; StandardOpcode.NULL_CHECK = AMD64StandardOpcode.NULL_CHECK; StandardOpcode.DIRECT_CALL = AMD64CallOpcode.DIRECT_CALL; StandardOpcode.INDIRECT_CALL = AMD64CallOpcode.INDIRECT_CALL; @@ -486,20 +486,28 @@ CiValue expected = loadNonConst(operand(node.expected())); Variable newValue = load(operand(node.newValue())); Variable addrBase = load(operand(node.object())); - CiValue addrIndex = loadNonConst(operand(node.offset())); + CiValue addrIndex = operand(node.offset()); + int addrDisplacement = 0; + if (isConstant(addrIndex) && NumUtil.isInt(asConstant(addrIndex).asLong())) { + addrDisplacement = (int) asConstant(addrIndex).asLong(); + addrIndex = CiValue.IllegalValue; + } else { + addrIndex = load(addrIndex); + } if (kind == CiKind.Object) { Variable loadedAddress = newVariable(compilation.compiler.target.wordKind); - append(LEA_MEMORY.create(loadedAddress, addrBase, addrIndex, CiAddress.Scale.Times1, 0)); + append(LEA_MEMORY.create(loadedAddress, addrBase, addrIndex, CiAddress.Scale.Times1, addrDisplacement)); + preGCWriteBarrier(loadedAddress, false, null); + addrBase = loadedAddress; addrIndex = Variable.IllegalValue; - - preGCWriteBarrier(addrBase, false, null); + addrDisplacement = 0; } CiRegisterValue rax = AMD64.rax.asValue(kind); append(MOVE.create(rax, expected)); - append(CAS.create(rax, addrBase, addrIndex, CiAddress.Scale.Times1, 0, rax, newValue)); + append(CAS.create(rax, addrBase, addrIndex, CiAddress.Scale.Times1, addrDisplacement, rax, newValue)); Variable result = newVariable(node.kind()); if (node.directResult()) { diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LogicFloatOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LogicFloatOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LogicFloatOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -51,13 +53,15 @@ } @Override - public boolean inputCanBeMemory(int index) { - return true; - } - - @Override - public CiValue registerHint() { - return input(0); + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MoveOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -22,10 +22,12 @@ */ package com.oracle.max.graal.compiler.target.amd64; -import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.alloc.util.ValueUtil.*; import static java.lang.Double.*; import static java.lang.Float.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -34,29 +36,126 @@ public class AMD64MoveOpcode { - public enum MoveOpcode implements StandardOpcode.MoveOpcode { + public enum MoveOpcode implements LIROpcode { MOVE; - @Override public LIRInstruction create(CiValue result, CiValue input) { assert result.kind == result.kind.stackKind() && result.kind != CiKind.Illegal; CiValue[] inputs = new CiValue[] {input}; CiValue[] outputs = new CiValue[] {result}; - return new AMD64LIRInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS) { - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - move(tasm, masm, output(0), input(0)); - } + if (isRegister(input) || isStackSlot(result)) { + return new AMD64MoveFromRegInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } else { + return new AMD64MoveToRegInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); + } + } + } - @Override - public CiValue registerHint() { - return input(0); - } - }; + public enum SpillMoveOpcode implements StandardOpcode.MoveOpcode { + SPILL_MOVE; + + @Override + public MoveInstruction create(CiValue result, CiValue input) { + assert result.kind == result.kind.stackKind() && result.kind != CiKind.Illegal; + CiValue[] inputs = new CiValue[] {input}; + CiValue[] outputs = new CiValue[] {result}; + + return new AMD64SpillMoveInstruction(this, outputs, null, inputs, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS); } } + protected static class AMD64SpillMoveInstruction extends MoveInstruction { + public AMD64SpillMoveInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + super(opcode, outputs, info, inputs, alives, temps); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); + } + + @Override + public CiValue getSource() { + return input(0); + } + @Override + public CiValue getDest() { + return output(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } + + } + + protected static class AMD64MoveToRegInstruction extends MoveInstruction { + public AMD64MoveToRegInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + super(opcode, outputs, info, inputs, alives, temps); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); + } + + @Override + public CiValue getSource() { + return input(0); + } + @Override + public CiValue getDest() { + return output(0); + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + throw Util.shouldNotReachHere(); + } + } + + protected static class AMD64MoveFromRegInstruction extends MoveInstruction { + public AMD64MoveFromRegInstruction(LIROpcode opcode, CiValue[] outputs, LIRDebugInfo info, CiValue[] inputs, CiValue[] alives, CiValue[] temps) { + super(opcode, outputs, info, inputs, alives, temps); + } + + @Override + public void emitCode(TargetMethodAssembler tasm) { + move(tasm, (AMD64MacroAssembler) tasm.asm, getDest(), getSource()); + } + + @Override + public CiValue getSource() { + return input(0); + } + @Override + public CiValue getDest() { + return output(0); + } + + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack); + } + throw Util.shouldNotReachHere(); + } + } public enum LoadOpcode implements LIROpcode { LOAD; @@ -70,6 +169,14 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { load(tasm, masm, output(0), new CiAddress(CiKind.Illegal, input(0), input(1), addrScale, addrDisplacement), kind, info); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && (index == 0 || index == 1)) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + return super.flagsFor(mode, index); + } }; } } @@ -86,6 +193,16 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { store(tasm, masm, new CiAddress(CiKind.Illegal, input(0), input(1), addrScale, addrDisplacement), input(2), kind, info); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && (index == 0 || index == 1)) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } else if (mode == OperandMode.Input && index == 2) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } + return super.flagsFor(mode, index); + } }; } } @@ -103,6 +220,14 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { masm.leaq(asLongReg(output(0)), new CiAddress(CiKind.Illegal, input(0), input(1), addrScale, addrDisplacement)); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && (index == 0 || index == 1)) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + return super.flagsFor(mode, index); + } }; } } @@ -172,11 +297,18 @@ public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { compareAndSwap(tasm, masm, output(0), new CiAddress(CiKind.Illegal, input(0), input(1), addrScale, addrDisplacement), input(2), input(3)); } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && (index == 0 || index == 1)) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal); + } + return super.flagsFor(mode, index); + } }; } } - protected static void move(TargetMethodAssembler tasm, AMD64MacroAssembler masm, CiValue result, CiValue input) { if (isRegister(input)) { if (isRegister(result)) { diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MulOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MulOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64MulOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -47,13 +49,15 @@ } @Override - public boolean inputCanBeMemory(int index) { - return index == 0; - } - - @Override - public CiValue registerHint() { - return input(0); + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } @@ -66,12 +70,14 @@ case LMUL: masm.imulq(dst, asRegister(right)); break; default: throw Util.shouldNotReachHere(); } - } else { + } else if (isConstant(right)) { switch (this) { case IMUL: masm.imull(dst, dst, tasm.asIntConst(right)); break; case LMUL: masm.imulq(dst, dst, tasm.asIntConst(right)); break; default: throw Util.shouldNotReachHere(); } + } else { + throw Util.shouldNotReachHere(); } } } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Op1Opcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Op1Opcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64Op1Opcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -45,13 +47,13 @@ } @Override - public boolean inputCanBeMemory(int index) { - return true; - } - - @Override - public CiValue registerHint() { - return input(0); + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } diff -r a69889e5a8a5 -r b019b2ebe03e graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ShiftOpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ShiftOpcode.java Sat Jan 07 23:59:54 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64ShiftOpcode.java Sat Jan 07 16:05:07 2012 -0800 @@ -24,6 +24,8 @@ import static com.oracle.max.cri.ci.CiValueUtil.*; +import java.util.*; + import com.oracle.max.asm.target.amd64.*; import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; @@ -48,13 +50,15 @@ } @Override - public boolean inputCanBeMemory(int index) { - return true; - } - - @Override - public CiValue registerHint() { - return input(0); + public EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant); + } else if (mode == OperandMode.Alive && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.Constant); + } else if (mode == OperandMode.Output && index == 0) { + return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint); + } + return super.flagsFor(mode, index); } }; } @@ -72,7 +76,7 @@ case ULSHR: masm.shrq(dst); break; default: throw Util.shouldNotReachHere(); } - } else { + } else if (isConstant(right)) { switch (this) { case ISHL: masm.shll(dst, tasm.asIntConst(right) & 31); break; case ISHR: masm.sarl(dst, tasm.asIntConst(right) & 31); break; @@ -82,6 +86,8 @@ case ULSHR: masm.shrq(dst, tasm.asIntConst(right) & 63); break; default: throw Util.shouldNotReachHere(); } + } else { + throw Util.shouldNotReachHere(); } } }