# HG changeset patch # User Christian Wimmer # Date 1325644861 28800 # Node ID bf6d8bcde8a0afe69d06f9f45816624082cc5697 # Parent 4e86f3befd6547b8f250c5d8415ddc86af2e27db Do not emit stack-to-stack moves. diff -r 4e86f3befd65 -r bf6d8bcde8a0 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 Tue Jan 03 18:36:53 2012 -0800 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java Tue Jan 03 18:41:01 2012 -0800 @@ -33,7 +33,7 @@ import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.compiler.util.*; -public final class MoveResolver { +public abstract class MoveResolver { private final FrameMap frameMap; private final int[] registersBlocked; private final Map valuesBlocked; @@ -265,10 +265,43 @@ } private void insertMove(CiValue src, Location dst) { - trace(3, "mr MOV %s -> %s", src, dst); - insertionBuffer.append(insertPos, StandardOpcode.MOVE.create(dst, src)); + if (isStackSlot(dst.location) && isLocation(src) && isStackSlot(asLocation(src).location)) { + // Move between two stack slots. We need a temporary registers. If the allocator can give + // us a free register, we need two moves: src->scratch, scratch->dst + // If the allocator cannot give us a free register (it returns a Location in this case), + // we need to spill the scratch register first, so we need four moves in total. + + CiValue scratch = scratchRegister(dst.variable); + + Location scratchSaved = null; + CiValue scratchRegister = scratch; + if (isLocation(scratch)) { + scratchSaved = new Location(asLocation(scratch).variable, frameMap.allocateSpillSlot(scratch.kind)); + insertMove(scratch, scratchSaved); + scratchRegister = asLocation(scratch).location; + } + assert isRegister(scratchRegister); + + Location scratchLocation = new Location(dst.variable, scratchRegister); + insertMove(src, scratchLocation); + insertMove(scratchLocation, dst); + + if (scratchSaved != null) { + insertMove(scratchSaved, asLocation(scratch)); + } + + } else { + trace(3, "mr MOV %s -> %s", src, dst); + insertionBuffer.append(insertPos, StandardOpcode.MOVE.create(dst, src)); + } } + /** + * 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. + */ + protected abstract CiValue scratchRegister(Variable spilled); private boolean checkEmpty() { assert insertPos == -1;