changeset 22114:d9f3acb4a9a1

[SPARC] Implement constant loads from constant table with base register
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Sat, 27 Jun 2015 18:02:44 +0200
parents 598c75a3d1d1
children 919ea5f6486a
files graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/LargeConstantSectionTest.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLoadConstantTableBaseOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp
diffstat 42 files changed, 1053 insertions(+), 473 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Sat Jun 27 18:02:44 2015 +0200
@@ -865,7 +865,21 @@
     }
 
     public static boolean isSimm13(JavaConstant constant) {
-        return constant.isNull() || isSimm13(constant.asLong());
+        long bits;
+        switch (constant.getKind()) {
+            case Double:
+                bits = Double.doubleToRawLongBits(constant.asDouble());
+                break;
+            case Float:
+                bits = Float.floatToRawIntBits(constant.asFloat());
+                break;
+            case Object:
+                return JavaConstant.NULL_POINTER.equals(constant);
+            default:
+                bits = constant.asLong();
+                break;
+        }
+        return constant.isNull() || isSimm13(bits);
     }
 
     public static boolean isSimm13(long imm) {
@@ -1640,6 +1654,44 @@
         ld(Ldsh, src, dst);
     }
 
+    public void ld(SPARCAddress src, Register dst, int bytes, boolean signed) {
+        if (signed) {
+            switch (bytes) {
+                case 1:
+                    ldub(src, dst);
+                    break;
+                case 2:
+                    lduh(src, dst);
+                    break;
+                case 4:
+                    lduw(src, dst);
+                    break;
+                case 8:
+                    ldx(src, dst);
+                    break;
+                default:
+                    throw new InternalError();
+            }
+        } else {
+            switch (bytes) {
+                case 1:
+                    ldsb(src, dst);
+                    break;
+                case 2:
+                    ldsh(src, dst);
+                    break;
+                case 4:
+                    ldsw(src, dst);
+                    break;
+                case 8:
+                    ldx(src, dst);
+                    break;
+                default:
+                    throw new InternalError();
+            }
+        }
+    }
+
     public void ldub(SPARCAddress src, Register dst) {
         assert isCPURegister(dst) : dst;
         ld(Ldub, src, dst);
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Sat Jun 27 18:02:44 2015 +0200
@@ -42,11 +42,23 @@
     private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(g1), new ScratchRegister(g3)};
     // Points to the next free scratch register
     private int nextFreeScratchRegister = 0;
+    /**
+     * Use ld [reg+simm13], reg for loading constants (User has to make sure, that the size of the
+     * constant table does not exceed simm13).
+     */
+    private boolean immediateConstantLoad;
 
     public SPARCMacroAssembler(TargetDescription target, RegisterConfig registerConfig) {
         super(target, registerConfig);
     }
 
+    /**
+     * @see #immediateConstantLoad
+     */
+    public void setImmediateConstantLoad(boolean immediateConstantLoad) {
+        this.immediateConstantLoad = immediateConstantLoad;
+    }
+
     @Override
     public void align(int modulus) {
         while (position() % modulus != 0) {
@@ -393,6 +405,10 @@
         sra(rd, g0, rd);
     }
 
+    public boolean isImmediateConstantLoad() {
+        return immediateConstantLoad;
+    }
+
     public ScratchRegister getScratchRegister() {
         return scratchRegister[nextFreeScratchRegister++];
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Sat Jun 27 18:02:44 2015 +0200
@@ -32,13 +32,15 @@
 import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.sparc.*;
-import jdk.internal.jvmci.sparc.SPARC.*;
+import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
 
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.spi.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegConst;
@@ -57,12 +59,9 @@
 import com.oracle.graal.lir.sparc.SPARCMove.LoadDataAddressOp;
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.MembarOp;
+import com.oracle.graal.lir.sparc.SPARCMove.Move;
 import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGpVIS3;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp;
-import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp;
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
-import com.oracle.graal.lir.sparc.SPARCMove.SPARCStackMove;
 import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp;
 import com.oracle.graal.phases.util.*;
 
@@ -73,6 +72,8 @@
 
     private StackSlotValue tmpStackSlot;
     private SPARCSpillMoveFactory moveFactory;
+    private Variable constantTableBase;
+    private SPARCLoadConstantTableBaseOp loadConstantTableBaseOp;
 
     private class SPARCSpillMoveFactory implements LIRGeneratorTool.SpillMoveFactory {
 
@@ -117,17 +118,28 @@
     }
 
     protected SPARCLIRInstruction createMove(AllocatableValue dst, Value src) {
+        boolean srcIsSlot = isStackSlotValue(src);
+        boolean dstIsSlot = isStackSlotValue(dst);
         if (src instanceof SPARCAddressValue) {
             return new LoadAddressOp(dst, (SPARCAddressValue) src);
-        } else if (isRegister(src) || isStackSlotValue(dst)) {
-            return new MoveFromRegOp(dst, src);
+        } else if (src instanceof JavaConstant) {
+            JavaConstant javaConstant = (JavaConstant) src;
+            if (canInlineConstant(javaConstant)) {
+                return new SPARCMove.LoadInlineConstant(javaConstant, dst);
+            } else {
+                return new SPARCMove.LoadConstantFromTable(javaConstant, getConstantTableBase(), dst);
+            }
+        } else if (!srcIsSlot && !dstIsSlot) {
+            return new Move(dst, src);
+        } else if (srcIsSlot != dstIsSlot) {
+            return new Move(dst, src);
         } else {
-            return new MoveToRegOp(dst, src);
+            throw JVMCIError.shouldNotReachHere(src.getClass() + " " + dst.getClass());
         }
     }
 
     protected LIRInstruction createStackMove(AllocatableValue result, Value input) {
-        return new SPARCStackMove(result, input);
+        return new SPARCMove.Move(result, input);
     }
 
     @Override
@@ -265,6 +277,7 @@
         CC conditionFlags;
         Value actualTrueValue = trueValue;
         Value actualFalseValue = falseValue;
+        // TODO: (sa) Review this loadSimm11 if it is really necessary
         switch ((Kind) left.getLIRKind().getPlatformKind()) {
             case Byte:
             case Short:
@@ -367,6 +380,7 @@
                 throw JVMCIError.shouldNotReachHere();
         }
         ConditionFlag flag = SPARCControlFlow.fromCondition(conditionCode, Condition.EQ, false);
+        // TODO: (sa) Review this loadSimm11 if it is really necessary
         append(new CondMoveOp(result, conditionCode, flag, loadSimm11(trueValue), loadSimm11(falseValue)));
         return result;
     }
@@ -383,7 +397,15 @@
 
     @Override
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, newVariable(key.getLIRKind())));
+        Value scratchValue = newVariable(key.getLIRKind());
+        AllocatableValue base = AllocatableValue.ILLEGAL;
+        for (JavaConstant c : strategy.keyConstants) {
+            if (!canInlineConstant(c)) {
+                base = getConstantTableBase();
+                break;
+            }
+        }
+        append(new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue));
     }
 
     @Override
@@ -874,12 +896,13 @@
     }
 
     private void moveBetweenFpGp(AllocatableValue dst, AllocatableValue src) {
-        if (!getArchitecture().getFeatures().contains(CPUFeature.VIS3)) {
-            StackSlotValue tempSlot = getTempSlot(LIRKind.value(Kind.Long));
-            append(new MoveFpGp(dst, src, tempSlot));
+        AllocatableValue tempSlot;
+        if (getArchitecture().getFeatures().contains(CPUFeature.VIS3)) {
+            tempSlot = AllocatableValue.ILLEGAL;
         } else {
-            append(new MoveFpGpVIS3(dst, src));
+            tempSlot = getTempSlot(LIRKind.value(Kind.Long));
         }
+        append(new MoveFpGp(dst, src, tempSlot));
     }
 
     private StackSlotValue getTempSlot(LIRKind kind) {
@@ -1042,4 +1065,24 @@
         assert kind == Kind.Object || kind == Kind.Long : address + " - " + kind + " not an object!";
         append(new NullCheckOp(asAddressValue(address), state));
     }
+
+    public void emitLoadConstantTableBase() {
+        constantTableBase = newVariable(LIRKind.value(Kind.Long));
+        int nextPosition = getResult().getLIR().getLIRforBlock(getCurrentBlock()).size();
+        NoOp placeHolder = append(new NoOp(getCurrentBlock(), nextPosition));
+        loadConstantTableBaseOp = new SPARCLoadConstantTableBaseOp(constantTableBase, placeHolder);
+    }
+
+    boolean useConstantTableBase = false;
+
+    protected Variable getConstantTableBase() {
+        useConstantTableBase = true;
+        return constantTableBase;
+    }
+
+    @Override
+    public void beforeRegisterAllocation() {
+        LIR lir = getResult().getLIR();
+        loadConstantTableBaseOp.setAlive(lir, useConstantTableBase);
+    }
 }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Sat Jun 27 18:02:44 2015 +0200
@@ -121,4 +121,10 @@
     public SPARCLIRGenerator getLIRGeneratorTool() {
         return (SPARCLIRGenerator) super.getLIRGeneratorTool();
     }
+
+    @Override
+    protected void emitPrologue(StructuredGraph graph) {
+        getLIRGeneratorTool().emitLoadConstantTableBase();
+        super.emitPrologue(graph);
+    }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCDeoptimizeOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -33,11 +33,12 @@
 @Opcode("DEOPT")
 final class SPARCDeoptimizeOp extends SPARCLIRInstruction implements BlockEndOp {
     public static final LIRInstructionClass<SPARCDeoptimizeOp> TYPE = LIRInstructionClass.create(SPARCDeoptimizeOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     @State private LIRFrameState info;
 
     SPARCDeoptimizeOp(LIRFrameState info) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.info = info;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Sat Jun 27 18:02:44 2015 +0200
@@ -33,14 +33,18 @@
 import static jdk.internal.jvmci.sparc.SPARC.*;
 
 import java.util.*;
+import java.util.concurrent.*;
 
 import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.code.DataSection.Data;
+import jdk.internal.jvmci.debug.*;
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.alloc.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.hotspot.*;
@@ -52,6 +56,7 @@
 import com.oracle.graal.lir.framemap.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.sparc.SPARCLIRInstruction.SizeEstimate;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -60,10 +65,29 @@
  */
 public class SPARCHotSpotBackend extends HotSpotHostBackend {
 
+    private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE");
+    private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL");
+
     public SPARCHotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
         super(runtime, providers);
     }
 
+    private static class SizeEstimateStatistics {
+        private static final ConcurrentHashMap<String, DebugMetric> metrics = new ConcurrentHashMap<>();
+        private final String suffix;
+
+        public SizeEstimateStatistics(String suffix) {
+            super();
+            this.suffix = suffix;
+        }
+
+        public void add(Class<?> c, int count) {
+            String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix;
+            DebugMetric m = metrics.computeIfAbsent(name, (n) -> Debug.metric(n));
+            m.add(count);
+        }
+    }
+
     @Override
     public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
@@ -200,14 +224,67 @@
             Map<LIRFrameState, SaveRegistersOp> calleeSaveInfo = gen.getCalleeSaveInfo();
             updateStub(stub, definedRegisters, calleeSaveInfo, frameMap);
         }
+        assert registerSizePredictionValidator(crb);
+        return crb;
+    }
 
