Mercurial > hg > truffle
changeset 4211:bf6d8bcde8a0
Do not emit stack-to-stack moves.
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Tue, 03 Jan 2012 18:41:01 -0800 |
parents | 4e86f3befd65 |
children | f282e35ea829 |
files | graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/alloc/util/MoveResolver.java |
diffstat | 1 files changed, 36 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- 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<CiValue, Integer> 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;