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;