-        return crb;
+    /**
+     * Registers a verifier which checks if the LIRInstructions estimate of constants size is
+     * greater or equal to the actual one.
+     */
+    private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb) {
+        /**
+         * Used to hold state between beforeOp and afterOp
+         */
+        class ValidationState {
+            LIRInstruction op;
+            int constantSizeBefore;
+
+            public void before(LIRInstruction before) {
+                assert op == null : "LIRInstruction " + op + " no after call received";
+                op = before;
+                constantSizeBefore = calculateDataSectionSize(crb.compilationResult.getDataSection());
+            }
+
+            public void after(LIRInstruction after) {
+                assert after.equals(op) : "Instructions before/after don't match " + op + "/" + after;
+                int constantSizeAfter = calculateDataSectionSize(crb.compilationResult.getDataSection());
+                int actual = constantSizeAfter - constantSizeBefore;
+                if (op instanceof SPARCLIRInstruction) {
+                    SizeEstimate size = ((SPARCLIRInstruction) op).estimateSize();
+                    assert size != null : "No size prediction available for op: " + op;
+                    Class<?> c = op.getClass();
+                    CONSTANT_ESTIMATED_STATS.add(c, size.constantSize);
+                    CONSTANT_ACTUAL_STATS.add(c, actual);
+                    assert size.constantSize >= actual : "Op " + op + " exceeded estimated constant size; predicted: " + size.constantSize + " actual: " + actual;
+                } else {
+                    assert actual == 0 : "Op " + op + " emitted to DataSection without any estimate.";
+                }
+                op = null;
+                constantSizeBefore = 0;
+            }
+        }
+        final ValidationState state = new ValidationState();
+        crb.setOpCallback(op -> state.before(op), op -> state.after(op));
+        return true;
+    }
+
+    private static int calculateDataSectionSize(DataSection ds) {
+        int sum = 0;
+        for (Data d : ds) {
+            sum += d.getSize();
+        }
+        return sum;
     }
 
     @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
+        SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
+        // TODO: (sa) Fold the two traversals into one
         stuffDelayedControlTransfers(lir);
-        SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
+        int constantSize = calculateConstantSize(lir);
+        boolean canUseImmediateConstantLoad = constantSize < (1 << 13) - 1;
+        masm.setImmediateConstantLoad(canUseImmediateConstantLoad);
         FrameMap frameMap = crb.frameMap;
         RegisterConfig regConfig = frameMap.getRegisterConfig();
         HotSpotVMConfig config = getRuntime().getConfig();
@@ -272,6 +349,21 @@
         }
     }
 
+    private static int calculateConstantSize(LIR lir) {
+        int size = 0;
+        for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
+            for (LIRInstruction inst : lir.getLIRforBlock(block)) {
+                if (inst instanceof SPARCLIRInstruction) {
+                    SizeEstimate pred = ((SPARCLIRInstruction) inst).estimateSize();
+                    if (pred != null) {
+                        size += pred.constantSize;
+                    }
+                }
+            }
+        }
+        return size;
+    }
+
     private static void resetDelayedControlTransfers(LIR lir) {
         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
             for (LIRInstruction inst : lir.getLIRforBlock(block)) {
@@ -321,12 +413,6 @@
                         // We have found a non overlapping LIR instruction which can be delayed
                         ((SPARCTailDelayedLIRInstruction) inst).setDelayedControlTransfer(delayedTransfer);
                         delayedTransfer = null;
-                        // Removed the moving as it causes problems (Nullpointer exceptions)
-                        // if (!adjacent) {
-                        // // If not adjacent, we make it adjacent
-                        // instructions.remove(i);
-                        // instructions.add(delayTransferPosition - 1, inst);
-                        // }
                     }
                 }
             }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -35,6 +35,7 @@
 @Opcode("CRUNTIME_CALL_EPILOGUE")
 final class SPARCHotSpotCRuntimeCallEpilogueOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCHotSpotCRuntimeCallEpilogueOp> TYPE = LIRInstructionClass.create(SPARCHotSpotCRuntimeCallEpilogueOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(11);
 
     private final int threadLastJavaSpOffset;
     private final int threadLastJavaPcOffset;
@@ -43,7 +44,7 @@
     @Use({REG, STACK}) protected Value threadTemp;
 
     public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread, Value threadTemp) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.threadLastJavaPcOffset = threadLastJavaPcOffset;
         this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -35,6 +35,7 @@
 @Opcode("CRUNTIME_CALL_PROLOGUE")
 final class SPARCHotSpotCRuntimeCallPrologueOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
     public static final LIRInstructionClass<SPARCHotSpotCRuntimeCallPrologueOp> TYPE = LIRInstructionClass.create(SPARCHotSpotCRuntimeCallPrologueOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(10);
 
     private final int threadLastJavaSpOffset;
     private final Register thread;
@@ -42,7 +43,7 @@
     @Def({REG, STACK}) protected Value threadTemp;
 
     public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer, Value threadTemp) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.threadLastJavaSpOffset = threadLastJavaSpOffset;
         this.thread = thread;
         this.stackPointer = stackPointer;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -37,9 +37,10 @@
 @Opcode("DEOPT_CALLER")
 final class SPARCHotSpotDeoptimizeCallerOp extends SPARCHotSpotEpilogueOp {
     public static final LIRInstructionClass<SPARCHotSpotDeoptimizeCallerOp> TYPE = LIRInstructionClass.create(SPARCHotSpotDeoptimizeCallerOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(32);
 
     protected SPARCHotSpotDeoptimizeCallerOp() {
-        super(TYPE);
+        super(TYPE, SIZE);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotEpilogueOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -33,8 +33,8 @@
 abstract class SPARCHotSpotEpilogueOp extends SPARCLIRInstruction implements BlockEndOp {
     public static final LIRInstructionClass<SPARCHotSpotEpilogueOp> TYPE = LIRInstructionClass.create(SPARCHotSpotEpilogueOp.class);
 
-    protected SPARCHotSpotEpilogueOp(LIRInstructionClass<? extends LIRInstruction> c) {
-        super(c);
+    protected SPARCHotSpotEpilogueOp(LIRInstructionClass<? extends LIRInstruction> c, SizeEstimate size) {
+        super(c, size);
     }
 
     protected void leaveFrame(CompilationResultBuilder crb) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -42,6 +42,7 @@
 final class SPARCHotSpotJumpToExceptionHandlerInCallerOp extends SPARCHotSpotEpilogueOp {
 
     public static final LIRInstructionClass<SPARCHotSpotJumpToExceptionHandlerInCallerOp> TYPE = LIRInstructionClass.create(SPARCHotSpotJumpToExceptionHandlerInCallerOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(5);
 
     @Use(REG) AllocatableValue handlerInCallerPc;
     @Use(REG) AllocatableValue exception;
@@ -50,7 +51,7 @@
     private final int isMethodHandleReturnOffset;
 
     SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.handlerInCallerPc = handlerInCallerPc;
         this.exception = exception;
         this.exceptionPc = exceptionPc;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -43,11 +43,12 @@
 @Opcode("JUMP_TO_EXCEPTION_HANDLER")
 final class SPARCHotSpotJumpToExceptionHandlerOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCHotSpotJumpToExceptionHandlerOp> TYPE = LIRInstructionClass.create(SPARCHotSpotJumpToExceptionHandlerOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
     @Use(REG) AllocatableValue address;
 
     SPARCHotSpotJumpToExceptionHandlerOp(AllocatableValue address) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.address = address;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Sat Jun 27 18:02:44 2015 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static jdk.internal.jvmci.code.ValueUtil.*;
+import static jdk.internal.jvmci.hotspot.HotSpotCompressedNullConstant.*;
 import static jdk.internal.jvmci.sparc.SPARC.*;
 
 import java.util.*;
@@ -220,7 +221,7 @@
         if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) {
             return true;
         } else if (c instanceof HotSpotObjectConstant) {
-            return ((HotSpotObjectConstant) c).isCompressed();
+            return false;
         } else {
             return super.canInlineConstant(c);
         }
@@ -261,11 +262,13 @@
 
     @Override
     protected SPARCLIRInstruction createMove(AllocatableValue dst, Value src) {
-        if (src instanceof JavaConstant) {
-            return new SPARCHotSpotMove.HotSpotLoadConstantOp(dst, (JavaConstant) src);
+        Value usedSource;
+        if (COMPRESSED_NULL.equals(src)) {
+            usedSource = INT_0;
         } else {
-            return super.createMove(dst, src);
+            usedSource = src;
         }
+        return super.createMove(dst, usedSource);
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java	Sat Jun 27 18:02:44 2015 +0200
@@ -22,130 +22,27 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
-import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.common.*;
-import jdk.internal.jvmci.hotspot.*;
-import jdk.internal.jvmci.hotspot.HotSpotVMConfig.*;
-import jdk.internal.jvmci.meta.*;
-import jdk.internal.jvmci.sparc.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static jdk.internal.jvmci.code.ValueUtil.*;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.hotspot.HotSpotVMConfig.CompressEncoding;
+import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.asm.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Annul;
+import com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCAssembler.RCondition;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
 
 public class SPARCHotSpotMove {
-
-    public static final class HotSpotLoadConstantOp extends SPARCLIRInstruction implements MoveOp {
-        public static final LIRInstructionClass<HotSpotLoadConstantOp> TYPE = LIRInstructionClass.create(HotSpotLoadConstantOp.class);
-
-        @Def({REG, STACK}) private AllocatableValue result;
-        private final JavaConstant input;
-
-        public HotSpotLoadConstantOp(AllocatableValue result, JavaConstant input) {
-            super(TYPE);
-            this.result = result;
-            this.input = input;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            if (isStackSlot(result)) {
-                StackSlot ss = asStackSlot(result);
-                try (ScratchRegister s1 = masm.getScratchRegister()) {
-                    Register sr1 = s1.getRegister();
-                    loadToRegister(crb, masm, sr1.asValue(), input);
-                    try (ScratchRegister s2 = masm.getScratchRegister()) {
-                        Register sr2 = s2.getRegister();
-                        int stackBias = HotSpotGraalRuntime.runtime().getConfig().stackBias;
-                        int offset = crb.frameMap.offsetForStackSlot(ss);
-                        new SPARCMacroAssembler.Setx(offset + stackBias, sr2).emit(masm);
-                        SPARCAddress addr = new SPARCAddress(SPARC.sp, sr2);
-                        Kind resultKind = (Kind) result.getPlatformKind();
-                        switch (resultKind) {
-                            case Byte:
-                                masm.stb(sr1, addr);
-                                break;
-                            case Short:
-                                masm.sth(sr1, addr);
-                                break;
-                            case Int:
-                                masm.stw(sr1, addr);
-                                break;
-                            case Long:
-                            case Object:
-                                masm.stx(sr1, addr);
-                                break;
-                            default:
-                                throw JVMCIError.shouldNotReachHere();
-                        }
-                    }
-                }
-            } else {
-                loadToRegister(crb, masm, result, input);
-            }
-        }
-
-        private static void loadToRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, AllocatableValue dest, JavaConstant constant) {
-            assert isRegister(dest);
-            if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(constant)) {
-                masm.mov(0, asRegister(dest));
-            } else if (constant instanceof HotSpotObjectConstant) {
-                boolean compressed = ((HotSpotObjectConstant) constant).isCompressed();
-                if (crb.target.inlineObjects) {
-                    crb.recordInlineDataInCode(constant);
-                    if (compressed) {
-                        masm.sethi(0xDEADDEAD >>> 10, asRegister(dest));
-                        masm.add(asRegister(dest), 0xAD & 0x3F, asRegister(dest));
-                    } else {
-                        new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(dest), true).emit(masm);
-                    }
-                } else {
-                    JVMCIError.unimplemented();
-                }
-            } else if (constant instanceof HotSpotMetaspaceConstant) {
-                assert constant.getKind() == Kind.Int || constant.getKind() == Kind.Long;
-                boolean compressed = constant.getKind() == Kind.Int;
-                boolean isImmutable = GraalOptions.ImmutableCode.getValue();
-                boolean generatePIC = GraalOptions.GeneratePIC.getValue();
-                crb.recordInlineDataInCode(constant);
-                if (compressed) {
-                    if (isImmutable && generatePIC) {
-                        JVMCIError.unimplemented();
-                    } else {
-                        new SPARCMacroAssembler.Setx(constant.asInt(), asRegister(dest), true).emit(masm);
-                    }
-                } else {
-                    if (isImmutable && generatePIC) {
-                        JVMCIError.unimplemented();
-                    } else {
-                        new SPARCMacroAssembler.Setx(constant.asLong(), asRegister(dest), true).emit(masm);
-                    }
-                }
-            } else {
-                SPARCMove.move(crb, masm, dest, constant, SPARCDelayedControlTransfer.DUMMY);
-            }
-        }
-
-        public Value getInput() {
-            return input;
-        }
-
-        public AllocatableValue getResult() {
-            return result;
-        }
-    }
-
     public static final class CompressPointer extends SPARCLIRInstruction {
         public static final LIRInstructionClass<CompressPointer> TYPE = LIRInstructionClass.create(CompressPointer.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(5);
 
         private final CompressEncoding encoding;
         private final boolean nonNull;
@@ -155,7 +52,7 @@
         @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
 
         public CompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.input = input;
             this.baseRegister = baseRegister;
@@ -165,26 +62,29 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
-
+            Register inputRegister = asRegister(input);
             Register resReg = asRegister(result);
             if (encoding.base != 0) {
                 Register baseReg = asRegister(baseRegister);
                 if (!nonNull) {
-                    masm.cmp(resReg, baseReg);
+                    masm.cmp(inputRegister, baseReg);
                     masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg);
+                    masm.sub(resReg, baseReg, resReg);
+                } else {
+                    masm.sub(inputRegister, baseReg, resReg);
                 }
-                masm.sub(resReg, baseReg, resReg);
-            }
-
-            if (encoding.shift != 0) {
-                masm.srlx(resReg, encoding.shift, resReg);
+                if (encoding.shift != 0) {
+                    masm.srlx(resReg, encoding.shift, resReg);
+                }
+            } else {
+                masm.srlx(inputRegister, encoding.shift, resReg);
             }
         }
     }
 
     public static final class UncompressPointer extends SPARCLIRInstruction {
         public static final LIRInstructionClass<UncompressPointer> TYPE = LIRInstructionClass.create(UncompressPointer.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(4);
 
         private final CompressEncoding encoding;
         private final boolean nonNull;
@@ -194,7 +94,7 @@
         @Alive({REG, ILLEGAL}) protected AllocatableValue baseRegister;
 
         public UncompressPointer(AllocatableValue result, AllocatableValue input, AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.input = input;
             this.baseRegister = baseRegister;
@@ -204,22 +104,23 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
-
+            Register inputRegister = asRegister(input);
             Register resReg = asRegister(result);
+            Register secondaryInput;
             if (encoding.shift != 0) {
-                masm.sll(resReg, encoding.shift, resReg);
+                masm.sll(inputRegister, encoding.shift, resReg);
+                secondaryInput = resReg;
+            } else {
+                secondaryInput = inputRegister;
             }
 
             if (encoding.base != 0) {
                 if (nonNull) {
-                    masm.add(resReg, asRegister(baseRegister), resReg);
+                    masm.add(secondaryInput, asRegister(baseRegister), resReg);
                 } else {
-                    masm.cmp(resReg, resReg);
-
                     Label done = new Label();
-                    masm.bpr(RCondition.Rc_nz, Annul.ANNUL, done, BranchPredict.PREDICT_TAKEN, resReg);
-                    masm.add(asRegister(baseRegister), resReg, resReg);
+                    masm.bpr(RCondition.Rc_nz, Annul.ANNUL, done, BranchPredict.PREDICT_TAKEN, secondaryInput);
+                    masm.add(asRegister(baseRegister), secondaryInput, resReg);
                     masm.bind(done);
                 }
             }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotPatchReturnAddressOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -39,11 +39,12 @@
 @Opcode("PATCH_RETURN")
 final class SPARCHotSpotPatchReturnAddressOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCHotSpotPatchReturnAddressOp> TYPE = LIRInstructionClass.create(SPARCHotSpotPatchReturnAddressOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     @Use(REG) AllocatableValue address;
 
     SPARCHotSpotPatchReturnAddressOp(AllocatableValue address) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.address = address;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotReturnOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.hotspot.sparc;
 
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import jdk.internal.jvmci.hotspot.*;
 import jdk.internal.jvmci.meta.*;
 import jdk.internal.jvmci.sparc.*;
-import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.lir.*;
@@ -38,13 +38,14 @@
 @Opcode("RETURN")
 final class SPARCHotSpotReturnOp extends SPARCHotSpotEpilogueOp {
     public static final LIRInstructionClass<SPARCHotSpotReturnOp> TYPE = LIRInstructionClass.create(SPARCHotSpotReturnOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
     @Use({REG, ILLEGAL}) protected Value value;
     private final boolean isStub;
     private final HotSpotVMConfig config;
 
     SPARCHotSpotReturnOp(Value value, boolean isStub, HotSpotVMConfig config) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.value = value;
         this.isStub = isStub;
         this.config = config;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotSafepointOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -40,6 +40,7 @@
 @Opcode("SAFEPOINT")
 public class SPARCHotSpotSafepointOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCHotSpotSafepointOp> TYPE = LIRInstructionClass.create(SPARCHotSpotSafepointOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(9);
 
     @State protected LIRFrameState state;
     @SuppressFBWarnings(value = "BC_IMPOSSIBLE_CAST", justification = "changed by the register allocator") @Temp({OperandFlag.REG}) private AllocatableValue temp;
@@ -47,7 +48,7 @@
     private final HotSpotVMConfig config;
 
     public SPARCHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.state = state;
         this.config = config;
         this.temp = tool.newVariable(LIRKind.value(tool.target().wordKind));
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -40,11 +40,12 @@
 @Opcode("UNWIND")
 final class SPARCHotSpotUnwindOp extends SPARCHotSpotEpilogueOp {
     public static final LIRInstructionClass<SPARCHotSpotUnwindOp> TYPE = LIRInstructionClass.create(SPARCHotSpotUnwindOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(32);
 
     @Use({REG}) protected RegisterValue exception;
 
     SPARCHotSpotUnwindOp(RegisterValue exception) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.exception = exception;
     }
 
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectStaticCallOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -38,12 +38,13 @@
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectStaticCallOp extends DirectCallOp {
     public static final LIRInstructionClass<SPARCHotspotDirectStaticCallOp> TYPE = LIRInstructionClass.create(SPARCHotspotDirectStaticCallOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(8);
 
     private final InvokeKind invokeKind;
     private final HotSpotVMConfig config;
 
     SPARCHotspotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, HotSpotVMConfig config) {
-        super(TYPE, target, result, parameters, temps, state);
+        super(TYPE, SIZE, target, result, parameters, temps, state);
         assert invokeKind.isDirect();
         this.invokeKind = invokeKind;
         this.config = config;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotspotDirectVirtualCallOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -41,12 +41,13 @@
 @Opcode("CALL_DIRECT")
 final class SPARCHotspotDirectVirtualCallOp extends DirectCallOp {
     public static final LIRInstructionClass<SPARCHotspotDirectVirtualCallOp> TYPE = LIRInstructionClass.create(SPARCHotspotDirectVirtualCallOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(8);
 
     private final InvokeKind invokeKind;
     private final HotSpotVMConfig config;
 
     SPARCHotspotDirectVirtualCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, HotSpotVMConfig config) {
-        super(TYPE, target, result, parameters, temps, state);
+        super(TYPE, SIZE, target, result, parameters, temps, state);
         this.invokeKind = invokeKind;
         this.config = config;
         assert invokeKind.isIndirect();
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCIndirectCallOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -44,6 +44,7 @@
 @Opcode("CALL_INDIRECT")
 final class SPARCIndirectCallOp extends IndirectCallOp {
     public static final LIRInstructionClass<SPARCIndirectCallOp> TYPE = LIRInstructionClass.create(SPARCIndirectCallOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
     /**
      * Vtable stubs expect the metaspace Method in g5.
@@ -55,7 +56,7 @@
     private final HotSpotVMConfig config;
 
     SPARCIndirectCallOp(ResolvedJavaMethod targetMethod, Value result, Value[] parameters, Value[] temps, Value metaspaceMethod, Value targetAddress, LIRFrameState state, HotSpotVMConfig config) {
-        super(TYPE, targetMethod, result, parameters, temps, targetAddress, state);
+        super(TYPE, SIZE, targetMethod, result, parameters, temps, targetAddress, state);
         this.metaspaceMethod = metaspaceMethod;
         this.config = config;
     }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCPrefetchOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -32,12 +32,13 @@
 
 public final class SPARCPrefetchOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCPrefetchOp> TYPE = LIRInstructionClass.create(SPARCPrefetchOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     private final int instr;  // AllocatePrefetchInstr
     @Alive({COMPOSITE}) protected SPARCAddressValue address;
 
     public SPARCPrefetchOp(SPARCAddressValue address, int instr) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.address = address;
         this.instr = instr;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/backend/LargeConstantSectionTest.java	Sat Jun 27 18:02:44 2015 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015, 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.graal.jtt.backend;
+
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import jdk.internal.jvmci.options.*;
+import jdk.internal.jvmci.options.OptionValue.OverrideScope;
+import jdk.internal.org.objectweb.asm.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.directives.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.jtt.*;
+
+public class LargeConstantSectionTest extends JTTTest {
+    private static final String NAME = "LargeConstantSection";
+    private static final long LARGE_CONSTANT = 0xF0F0F0F0F0L;
+    private static LargeConstantClassLoader LOADER;
+
+    @BeforeClass
+    public static void before() {
+        LOADER = new LargeConstantClassLoader(LargeConstantSectionTest.class.getClassLoader());
+    }
+
+    public abstract static class LargeConstantAbstract {
+        public abstract long run(long i);
+    }
+
+    public static long test(LargeConstantAbstract a, long i) throws Exception {
+        return a.run(GraalDirectives.opaque(i));
+    }
+
+    public static class LargeConstantClassLoader extends ClassLoader {
+        public LargeConstantClassLoader(ClassLoader parent) {
+            super(parent);
+        }
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            if (name.equals(NAME)) {
+                int numberIfBlocks = 1100; // Each if block contains three constants
+                ClassWriter cw = new ClassWriter(0);
+                MethodVisitor mv;
+                String abstractClassName = Type.getInternalName(LargeConstantAbstract.class);
+                cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, abstractClassName, null);
+
+                mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+                mv.visitCode();
+                Label l0 = new Label();
+                mv.visitLabel(l0);
+                mv.visitVarInsn(ALOAD, 0);
+                mv.visitMethodInsn(INVOKESPECIAL, abstractClassName, "<init>", "()V", false);
+                mv.visitInsn(RETURN);
+                Label l1 = new Label();
+                mv.visitLabel(l1);
+                mv.visitMaxs(1, 1);
+                mv.visitEnd();
+
+                mv = cw.visitMethod(ACC_PUBLIC, "run", "(J)J", null, null);
+                mv.visitCode();
+                Label nextIf = new Label();
+                for (int i = 0; i < numberIfBlocks; i++) {
+                    mv.visitLabel(nextIf);
+                    mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{});
+                    mv.visitVarInsn(LLOAD, 1);
+                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i));
+                    mv.visitInsn(LCMP);
+                    nextIf = new Label();
+                    mv.visitJumpInsn(IFNE, nextIf);
+                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks));
+                    mv.visitMethodInsn(INVOKESTATIC, "com/oracle/graal/api/directives/GraalDirectives", "opaque", "(J)J", false);
+                    mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks * 2));
+                    mv.visitMethodInsn(INVOKESTATIC, "com/oracle/graal/api/directives/GraalDirectives", "opaque", "(J)J", false);
+                    mv.visitInsn(LADD);
+                    mv.visitInsn(LRETURN);
+                }
+                mv.visitLabel(nextIf);
+                mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{});
+                mv.visitInsn(LCONST_0);
+                mv.visitInsn(LRETURN);
+                Label l9 = new Label();
+                mv.visitLabel(l9);
+                mv.visitMaxs(4, 6);
+                mv.visitEnd();
+
+                cw.visitEnd();
+
+                byte[] bytes = cw.toByteArray();
+                return defineClass(name, bytes, 0, bytes.length);
+            } else {
+                return super.findClass(name);
+            }
+        }
+    }
+
+    @Test
+    public void run0() throws Exception {
+        try (OverrideScope os = OptionValue.override(GraalOptions.InlineEverything, true)) {
+            runTest("test", LOADER.findClass(NAME).newInstance(), 0L);
+        }
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Sat Jun 27 18:02:44 2015 +0200
@@ -64,6 +64,8 @@
      */
     public static final class Unary2Op extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<Unary2Op> TYPE = LIRInstructionClass.create(Unary2Op.class);
+        public static final SizeEstimate SIZE_1 = SizeEstimate.create(1);
+        public static final SizeEstimate SIZE_5 = SizeEstimate.create(5);
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG, HINT}) protected AllocatableValue result;
@@ -80,6 +82,19 @@
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             emitUnary(crb, masm, opcode, result, x, null, delayedControlTransfer);
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            switch (opcode) {
+                case F2L:
+                case F2I:
+                case D2L:
+                case D2I:
+                    return SIZE_5;
+                default:
+                    return SIZE_1;
+            }
+        }
     }
 
     /**
@@ -88,6 +103,9 @@
      */
     public static final class BinaryRegReg extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<BinaryRegReg> TYPE = LIRInstructionClass.create(BinaryRegReg.class);
+        public static final SizeEstimate SIZE_1 = SizeEstimate.create(1);
+        public static final SizeEstimate SIZE_3 = SizeEstimate.create(3);
+        public static final SizeEstimate SIZE_7 = SizeEstimate.create(7);
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG}) protected Value result;
@@ -118,6 +136,19 @@
             super.verify();
             verifyKind(opcode, result, x, y);
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            switch (opcode) {
+                case IMULCC:
+                    return SIZE_7;
+                case IUDIV:
+                case IDIV:
+                    return SIZE_3;
+                default:
+                    return SIZE_1;
+            }
+        }
     }
 
     /**
@@ -125,6 +156,7 @@
      */
     public static final class BinaryRegConst extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<BinaryRegConst> TYPE = LIRInstructionClass.create(BinaryRegConst.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG}) protected AllocatableValue result;
@@ -137,7 +169,7 @@
         }
 
         public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, Value x, JavaConstant y, LIRFrameState state) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -162,6 +194,7 @@
      */
     public static final class RemOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<RemOp> TYPE = LIRInstructionClass.create(RemOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(4);
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG}) protected Value result;
@@ -172,7 +205,7 @@
         @State protected LIRFrameState state;
 
         public RemOp(SPARCArithmetic opcode, Value result, Value x, Value y, LIRFrameState state, LIRGeneratorTool gen) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.opcode = opcode;
             this.result = result;
             this.x = x;
@@ -199,6 +232,8 @@
      */
     public static final class SPARCLMulccOp extends SPARCLIRInstruction {
         public static final LIRInstructionClass<SPARCLMulccOp> TYPE = LIRInstructionClass.create(SPARCLMulccOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(13);
+
         @Def({REG}) protected Value result;
         @Alive({REG}) protected Value x;
         @Alive({REG}) protected Value y;
@@ -206,7 +241,7 @@
         @Temp({REG}) protected Value scratch2;
 
         public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.x = x;
             this.y = y;
@@ -856,6 +891,7 @@
 
     public static final class MulHighOp extends SPARCLIRInstruction {
         public static final LIRInstructionClass<MulHighOp> TYPE = LIRInstructionClass.create(MulHighOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(4);
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG}) public AllocatableValue result;
@@ -864,7 +900,7 @@
         @Temp({REG}) public AllocatableValue scratch;
 
         public MulHighOp(SPARCArithmetic opcode, AllocatableValue x, AllocatableValue y, AllocatableValue result, AllocatableValue scratch) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.opcode = opcode;
             this.x = x;
             this.y = y;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArrayEqualsOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -53,6 +53,7 @@
 @Opcode("ARRAY_EQUALS")
 public final class SPARCArrayEqualsOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCArrayEqualsOp> TYPE = LIRInstructionClass.create(SPARCArrayEqualsOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(32);
 
     private final Kind kind;
     private final int arrayBaseOffset;
@@ -69,7 +70,7 @@
     @Temp({REG}) protected Value temp5;
 
     public SPARCArrayEqualsOp(LIRGeneratorTool tool, Kind kind, Value result, Value array1, Value array2, Value length) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.kind = kind;
 
         Class<?> arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass();
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -39,11 +39,17 @@
     public static final LIRInstructionClass<SPARCBitManipulationOp> TYPE = LIRInstructionClass.create(SPARCBitManipulationOp.class);
 
     public enum IntrinsicOpcode {
-        IPOPCNT,
-        LPOPCNT,
-        IBSR,
-        LBSR,
-        BSF;
+        IPOPCNT(SizeEstimate.create(2)),
+        LPOPCNT(SizeEstimate.create(1)),
+        IBSR(SizeEstimate.create(13)),
+        LBSR(SizeEstimate.create(14)),
+        BSF(SizeEstimate.create(4));
+
+        final SizeEstimate size;
+
+        private IntrinsicOpcode(SizeEstimate size) {
+            this.size = size;
+        }
     }
 
     @Opcode private final IntrinsicOpcode opcode;
@@ -52,7 +58,7 @@
     @Temp({REG}) protected Value scratch;
 
     public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) {
-        super(TYPE);
+        super(TYPE, opcode.size);
         this.opcode = opcode;
         this.result = result;
         this.input = input;
@@ -148,5 +154,4 @@
             throw JVMCIError.shouldNotReachHere();
         }
     }
-
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBreakpointOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -35,6 +35,7 @@
 @Opcode("BREAKPOINT")
 public final class SPARCBreakpointOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCBreakpointOp> TYPE = LIRInstructionClass.create(SPARCBreakpointOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     // historical - from hotspot src/cpu/sparc/vm
     // <sys/trap.h> promises that the system will not use traps 16-31
@@ -47,7 +48,7 @@
     @Use({REG, STACK}) protected Value[] parameters;
 
     public SPARCBreakpointOp(Value[] parameters) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.parameters = parameters;
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCByteSwapOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -37,14 +37,14 @@
 @Opcode("BSWAP")
 public final class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
     public static final LIRInstructionClass<SPARCByteSwapOp> TYPE = LIRInstructionClass.create(SPARCByteSwapOp.class);
-
+    public static final SizeEstimate SIZE = SizeEstimate.create(3);
     @Def({REG, HINT}) protected Value result;
     @Use({REG}) protected Value input;
     @Temp({REG}) protected Value tempIndex;
     @Use({STACK}) protected StackSlotValue tmpSlot;
 
     public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.result = result;
         this.input = input;
         this.tmpSlot = tool.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(Kind.Long));
@@ -53,7 +53,7 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-        SPARCMove.move(crb, masm, tmpSlot, input, SPARCDelayedControlTransfer.DUMMY);
+        SPARCMove.reg2stack(crb, masm, tmpSlot, input, SPARCDelayedControlTransfer.DUMMY);
         SPARCAddress addr = (SPARCAddress) crb.asAddress(tmpSlot);
         if (addr.getIndex().equals(Register.None)) {
             Register tempReg = ValueUtil.asLongReg(tempIndex);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCall.java	Sat Jun 27 18:02:44 2015 +0200
@@ -37,15 +37,13 @@
 public class SPARCCall {
 
     public abstract static class CallOp extends SPARCLIRInstruction {
-        public static final LIRInstructionClass<CallOp> TYPE = LIRInstructionClass.create(CallOp.class);
-
         @Def({REG, ILLEGAL}) protected Value result;
         @Use({REG, STACK}) protected Value[] parameters;
         @Temp protected Value[] temps;
         @State protected LIRFrameState state;
 
-        protected CallOp(LIRInstructionClass<? extends CallOp> c, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(c);
+        protected CallOp(LIRInstructionClass<? extends CallOp> c, SizeEstimate size, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(c, size);
             this.result = result;
             this.parameters = parameters;
             this.state = state;
@@ -60,28 +58,23 @@
     }
 
     public abstract static class MethodCallOp extends CallOp {
-        public static final LIRInstructionClass<MethodCallOp> TYPE = LIRInstructionClass.create(MethodCallOp.class);
 
         protected final ResolvedJavaMethod callTarget;
 
-        protected MethodCallOp(LIRInstructionClass<? extends MethodCallOp> c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(c, result, parameters, temps, state);
+        protected MethodCallOp(LIRInstructionClass<? extends MethodCallOp> c, SizeEstimate size, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(c, size, result, parameters, temps, state);
             this.callTarget = callTarget;
         }
 
     }
 
     @Opcode("CALL_DIRECT")
-    public abstract static class DirectCallOp extends MethodCallOp /*
-                                                                    * implements
-                                                                    * SPARCDelayedControlTransfer
-                                                                    */{
-        public static final LIRInstructionClass<DirectCallOp> TYPE = LIRInstructionClass.create(DirectCallOp.class);
+    public abstract static class DirectCallOp extends MethodCallOp {
         private boolean emitted = false;
         private int before = -1;
 
-        public DirectCallOp(LIRInstructionClass<? extends DirectCallOp> c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(c, callTarget, result, parameters, temps, state);
+        public DirectCallOp(LIRInstructionClass<? extends DirectCallOp> c, SizeEstimate size, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(c, size, callTarget, result, parameters, temps, state);
         }
 
         @Override
@@ -126,13 +119,11 @@
 
     @Opcode("CALL_INDIRECT")
     public abstract static class IndirectCallOp extends MethodCallOp {
-        public static final LIRInstructionClass<IndirectCallOp> TYPE = LIRInstructionClass.create(IndirectCallOp.class);
-
         @Use({REG}) protected Value targetAddress;
 
-        protected IndirectCallOp(LIRInstructionClass<? extends IndirectCallOp> c, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress,
-                        LIRFrameState state) {
-            super(c, callTarget, result, parameters, temps, state);
+        protected IndirectCallOp(LIRInstructionClass<? extends IndirectCallOp> c, SizeEstimate size, ResolvedJavaMethod callTarget, Value result, Value[] parameters, Value[] temps,
+                        Value targetAddress, LIRFrameState state) {
+            super(c, size, callTarget, result, parameters, temps, state);
             this.targetAddress = targetAddress;
         }
 
@@ -153,8 +144,8 @@
 
         protected final ForeignCallLinkage callTarget;
 
-        public ForeignCallOp(LIRInstructionClass<? extends ForeignCallOp> c, ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(c, result, parameters, temps, state);
+        public ForeignCallOp(LIRInstructionClass<? extends ForeignCallOp> c, SizeEstimate size, ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
+            super(c, size, result, parameters, temps, state);
             this.callTarget = callTarget;
         }
 
@@ -167,9 +158,10 @@
     @Opcode("NEAR_FOREIGN_CALL")
     public static final class DirectNearForeignCallOp extends ForeignCallOp {
         public static final LIRInstructionClass<DirectNearForeignCallOp> TYPE = LIRInstructionClass.create(DirectNearForeignCallOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         public DirectNearForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(TYPE, linkage, result, parameters, temps, state);
+            super(TYPE, SIZE, linkage, result, parameters, temps, state);
         }
 
         @Override
@@ -181,9 +173,10 @@
     @Opcode("FAR_FOREIGN_CALL")
     public static final class DirectFarForeignCallOp extends ForeignCallOp {
         public static final LIRInstructionClass<DirectFarForeignCallOp> TYPE = LIRInstructionClass.create(DirectFarForeignCallOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         public DirectFarForeignCallOp(ForeignCallLinkage callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) {
-            super(TYPE, callTarget, result, parameters, temps, state);
+            super(TYPE, SIZE, callTarget, result, parameters, temps, state);
         }
 
         @Override
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCCompare.java	Sat Jun 27 18:02:44 2015 +0200
@@ -44,13 +44,14 @@
 
     public static final class CompareOp extends SPARCLIRInstruction {
         public static final LIRInstructionClass<CompareOp> TYPE = LIRInstructionClass.create(CompareOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         @Opcode private final SPARCCompare opcode;
         @Use({REG}) protected Value x;
         @Use({REG, CONST}) protected Value y;
 
         public CompareOp(SPARCCompare opcode, Value x, Value y) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.opcode = opcode;
             this.x = x;
             this.y = y;
@@ -74,7 +75,6 @@
                     (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) ||
                     (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double)
                     : "Name; " + name() + " x: " + x + " y: " + y;
-
             // @formatter:on
         }
     }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sat Jun 27 18:02:44 2015 +0200
@@ -28,6 +28,7 @@
 import static com.oracle.graal.asm.sparc.SPARCAssembler.CC.*;
 import static com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.sparc.SPARCMove.*;
 import static jdk.internal.jvmci.code.ValueUtil.*;
 import static jdk.internal.jvmci.sparc.SPARC.*;
 
@@ -56,11 +57,12 @@
 
     public static final class ReturnOp extends SPARCLIRInstruction implements BlockEndOp {
         public static final LIRInstructionClass<ReturnOp> TYPE = LIRInstructionClass.create(ReturnOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
         @Use({REG, ILLEGAL}) protected Value x;
 
         public ReturnOp(Value x) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.x = x;
         }
 
@@ -78,6 +80,7 @@
 
     public static final class CompareBranchOp extends SPARCLIRInstruction implements BlockEndOp, SPARCDelayedControlTransfer {
         public static final LIRInstructionClass<CompareBranchOp> TYPE = LIRInstructionClass.create(CompareBranchOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(3);
         static final EnumSet<Kind> SUPPORTED_KINDS = EnumSet.of(Kind.Long, Kind.Int, Kind.Object, Kind.Float, Kind.Double);
 
         private final SPARCCompare opcode;
@@ -99,7 +102,7 @@
 
         public CompareBranchOp(SPARCCompare opcode, Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind, boolean unorderedIsTrue,
                         double trueDestinationProbability) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.opcode = opcode;
             this.x = x;
             this.y = y;
@@ -328,6 +331,7 @@
 
     public static final class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
         public static final LIRInstructionClass<BranchOp> TYPE = LIRInstructionClass.create(BranchOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
         protected final ConditionFlag conditionFlag;
         protected final LabelRef trueDestination;
         protected final LabelRef falseDestination;
@@ -335,7 +339,7 @@
         protected final double trueDestinationProbability;
 
         public BranchOp(ConditionFlag conditionFlag, LabelRef trueDestination, LabelRef falseDestination, Kind kind, double trueDestinationProbability) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.trueDestination = trueDestination;
             this.falseDestination = falseDestination;
             this.kind = kind;
@@ -396,15 +400,17 @@
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         @Alive({REG}) protected Value key;
+        @Alive({REG, ILLEGAL}) protected Value constantTableBase;
         @Temp({REG}) protected Value scratch;
         private final SwitchStrategy strategy;
 
-        public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+        public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
             super(TYPE);
             this.strategy = strategy;
             this.keyConstants = strategy.keyConstants;
             this.keyTargets = keyTargets;
             this.defaultTarget = defaultTarget;
+            this.constantTableBase = constantTableBase;
             this.key = key;
             this.scratch = scratch;
             assert keyConstants.length == keyTargets.length;
@@ -414,11 +420,11 @@
         @Override
         public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) {
             final Register keyRegister = asRegister(key);
-
+            final Register constantBaseRegister = AllocatableValue.ILLEGAL.equals(constantTableBase) ? g0 : asRegister(constantTableBase);
             BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) {
                 @Override
                 protected void conditionalJump(int index, Condition condition, Label target) {
-                    SPARCMove.move(crb, masm, scratch, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                    const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
                     CC conditionCode;
                     Register scratchRegister;
                     switch (key.getKind()) {
@@ -450,6 +456,17 @@
             };
             strategy.run(closure);
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            int constantBytes = 0;
+            for (JavaConstant v : keyConstants) {
+                if (!SPARCAssembler.isSimm13(v)) {
+                    constantBytes += v.getKind().getByteCount();
+                }
+            }
+            return new SizeEstimate(4 * keyTargets.length, constantBytes);
+        }
     }
 
     public static final class TableSwitchOp extends SPARCLIRInstruction implements BlockEndOp {
@@ -522,6 +539,11 @@
                 masm.nop(); // delay slot
             }
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            return SizeEstimate.create(17 + targets.length * 2);
+        }
     }
 
     @Opcode("CMOVE")
@@ -563,6 +585,18 @@
                 cmove(masm, cc, result, actualCondition, actualTrueValue);
             }
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            int constantSize = 0;
+            if (isConstant(trueValue) && !SPARCAssembler.isSimm13(asConstant(trueValue))) {
+                constantSize += trueValue.getKind().getByteCount();
+            }
+            if (isConstant(falseValue) && !SPARCAssembler.isSimm13(asConstant(falseValue))) {
+                constantSize += trueValue.getKind().getByteCount();
+            }
+            return SizeEstimate.create(3, constantSize);
+        }
     }
 
     private static void cmove(SPARCMacroAssembler masm, CC cc, Value result, ConditionFlag cond, Value other) {
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCJumpOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -29,9 +29,12 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.sparc.SPARCLIRInstruction.*;
 
 public final class SPARCJumpOp extends JumpOp implements SPARCDelayedControlTransfer {
     public static final LIRInstructionClass<SPARCJumpOp> TYPE = LIRInstructionClass.create(SPARCJumpOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(2);
+
     private boolean emitDone = false;
     private int delaySlotPosition = -1;
 
@@ -56,11 +59,16 @@
                 masm.bicc(ConditionFlag.Always, NOT_ANNUL, destination().label());
                 masm.nop();
             } else {
-                assert crb.asm.position() - delaySlotPosition == 4;
+                int disp = crb.asm.position() - delaySlotPosition;
+                assert disp == 4 : disp;
             }
         }
     }
 
+    public static SizeEstimate getSize() {
+        return SIZE;
+    }
+
     public void resetState() {
         delaySlotPosition = -1;
         emitDone = false;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java	Sat Jun 27 18:02:44 2015 +0200
@@ -31,9 +31,15 @@
  */
 public abstract class SPARCLIRInstruction extends LIRInstruction {
     public static final LIRInstructionClass<SPARCLIRInstruction> TYPE = LIRInstructionClass.create(SPARCLIRInstruction.class);
+    private final SizeEstimate size;
 
     protected SPARCLIRInstruction(LIRInstructionClass<? extends LIRInstruction> c) {
+        this(c, null);
+    }
+
+    protected SPARCLIRInstruction(LIRInstructionClass<? extends LIRInstruction> c, SizeEstimate size) {
         super(c);
+        this.size = size;
     }
 
     protected SPARCDelayedControlTransfer delayedControlTransfer = SPARCDelayedControlTransfer.DUMMY;
@@ -52,4 +58,48 @@
     public void setDelayedControlTransfer(SPARCDelayedControlTransfer holder) {
         this.delayedControlTransfer = holder;
     }
+
+    public SizeEstimate estimateSize() {
+        return size;
+    }
+
+    /**
+     * This class represents a size estimation of a particular LIR instruction. It contains a
+     * pessimistic estimate of emitted SPARC instructions and emitted bytes into the constant
+     * section.
+     */
+    public static class SizeEstimate {
+        /**
+         * Cache the first size definition (with just 0 as constant size).
+         */
+        private static final SizeEstimate[] cache = new SizeEstimate[5];
+        static {
+            for (int i = 0; i < cache.length; i++) {
+                cache[i] = new SizeEstimate(i, 0);
+            }
+        }
+        public final int instructionSize;
+        public final int constantSize;
+
+        public SizeEstimate(int instructionSize, int constantSize) {
+            this.instructionSize = instructionSize;
+            this.constantSize = constantSize;
+        }
+
+        public static SizeEstimate create(int instructionSize, int constantSize) {
+            if (constantSize == 0 && instructionSize < cache.length) {
+                return cache[instructionSize];
+            } else {
+                return new SizeEstimate(instructionSize, constantSize);
+            }
+        }
+
+        public static SizeEstimate create(int instructionSize) {
+            if (instructionSize < cache.length) {
+                return cache[instructionSize];
+            } else {
+                return new SizeEstimate(instructionSize, 0);
+            }
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLoadConstantTableBaseOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009, 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.graal.lir.sparc;
+
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static jdk.internal.jvmci.code.ValueUtil.*;
+import jdk.internal.jvmci.code.CompilationResult.DataSectionReference;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.meta.*;
+
+import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.NoOp;
+import com.oracle.graal.lir.asm.*;
+
+/**
+ * Loads the constant section base into a register.
+ *
+ * <p>
+ * Layout:
+ *
+ * <pre>
+ * +----constant section----+--pad--+---code section--+
+ * |<-------------------_------------------->|
+ *                      ^- Constant section base pointer
+ * </pre>
+ *
+ * The constant section base pointer is placed as such that the lowest offset -4096 points to the
+ * start of the constant section.
+ * <p>
+ * If the constant section grows beyond 8k size, the immediate addressing cannot be used anymore; in
+ * this case absolute addressing (without using the base pointer is used). See also:
+ * CodeInstaller::pd_patch_DataSectionReference
+ *
+ * @see SPARCMove#loadFromConstantTable(CompilationResultBuilder, SPARCMacroAssembler, Kind,
+ *      Register, Register, SPARCDelayedControlTransfer, Runnable)
+ */
+public class SPARCLoadConstantTableBaseOp extends SPARCLIRInstruction {
+    public static final LIRInstructionClass<SPARCLoadConstantTableBaseOp> TYPE = LIRInstructionClass.create(SPARCLoadConstantTableBaseOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(9);
+
+    private final NoOp placeHolder;
+    @Def({REG}) private AllocatableValue base;
+
+    public SPARCLoadConstantTableBaseOp(Variable base, NoOp placeHolder) {
+        super(TYPE, SIZE);
+        this.base = base;
+        this.placeHolder = placeHolder;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+        Register baseRegister = asRegister(base);
+        DataSectionReference ref = new DataSectionReference();
+        ref.setOffset(0);
+        crb.compilationResult.recordDataPatch(masm.position(), ref);
+        // TODO: (sa) Make this relocation shorter (right now it takes always 8 instructions)
+        new SPARCMacroAssembler.Setx(0, baseRegister, true).emit(masm);
+        /**
+         * Place the base register into the center of the reachable 8k range. This bias is reflected
+         * in CodeInstaller::pd_patch_DataSectionReference (jvmciCodeInstaller_sparc.cpp)
+         */
+        masm.sub(baseRegister, -1 & ~((1 << 12) - 1), baseRegister);
+    }
+
+    public AllocatableValue getResult() {
+        return base;
+    }
+
+    public void setAlive(LIR lir, boolean alive) {
+        if (alive) {
+            placeHolder.replace(lir, this);
+        } else {
+            placeHolder.remove(lir);
+        }
+    }
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -32,6 +32,7 @@
 
 public final class SPARCMathIntrinsicOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
     public static final LIRInstructionClass<SPARCMathIntrinsicOp> TYPE = LIRInstructionClass.create(SPARCMathIntrinsicOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     public enum IntrinsicOpcode {
         SQRT,
@@ -43,7 +44,7 @@
     @Use protected Value input;
 
     public SPARCMathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.opcode = opcode;
         this.result = result;
         this.input = input;
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Sat Jun 27 18:02:44 2015 +0200
@@ -27,6 +27,9 @@
 import static jdk.internal.jvmci.code.ValueUtil.*;
 import static jdk.internal.jvmci.meta.Kind.*;
 import static jdk.internal.jvmci.sparc.SPARC.*;
+
+import java.util.*;
+
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.common.*;
 import jdk.internal.jvmci.meta.*;
@@ -35,6 +38,7 @@
 
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Sethix;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
@@ -44,22 +48,110 @@
 
 public class SPARCMove {
 
-    @Opcode("MOVE_TOREG")
-    public static class MoveToRegOp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
-        public static final LIRInstructionClass<MoveToRegOp> TYPE = LIRInstructionClass.create(MoveToRegOp.class);
+    public static class LoadInlineConstant extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction, MoveOp {
+        public static final LIRInstructionClass<LoadInlineConstant> TYPE = LIRInstructionClass.create(LoadInlineConstant.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
+        private JavaConstant constant;
+        @Def({REG, STACK}) AllocatableValue result;
+
+        public LoadInlineConstant(JavaConstant constant, AllocatableValue result) {
+            super(TYPE, SIZE);
+            this.constant = constant;
+            this.result = result;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            if (isRegister(result)) {
+                const2reg(crb, masm, result, g0, constant, delayedControlTransfer);
+            } else if (isStackSlot(result)) {
+                StackSlot slot = asStackSlot(result);
+                const2stack(crb, masm, slot, g0, constant, delayedControlTransfer, constant);
+            }
+        }
+
+        public Value getInput() {
+            return constant;
+        }
+
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    public static class LoadConstantFromTable extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
+        public static final LIRInstructionClass<LoadConstantFromTable> TYPE = LIRInstructionClass.create(LoadConstantFromTable.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1, 8);
+
+        private JavaConstant constant;
+        @Def({REG, STACK}) AllocatableValue result;
+        @Use({REG}) private AllocatableValue constantTableBase;
+
+        public LoadConstantFromTable(JavaConstant constant, AllocatableValue constantTableBase, AllocatableValue result) {
+            super(TYPE, SIZE);
+            this.constant = constant;
+            this.result = result;
+            this.constantTableBase = constantTableBase;
+        }
 
-        @Def({REG, HINT}) protected AllocatableValue result;
-        @Use({REG, STACK, CONST}) protected Value input;
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            final Runnable recordReference;
+            final Kind constantKind = constant.getKind().equals(Object) ? Kind.Long : constant.getKind();
+            switch (constantKind) {
+                case Object:
+                case Float:
+                case Double:
+                case Char:
+                case Short:
+                case Int:
+                case Long:
+                    recordReference = () -> crb.recordDataReferenceInCode(constant, constantKind.getByteCount());
+                    break;
+                case Byte:
+                case Boolean: // Byte and Boolean always fits into simm13
+                    throw JVMCIError.shouldNotReachHere("Byte/Boolean must not be loaded via constant table");
+                default:
+                    throw JVMCIError.shouldNotReachHere("Unimplemented constant type: " + constant);
+            }
+            Register baseRegister = asRegister(constantTableBase);
+            if (isRegister(result)) {
+                Register resultRegister = asRegister(result);
+                loadFromConstantTable(crb, masm, constantKind, baseRegister, resultRegister, delayedControlTransfer, recordReference);
+            } else if (isStackSlot(result)) {
+                try (ScratchRegister scratch = masm.getScratchRegister()) {
+                    Register scratchRegister = scratch.getRegister();
+                    loadFromConstantTable(crb, masm, constantKind, baseRegister, scratchRegister, delayedControlTransfer, recordReference);
+                    StackSlot slot = asStackSlot(result);
+                    delayedControlTransfer.emitControlTransfer(crb, masm);
+                    masm.stx(scratchRegister, (SPARCAddress) crb.asAddress(slot));
+                }
+            }
+        }
+    }
 
-        public MoveToRegOp(AllocatableValue result, Value input) {
-            super(TYPE);
+    @Opcode("MOVE")
+    public static class Move extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
+        public static final LIRInstructionClass<Move> TYPE = LIRInstructionClass.create(Move.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(8);
+
+        @Def({REG, STACK}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected Value input;
+
+        public Move(AllocatableValue result, Value input) {
+            super(TYPE, SIZE);
             this.result = result;
             this.input = input;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            move(crb, masm, getResult(), getInput(), delayedControlTransfer);
+            assert !isConstant(input);
+            if (isStackSlot(input) && isStackSlot(result)) {
+                stack2stack(crb, masm, reInterpret(asStackSlot(result)), reInterpret(asStackSlot(input)), delayedControlTransfer);
+            } else {
+                move(crb, masm, getResult(), getInput(), delayedControlTransfer);
+            }
         }
 
         @Override
@@ -71,54 +163,44 @@
         public AllocatableValue getResult() {
             return result;
         }
-    }
 
-    @Opcode("MOVE_FROMREG")
-    public static final class MoveFromRegOp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
-        public static final LIRInstructionClass<MoveFromRegOp> TYPE = LIRInstructionClass.create(MoveFromRegOp.class);
-
-        @Def({REG, STACK}) protected AllocatableValue result;
-        @Use({REG, CONST, HINT}) protected Value input;
-
-        public MoveFromRegOp(AllocatableValue result, Value input) {
-            super(TYPE);
-            this.result = result;
-            this.input = input;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            move(crb, masm, getResult(), getInput(), delayedControlTransfer);
-        }
-
-        @Override
-        public Value getInput() {
-            return input;
-        }
-
-        @Override
-        public AllocatableValue getResult() {
-            return result;
+        private static StackSlot reInterpret(StackSlot slot) {
+            switch ((Kind) slot.getPlatformKind()) {
+                case Boolean:
+                case Byte:
+                case Short:
+                case Char:
+                case Int:
+                case Long:
+                case Object:
+                    return slot;
+                case Float:
+                    return StackSlot.get(LIRKind.value(Kind.Int), slot.getRawOffset(), slot.getRawAddFrameSize());
+                case Double:
+                    return StackSlot.get(LIRKind.value(Kind.Long), slot.getRawOffset(), slot.getRawAddFrameSize());
+                default:
+                    throw JVMCIError.shouldNotReachHere();
+            }
         }
     }
 
     /**
-     * Move between floating-point and general purpose register domain (WITHOUT VIS3).
+     * Move between floating-point and general purpose register domain.
      */
-    @Opcode("MOVE")
+    @Opcode("MOVE_FPGP")
     public static final class MoveFpGp extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<MoveFpGp> TYPE = LIRInstructionClass.create(MoveFpGp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue input;
-        @Use({STACK}) protected StackSlotValue temp;
+        @Use({STACK, ILLEGAL}) protected AllocatableValue temp;
 
-        public MoveFpGp(AllocatableValue result, AllocatableValue input, StackSlotValue temp) {
-            super(TYPE);
+        public MoveFpGp(AllocatableValue result, AllocatableValue input, AllocatableValue temp) {
+            super(TYPE, SIZE);
             this.result = result;
             this.input = input;
             this.temp = temp;
-            assert this.temp.getPlatformKind() == Kind.Long;
         }
 
         public Value getInput() {
@@ -133,6 +215,43 @@
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             Kind inputKind = (Kind) input.getPlatformKind();
             Kind resultKind = (Kind) result.getPlatformKind();
+            if (AllocatableValue.ILLEGAL.equals(temp)) {
+                moveDirect(crb, masm, inputKind, resultKind);
+            } else {
+                moveViaStack(crb, masm, inputKind, resultKind);
+            }
+        }
+
+        private void moveDirect(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind inputKind, Kind resultKind) {
+            delayedControlTransfer.emitControlTransfer(crb, masm);
+            if (resultKind == Float) {
+                if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) {
+                    masm.movwtos(asIntReg(input), asFloatReg(result));
+                } else {
+                    throw JVMCIError.shouldNotReachHere();
+                }
+            } else if (resultKind == Double) {
+                if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) {
+                    masm.movxtod(asIntReg(input), asDoubleReg(result));
+                } else {
+                    masm.movxtod(asLongReg(input), asDoubleReg(result));
+                }
+            } else if (inputKind == Float) {
+                if (resultKind == Int || resultKind == Short || resultKind == Byte) {
+                    masm.movstosw(asFloatReg(input), asIntReg(result));
+                } else {
+                    masm.movstouw(asFloatReg(input), asIntReg(result));
+                }
+            } else if (inputKind == Double) {
+                if (resultKind == Long) {
+                    masm.movdtox(asDoubleReg(input), asLongReg(result));
+                } else {
+                    throw JVMCIError.shouldNotReachHere();
+                }
+            }
+        }
+
+        private void moveViaStack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind inputKind, Kind resultKind) {
             int resultKindSize = crb.target.getSizeInBytes(resultKind);
             try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
@@ -197,118 +316,6 @@
         }
     }
 
-    /**
-     * Move between floating-point and general purpose register domain (WITH VIS3).
-     */
-    @Opcode("MOVE")
-    public static final class MoveFpGpVIS3 extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
-        public static final LIRInstructionClass<MoveFpGpVIS3> TYPE = LIRInstructionClass.create(MoveFpGpVIS3.class);
-
-        @Def({REG}) protected AllocatableValue result;
-        @Use({REG}) protected AllocatableValue input;
-
-        public MoveFpGpVIS3(AllocatableValue result, AllocatableValue input) {
-            super(TYPE);
-            this.result = result;
-            this.input = input;
-        }
-
-        public Value getInput() {
-            return input;
-        }
-
-        public AllocatableValue getResult() {
-            return result;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            Kind inputKind = (Kind) input.getPlatformKind();
-            Kind resultKind = (Kind) result.getPlatformKind();
-            delayedControlTransfer.emitControlTransfer(crb, masm);
-            if (resultKind == Float) {
-                if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) {
-                    masm.movwtos(asIntReg(input), asFloatReg(result));
-                } else {
-                    throw JVMCIError.shouldNotReachHere();
-                }
-            } else if (resultKind == Double) {
-                if (inputKind == Int || inputKind == Short || inputKind == Char || inputKind == Byte) {
-                    masm.movxtod(asIntReg(input), asDoubleReg(result));
-                } else {
-                    masm.movxtod(asLongReg(input), asDoubleReg(result));
-                }
-            } else if (inputKind == Float) {
-                if (resultKind == Int || resultKind == Short || resultKind == Byte) {
-                    masm.movstosw(asFloatReg(input), asIntReg(result));
-                } else {
-                    masm.movstouw(asFloatReg(input), asIntReg(result));
-                }
-            } else if (inputKind == Double) {
-                if (resultKind == Long) {
-                    masm.movdtox(asDoubleReg(input), asLongReg(result));
-                } else {
-                    throw JVMCIError.shouldNotReachHere();
-                }
-            }
-        }
-    }
-
-    @Opcode("STACKMOVE")
-    public static final class SPARCStackMove extends SPARCLIRInstruction implements MoveOp, SPARCTailDelayedLIRInstruction {
-        public static final LIRInstructionClass<SPARCStackMove> TYPE = LIRInstructionClass.create(SPARCStackMove.class);
-
-        @Def({STACK}) protected AllocatableValue result;
-        @Use({STACK, HINT}) protected Value input;
-
-        public SPARCStackMove(AllocatableValue result, Value input) {
-            super(TYPE);
-            this.result = result;
-            this.input = input;
-        }
-
-        @Override
-        public Value getInput() {
-            return input;
-        }
-
-        @Override
-        public AllocatableValue getResult() {
-            return result;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            try (ScratchRegister scratchReg = masm.getScratchRegister()) {
-                Register scratch = scratchReg.getRegister();
-                StackSlot intInput = reInterpret(asStackSlot(getInput()));
-                StackSlot intResult = reInterpret(asStackSlot(getResult()));
-                // move stack slot
-                move(crb, masm, scratch.asValue(intInput.getLIRKind()), intInput, SPARCDelayedControlTransfer.DUMMY);
-                move(crb, masm, intResult, scratch.asValue(intResult.getLIRKind()), delayedControlTransfer);
-            }
-        }
-
-        private static StackSlot reInterpret(StackSlot slot) {
-            switch ((Kind) slot.getPlatformKind()) {
-                case Boolean:
-                case Byte:
-                case Short:
-                case Char:
-                case Int:
-                case Long:
-                case Object:
-                    return slot;
-                case Float:
-                    return StackSlot.get(LIRKind.value(Kind.Int), slot.getRawOffset(), slot.getRawAddFrameSize());
-                case Double:
-                    return StackSlot.get(LIRKind.value(Kind.Long), slot.getRawOffset(), slot.getRawAddFrameSize());
-                default:
-                    throw JVMCIError.shouldNotReachHere();
-            }
-        }
-    }
-
     public abstract static class MemOp extends SPARCLIRInstruction implements ImplicitNullCheck {
         public static final LIRInstructionClass<MemOp> TYPE = LIRInstructionClass.create(MemOp.class);
 
@@ -316,8 +323,8 @@
         @Use({COMPOSITE}) protected SPARCAddressValue address;
         @State protected LIRFrameState state;
 
-        public MemOp(LIRInstructionClass<? extends MemOp> c, PlatformKind kind, SPARCAddressValue address, LIRFrameState state) {
-            super(c);
+        public MemOp(LIRInstructionClass<? extends MemOp> c, SizeEstimate size, PlatformKind kind, SPARCAddressValue address, LIRFrameState state) {
+            super(c, size);
             this.kind = kind;
             this.address = address;
             this.state = state;
@@ -341,6 +348,7 @@
 
     public static final class LoadOp extends MemOp implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<LoadOp> TYPE = LIRInstructionClass.create(LoadOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         @Def({REG}) protected AllocatableValue result;
         protected boolean signExtend;
@@ -350,25 +358,26 @@
         }
 
         public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state, boolean signExtend) {
-            super(TYPE, kind, address, state);
+            super(TYPE, SIZE, kind, address, state);
             this.result = result;
             this.signExtend = signExtend;
         }
 
         @Override
         public void emitMemAccess(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            emitLoad(address.toAddress(), result, signExtend, kind, delayedControlTransfer, state, crb, masm);
+            emitLoad(crb, masm, address.toAddress(), result, signExtend, kind, delayedControlTransfer, state);
         }
     }
 
     public static final class LoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<LoadAddressOp> TYPE = LIRInstructionClass.create(LoadAddressOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(8);
 
         @Def({REG}) protected AllocatableValue result;
         @Use({COMPOSITE, UNINITIALIZED}) protected SPARCAddressValue addressValue;
 
         public LoadAddressOp(AllocatableValue result, SPARCAddressValue address) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.addressValue = address;
         }
@@ -394,21 +403,27 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(data, 16);
+            SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(data, 8);
             assert addr == masm.getPlaceholder();
             final boolean forceRelocatable = true;
             Register dstReg = asRegister(result);
             new Setx(0, dstReg, forceRelocatable).emit(masm);
         }
+
+        @Override
+        public SizeEstimate estimateSize() {
+            return SizeEstimate.create(8, data.length);
+        }
     }
 
     public static final class MembarOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<MembarOp> TYPE = LIRInstructionClass.create(MembarOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         private final int barriers;
 
         public MembarOp(final int barriers) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.barriers = barriers;
         }
 
@@ -421,12 +436,13 @@
 
     public static final class NullCheckOp extends SPARCLIRInstruction implements NullCheck, SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<NullCheckOp> TYPE = LIRInstructionClass.create(NullCheckOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         @Use({COMPOSITE}) protected SPARCAddressValue input;
         @State protected LIRFrameState state;
 
         public NullCheckOp(SPARCAddressValue input, LIRFrameState state) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.input = input;
             this.state = state;
         }
@@ -453,6 +469,7 @@
     @Opcode("CAS")
     public static final class CompareAndSwapOp extends SPARCLIRInstruction {
         public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Alive({REG}) protected AllocatableValue address;
@@ -460,7 +477,7 @@
         @Use({REG}) protected AllocatableValue newValue;
 
         public CompareAndSwapOp(AllocatableValue result, AllocatableValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -476,12 +493,13 @@
 
     public static final class StackLoadAddressOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<StackLoadAddressOp> TYPE = LIRInstructionClass.create(StackLoadAddressOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
         @Def({REG}) protected AllocatableValue result;
         @Use({STACK, UNINITIALIZED}) protected StackSlotValue slot;
 
         public StackLoadAddressOp(AllocatableValue result, StackSlotValue address) {
-            super(TYPE);
+            super(TYPE, SIZE);
             this.result = result;
             this.slot = address;
         }
@@ -513,11 +531,12 @@
 
     public static class StoreOp extends MemOp implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<StoreOp> TYPE = LIRInstructionClass.create(StoreOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
         @Use({REG}) protected AllocatableValue input;
 
         public StoreOp(Kind kind, SPARCAddressValue address, AllocatableValue input, LIRFrameState state) {
-            super(TYPE, kind, address, state);
+            super(TYPE, SIZE, kind, address, state);
             this.input = input;
         }
 
@@ -529,11 +548,12 @@
 
     public static final class StoreConstantOp extends MemOp implements SPARCTailDelayedLIRInstruction {
         public static final LIRInstructionClass<StoreConstantOp> TYPE = LIRInstructionClass.create(StoreConstantOp.class);
+        public static final SizeEstimate SIZE = SizeEstimate.create(2);
 
         protected final JavaConstant input;
 
         public StoreConstantOp(Kind kind, SPARCAddressValue address, JavaConstant input, LIRFrameState state) {
-            super(TYPE, kind, address, state);
+            super(TYPE, SIZE, kind, address, state);
             this.input = input;
             if (!input.isDefaultForKind()) {
                 throw JVMCIError.shouldNotReachHere("Can only store null constants to memory");
@@ -576,43 +596,33 @@
     }
 
     public static void move(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
+        move(crb, masm, result, g0, input, delaySlotLir);
+    }
+
+    public static void move(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Register constantTableBase, Value input, SPARCDelayedControlTransfer delaySlotLir) {
         if (isRegister(input)) {
             if (isRegister(result)) {
                 reg2reg(crb, masm, result, input, delaySlotLir);
             } else if (isStackSlot(result)) {
-                SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
-                emitStore(input, resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+                reg2stack(crb, masm, result, input, delaySlotLir);
             } else {
-                throw JVMCIError.shouldNotReachHere();
+                throw JVMCIError.shouldNotReachHere("Result is a: " + result);
             }
         } else if (isStackSlot(input)) {
             if (isRegister(result)) {
                 SPARCAddress inputAddress = (SPARCAddress) crb.asAddress(input);
-                emitLoad(inputAddress, result, false, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+                emitLoad(crb, masm, inputAddress, result, false, input.getPlatformKind(), delaySlotLir, null);
+            } else if (isStackSlot(result)) {
+                stack2stack(crb, masm, result, input, delaySlotLir);
             } else {
-                throw JVMCIError.shouldNotReachHere();
+                throw JVMCIError.shouldNotReachHere("Result is a: " + result);
             }
         } else if (isConstant(input)) {
             JavaConstant constant = asConstant(input);
             if (isRegister(result)) {
-                const2reg(crb, masm, result, constant, delaySlotLir);
+                const2reg(crb, masm, result, constantTableBase, constant, delaySlotLir);
             } else if (isStackSlot(result)) {
-                if (constant.isDefaultForKind() || constant.isNull()) {
-                    SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
-                    emitStore(g0.asValue(LIRKind.derive(input)), resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
-                } else {
-                    try (ScratchRegister sc = masm.getScratchRegister()) {
-                        Register scratch = sc.getRegister();
-                        long value = constant.asLong();
-                        if (isSimm13(value)) {
-                            masm.or(g0, (int) value, scratch);
-                        } else {
-                            new Setx(value, scratch).emit(masm);
-                        }
-                        SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
-                        emitStore(scratch.asValue(LIRKind.derive(input)), resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
-                    }
-                }
+                const2stack(crb, masm, result, constantTableBase, input, delaySlotLir, constant);
             } else {
                 throw JVMCIError.shouldNotReachHere("Result is a: " + result);
             }
@@ -621,7 +631,37 @@
         }
     }
 
-    private static void reg2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
+    public static void const2stack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Register constantTableBase, Value input, SPARCDelayedControlTransfer delaySlotLir,
+                    JavaConstant constant) {
+        if (constant.isDefaultForKind() || constant.isNull()) {
+            SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
+            emitStore(g0.asValue(LIRKind.derive(input)), resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+        } else {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
+                Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.derive(constant));
+                const2reg(crb, masm, scratchRegisterValue, constantTableBase, constant, SPARCDelayedControlTransfer.DUMMY);
+                SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
+                emitStore(scratchRegisterValue, resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+            }
+        }
+    }
+
+    public static void stack2stack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
+        try (ScratchRegister sc = masm.getScratchRegister()) {
+            SPARCAddress inputAddress = (SPARCAddress) crb.asAddress(input);
+            Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.derive(input));
+            emitLoad(crb, masm, inputAddress, scratchRegisterValue, false, input.getPlatformKind(), SPARCDelayedControlTransfer.DUMMY, null);
+            SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
+            emitStore(scratchRegisterValue, resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+        }
+    }
+
+    public static void reg2stack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
+        SPARCAddress resultAddress = (SPARCAddress) crb.asAddress(result);
+        emitStore(input, resultAddress, input.getPlatformKind(), delaySlotLir, null, crb, masm);
+    }
+
+    public static void reg2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
         final Register src = asRegister(input);
         final Register dst = asRegister(result);
         if (src.equals(dst)) {
@@ -677,24 +717,28 @@
         }
     }
 
-    private static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, JavaConstant input, SPARCDelayedControlTransfer delaySlotLir) {
+    public static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Register constantTableBase, JavaConstant input, SPARCDelayedControlTransfer delaySlotLir) {
         try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
-            boolean hasVIS3 = ((SPARC) masm.target.arch).getFeatures().contains(CPUFeature.VIS3);
+            Set<CPUFeature> cpuFeatures = ((SPARC) masm.target.arch).getFeatures();
+            boolean hasVIS1 = cpuFeatures.contains(CPUFeature.VIS1);
+            boolean hasVIS3 = cpuFeatures.contains(CPUFeature.VIS3);
             Register resultRegister = asRegister(result);
             switch (input.getKind().getStackKind()) {
                 case Int:
                     if (input.isDefaultForKind()) {
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.clr(resultRegister);
-                    } else if (isSimm13(input.asLong())) {
+                    } else if (isSimm13(input.asInt())) {
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.or(g0, input.asInt(), resultRegister);
                     } else {
-                        Setx set = new Setx(input.asLong(), resultRegister, false, true);
-                        set.emitFirstPartOfDelayed(masm);
-                        delaySlotLir.emitControlTransfer(crb, masm);
-                        set.emitSecondPartOfDelayed(masm);
+                        if (constantTableBase.equals(g0)) {
+                            throw JVMCIError.shouldNotReachHere();
+                        } else {
+                            Runnable recordReference = () -> crb.recordDataReferenceInCode(input, input.getKind().getByteCount());
+                            loadFromConstantTable(crb, masm, input.getKind(), constantTableBase, resultRegister, delaySlotLir, recordReference);
+                        }
                     }
                     break;
                 case Long:
@@ -705,35 +749,25 @@
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.or(g0, (int) input.asLong(), resultRegister);
                     } else {
-                        Setx setx = new Setx(input.asLong(), resultRegister, false, true);
-                        setx.emitFirstPartOfDelayed(masm);
-                        delaySlotLir.emitControlTransfer(crb, masm);
-                        setx.emitSecondPartOfDelayed(masm);
+                        Runnable recordReference = () -> crb.asLongConstRef(input);
+                        loadFromConstantTable(crb, masm, Long, constantTableBase, resultRegister, delaySlotLir, recordReference);
                     }
                     break;
                 case Float: {
                     float constant = input.asFloat();
                     int constantBits = java.lang.Float.floatToIntBits(constant);
-                    if (constantBits == 0) {
+                    if (hasVIS1 && constantBits == 0) {
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.fzeros(resultRegister);
                     } else {
-                        if (hasVIS3) {
-                            if (isSimm13(constantBits)) {
-                                masm.or(g0, constantBits, scratch);
-                            } else {
-                                new Setx(constantBits, scratch, false).emit(masm);
-                            }
+                        if (hasVIS3 && isSimm13(constantBits)) {
+                            masm.or(g0, constantBits, scratch);
                             delaySlotLir.emitControlTransfer(crb, masm);
-                            // Now load the float value
                             masm.movwtos(scratch, resultRegister);
                         } else {
-                            crb.asFloatConstRef(input);
+                            Runnable recordReference = () -> crb.asFloatConstRef(input);
                             // First load the address into the scratch register
-                            new Setx(0, scratch, true).emit(masm);
-                            // Now load the float value
-                            delaySlotLir.emitControlTransfer(crb, masm);
-                            masm.ldf(new SPARCAddress(scratch, 0), resultRegister);
+                            loadFromConstantTable(crb, masm, Float, constantTableBase, resultRegister, delaySlotLir, recordReference);
                         }
                     }
                     break;
@@ -741,26 +775,17 @@
                 case Double: {
                     double constant = input.asDouble();
                     long constantBits = java.lang.Double.doubleToRawLongBits(constant);
-                    if (constantBits == 0) {
+                    if (hasVIS1 && constantBits == 0) {
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.fzerod(resultRegister);
                     } else {
-                        if (hasVIS3) {
-                            if (isSimm13(constantBits)) {
-                                masm.or(g0, (int) constantBits, scratch);
-                            } else {
-                                new Setx(constantBits, scratch, false).emit(masm);
-                            }
+                        if (hasVIS3 && isSimm13(constantBits)) {
+                            masm.or(g0, (int) constantBits, scratch);
                             delaySlotLir.emitControlTransfer(crb, masm);
-                            // Now load the float value
                             masm.movxtod(scratch, resultRegister);
                         } else {
-                            crb.asDoubleConstRef(input);
-                            // First load the address into the scratch register
-                            new Setx(0, scratch, true).emit(masm);
-                            delaySlotLir.emitControlTransfer(crb, masm);
-                            // Now load the float value
-                            masm.lddf(new SPARCAddress(scratch, 0), resultRegister);
+                            Runnable recordReference = () -> crb.asDoubleConstRef(input);
+                            loadFromConstantTable(crb, masm, Double, constantTableBase, resultRegister, delaySlotLir, recordReference);
                         }
                     }
                     break;
@@ -769,11 +794,9 @@
                     if (input.isNull()) {
                         delaySlotLir.emitControlTransfer(crb, masm);
                         masm.clr(resultRegister);
-                    } else if (crb.target.inlineObjects) {
-                        crb.recordInlineDataInCode(input); // relocatable cannot be delayed
-                        new Setx(0xDEADDEADDEADDEADL, resultRegister, true).emit(masm);
                     } else {
-                        throw JVMCIError.unimplemented();
+                        Runnable recordReference = () -> crb.recordDataReferenceInCode(input, 8);
+                        loadFromConstantTable(crb, masm, Long, constantTableBase, resultRegister, delaySlotLir, recordReference);
                     }
                     break;
                 default:
@@ -798,8 +821,8 @@
         }
     }
 
-    private static void emitLoad(SPARCAddress address, Value result, boolean signExtend, PlatformKind kind, SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state,
-                    CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+    private static void emitLoad(CompilationResultBuilder crb, SPARCMacroAssembler masm, SPARCAddress address, Value result, boolean signExtend, PlatformKind kind,
+                    SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state) {
         try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
             final SPARCAddress addr = generateSimm13OffsetLoad(address, masm, scratch);
@@ -856,7 +879,7 @@
         }
     }
 
-    private static void emitStore(Value input, SPARCAddress address, PlatformKind kind, SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state, CompilationResultBuilder crb,
+    public static void emitStore(Value input, SPARCAddress address, PlatformKind kind, SPARCDelayedControlTransfer delayedControlTransfer, LIRFrameState state, CompilationResultBuilder crb,
                     SPARCMacroAssembler masm) {
         try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
@@ -894,4 +917,58 @@
             }
         }
     }
+
+    /**
+     * This method creates a load from the constant section. It automatically respects the different
+     * patterns used for small constant sections (<8k) and large constant sections (>=8k). The
+     * generated patterns by this method must be understood by
+     * CodeInstaller::pd_patch_DataSectionReference (jvmciCodeInstaller_sparc.cpp).
+     */
+    public static void loadFromConstantTable(CompilationResultBuilder crb, SPARCMacroAssembler masm, Kind kind, Register constantTableBase, Register dest,
+                    SPARCDelayedControlTransfer delaySlotInstruction, Runnable recordReference) {
+        SPARCAddress address;
+        ScratchRegister scratch = null;
+        try {
+            if (masm.isImmediateConstantLoad()) {
+                address = new SPARCAddress(constantTableBase, 0);
+                // Make delayed only, when using immediate constant load.
+                delaySlotInstruction.emitControlTransfer(crb, masm);
+                recordReference.run();
+            } else {
+                scratch = masm.getScratchRegister();
+                Register sr = scratch.getRegister();
+                recordReference.run();
+                new Sethix(0, sr, true).emit(masm);
+                address = new SPARCAddress(sr, 0);
+            }
+            switch (kind) {
+                case Boolean:
+                case Byte:
+                    masm.ldub(address, dest);
+                    break;
+                case Short:
+                case Char:
+                    masm.lduh(address, dest);
+                    break;
+                case Int:
+                    masm.lduw(address, dest);
+                    break;
+                case Long:
+                    masm.ldx(address, dest);
+                    break;
+                case Float:
+                    masm.ldf(address, dest);
+                    break;
+                case Double:
+                    masm.lddf(address, dest);
+                    break;
+                default:
+                    throw new InternalError("Unknown constant load kind: " + kind);
+            }
+        } finally {
+            if (scratch != null) {
+                scratch.close();
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.lir.sparc;
 
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.sparc.SPARCDelayedControlTransfer.*;
 import static jdk.internal.jvmci.code.ValueUtil.*;
 
 import java.util.*;
@@ -43,6 +44,7 @@
 public class SPARCSaveRegistersOp extends SPARCLIRInstruction implements SaveRegistersOp {
     public static final LIRInstructionClass<SPARCSaveRegistersOp> TYPE = LIRInstructionClass.create(SPARCSaveRegistersOp.class);
     public static final Register RETURN_REGISTER_STORAGE = SPARC.d62;
+    public static final SizeEstimate SIZE = SizeEstimate.create(32);
     /**
      * The registers (potentially) saved by this operation.
      */
@@ -66,18 +68,13 @@
      * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned}
      */
     public SPARCSaveRegistersOp(Register[] savedRegisters, StackSlotValue[] savedRegisterLocations, boolean supportsRemove) {
-        super(TYPE);
+        super(TYPE, SIZE);
         assert Arrays.asList(savedRegisterLocations).stream().allMatch(ValueUtil::isVirtualStackSlot);
         this.savedRegisters = savedRegisters;
         this.slots = savedRegisterLocations;
         this.supportsRemove = supportsRemove;
     }
 
-    private static void saveRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, StackSlot result, Register register) {
-        RegisterValue input = register.asValue(result.getLIRKind());
-        SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY);
-    }
-
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         // Can be used with VIS3
@@ -92,7 +89,11 @@
         for (int i = 0; i < savedRegisters.length; i++) {
             if (savedRegisters[i] != null) {
                 assert isStackSlot(slots[i]) : "not a StackSlot: " + slots[i];
-                saveRegister(crb, masm, asStackSlot(slots[i]), savedRegisters[i]);
+                Register savedRegister = savedRegisters[i];
+                StackSlot slot = asStackSlot(slots[i]);
+                SPARCAddress slotAddress = (SPARCAddress) crb.asAddress(slot);
+                RegisterValue input = savedRegister.asValue(slot.getLIRKind());
+                SPARCMove.emitStore(input, slotAddress, slot.getPlatformKind(), DUMMY, null, crb, masm);
             }
         }
     }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCTestOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -34,12 +34,13 @@
 
 public class SPARCTestOp extends SPARCLIRInstruction {
     public static final LIRInstructionClass<SPARCTestOp> TYPE = LIRInstructionClass.create(SPARCTestOp.class);
+    public static final SizeEstimate SIZE = SizeEstimate.create(1);
 
     @Use({REG}) protected Value x;
     @Use({REG, CONST}) protected Value y;
 
     public SPARCTestOp(Value x, Value y) {
-        super(TYPE);
+        super(TYPE, SIZE);
         this.x = x;
         this.y = y;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Sat Jun 27 18:02:44 2015 +0200
@@ -265,6 +265,12 @@
             instructions.set(index, replacement);
         }
 
+        public void remove(LIR lir) {
+            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+            assert instructions.get(index).equals(this) : String.format("Removing the wrong instruction: %s instead of %s", instructions.get(index), this);
+            instructions.remove(index);
+        }
+
         @Override
         public void emitCode(CompilationResultBuilder crb) {
             if (block != null) {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Sat Jun 27 18:02:44 2015 +0200
@@ -25,6 +25,7 @@
 import static jdk.internal.jvmci.code.ValueUtil.*;
 
 import java.util.*;
+import java.util.function.*;
 
 import jdk.internal.jvmci.code.*;
 import jdk.internal.jvmci.code.CompilationResult.*;
@@ -88,6 +89,9 @@
 
     private final IdentityHashMap<Constant, Data> dataCache;
 
+    private Consumer<LIRInstruction> beforeOp;
+    private Consumer<LIRInstruction> afterOp;
+
     public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, CompilationResult compilationResult) {
         this.target = codeCache.getTarget();
         this.codeCache = codeCache;
@@ -368,7 +372,13 @@
             }
 
             try {
+                if (beforeOp != null) {
+                    beforeOp.accept(op);
+                }
                 emitOp(this, op);
+                if (afterOp != null) {
+                    afterOp.accept(op);
+                }
             } catch (JVMCIError e) {
                 throw e.addContext("lir instruction", block + "@" + op.id() + " " + op + "\n" + lir.codeEmittingOrder());
             }
@@ -395,4 +405,9 @@
             dataCache.clear();
         }
     }
+
+    public void setOpCallback(Consumer<LIRInstruction> beforeOp, Consumer<LIRInstruction> afterOp) {
+        this.beforeOp = beforeOp;
+        this.afterOp = afterOp;
+    }
 }
--- a/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Sat Jun 27 17:59:37 2015 +0200
+++ b/jvmci/jdk.internal.jvmci.hotspot.sparc/src/jdk/internal/jvmci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java	Sat Jun 27 18:02:44 2015 +0200
@@ -43,7 +43,7 @@
     protected TargetDescription createTarget(HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
-        final boolean inlineObjects = true;
+        final boolean inlineObjects = false;
         return new HotSpotTargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
     }
 
--- a/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Sat Jun 27 17:59:37 2015 +0200
+++ b/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp	Sat Jun 27 18:02:44 2015 +0200
@@ -66,12 +66,22 @@
 
 void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
   address pc = _instructions->start() + pc_offset;
-  address const_start = _constants->start();
-  address dest = _constants->start() + data_offset;
-
-  _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
-  _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
-  TRACE_jvmci_3("relocating at %p with destination at %p (%d)", pc, dest, data_offset);
+  NativeInstruction* inst = nativeInstruction_at(pc);
+  NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
+  if(inst->is_sethi() && inst1->is_nop()) {
+      address const_start = _constants->start();
+      address dest = _constants->start() + data_offset;
+      if(_constants_size > 0) {
+        _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+        _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+      }
+      TRACE_jvmci_3("relocating at %p (+%d) with destination at %d", pc, pc_offset, data_offset);
+  } else {
+    NativeMovRegMem* load = nativeMovRegMem_at(pc);
+    // The base pointer is set 4k off (see SPARCLoadConstantTableBaseOp)
+    load->set_offset(data_offset - (1<<12));
+    TRACE_jvmci_3("relocating ld at %p (+%d) with destination at %d", pc, pc_offset, data_offset);
+  }
 }
 
 void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {