changeset 16955:7ef0a2355540

Merged.
author David Piorkowski <david.piorkowski@oracle.com>
date Tue, 26 Aug 2014 09:35:08 -0700
parents 5ed920f3aa18 (current diff) 85020469ed2b (diff)
children 39ca6be0d5eb 997899955e72 a1427e40deaf
files
diffstat 58 files changed, 2708 insertions(+), 347 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java	Tue Aug 26 09:35:08 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.asm.amd64.test;
 
+import static org.junit.Assume.*;
+
 import java.nio.*;
 
 import org.junit.*;
@@ -35,6 +37,11 @@
 
 public class SimpleAssemblerTest extends AssemblerTest {
 
+    @Before
+    public void assumeNotSparc() {
+        assumeFalse(System.getProperty("os.arch").toLowerCase().contains("sparc"));
+    }
+
     @Test
     public void intTest() {
         CodeGenTest test = new CodeGenTest() {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java	Tue Aug 26 09:35:08 2014 -0700
@@ -77,6 +77,7 @@
             final int inst = masm.getInt(pos);
             Op2s op2 = Op2s.byValue((inst&OP2_MASK) >> OP2_SHIFT);
             switch(op2) {
+                case Br:
                 case Fb:
                     return Fmt00b.read(masm, op2, pos);
                 case Sethi:
@@ -213,6 +214,10 @@
         private static final int DISP22_MASK = 0b00000000001111111111111111111111;
         // @formatter:on
 
+        public Fmt00b(boolean annul, ConditionFlag cond, Op2s op2, Label label) {
+            this(annul ? 1 : 0, cond.getValue(), op2.getValue(), 0, label);
+        }
+
         public Fmt00b(boolean annul, FCond cond, Op2s op2, Label label) {
             this(annul ? 1 : 0, cond.getValue(), op2.getValue(), 0, label);
         }
@@ -810,14 +815,19 @@
         }
 
         public void verify() {
-            assert ((rd << RD_SHIFT) & RD_MASK) == (rd << RD_SHIFT);
-            assert ((op3 << OP3_SHIFT) & OP3_MASK) == (op3 << OP3_SHIFT);
-            assert ((rs1 << RS1_SHIFT) & RS1_MASK) == (rs1 << RS1_SHIFT);
-            assert ((i << I_SHIFT) & I_MASK) == (i << I_SHIFT);
-            assert ((x << X_SHIFT) & X_MASK) == (x << X_SHIFT);
-            assert ((immAsi << IMM_ASI_SHIFT) & IMM_ASI_MASK) == (immAsi << IMM_ASI_SHIFT);
-            assert ((rs2 << RS2_SHIFT) & RS2_MASK) == (rs2 << RS2_SHIFT);
-            assert isSimm13(simm13);
+            assert ((rd << RD_SHIFT) & RD_MASK) == (rd << RD_SHIFT) : this;
+            assert ((op3 << OP3_SHIFT) & OP3_MASK) == (op3 << OP3_SHIFT) : this;
+            assert ((rs1 << RS1_SHIFT) & RS1_MASK) == (rs1 << RS1_SHIFT) : this;
+            assert ((i << I_SHIFT) & I_MASK) == (i << I_SHIFT) : this;
+            assert ((x << X_SHIFT) & X_MASK) == (x << X_SHIFT) : this;
+            assert ((immAsi << IMM_ASI_SHIFT) & IMM_ASI_MASK) == (immAsi << IMM_ASI_SHIFT) : this;
+            assert ((rs2 << RS2_SHIFT) & RS2_MASK) == (rs2 << RS2_SHIFT) : this;
+            assert isSimm13(simm13) : this;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s: [rd: 0x%x, op3: 0x%x, rs1: 0x%x, i: 0x%x, x: 0x%x, immAsi: 0x%x, rs2: 0x%x, simm13: 0x%x", getClass().getName(), rd, op3, rs1, i, x, immAsi, rs2, simm13);
         }
     }
 
@@ -1432,7 +1442,8 @@
         Movstouw(0x111, "movstouw"),
         Movstosw(0x113, "movstosw"),
         Movxtod(0x118, "movxtod"),
-        Movwtos(0x119, "movwtos"),
+        Movwtos(0b1_0001_1001, "movwtos"),
+        UMulxhi(0b0_0001_0110, "umulxhi"),
         // end VIS3
 
         // start CAMMELLIA
@@ -1682,6 +1693,18 @@
         public String getOperator() {
             return operator;
         }
+
+        public ConditionFlag negate() {
+            switch (this) {
+                case CarrySet:
+                    return CarryClear;
+                case CarryClear:
+                    return CarrySet;
+                default:
+                    GraalInternalError.unimplemented();
+            }
+            return null;
+        }
     }
 
     public enum RCondition {
@@ -1978,6 +2001,13 @@
         }
     }
 
+    public static class Umulxhi extends Fmt3p {
+        public Umulxhi(Register src1, Register src2, Register dst) {
+            /* VIS3 only */
+            super(Ops.ArithOp, Op3s.Impdep1, Opfs.UMulxhi, src1, src2, dst);
+        }
+    }
+
     public static class Movxtod extends Fmt3p {
         public Movxtod(Register src, Register dst) {
             /* VIS3 only */
@@ -2812,6 +2842,13 @@
         }
     }
 
+    public static class Fsmuld extends Fmt3p {
+
+        public Fsmuld(Register src1, Register src2, Register dst) {
+            super(Ops.ArithOp, Op3s.Fpop1, Opfs.Fsmuld, src1, src2, dst);
+        }
+    }
+
     public static class Fmul8x16 extends Fmt3p {
 
         public Fmul8x16(Register src1, Register src2, Register dst) {
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Tue Aug 26 09:35:08 2014 -0700
@@ -327,7 +327,7 @@
         public void emit(SPARCMacroAssembler masm) {
             if (value == 0) {
                 new Clr(dst).emit(masm);
-            } else if (-4095 <= value && value <= 4096) {
+            } else if (isSimm13(value)) {
                 new Or(g0, value, dst).emit(masm);
             } else if (value >= 0 && ((value & 0x3FFF) == 0)) {
                 new Sethi(hi22(value), dst).emit(masm);
--- a/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java	Tue Aug 26 09:35:08 2014 -0700
@@ -32,7 +32,7 @@
 
     @Before
     public void setUp() {
-        assumeTrue(isArchitecture("AMD64"));
+        assumeTrue(isArchitecture("x86_64"));
     }
 
     @Test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/DominatorOptimizationProblem.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, 2014, 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.compiler.common.cfg;
+
+import java.util.*;
+import java.util.stream.*;
+
+/**
+ * This class represents a dominator tree problem, i.e. a problem which can be solved by traversing
+ * the dominator (sub-)tree.
+ *
+ * @param <E> An enum that describes the flags that can be associated with a block.
+ * @param <C> An arbitrary cost type that is associated with a block. It is intended to carry
+ *            information needed to calculate the solution. Note that {@code C} should not contain
+ *            boolean flags. Use an enum entry in {@code E} instead.
+ */
+public abstract class DominatorOptimizationProblem<E extends Enum<E>, C> {
+
+    private List<? extends AbstractBlock<?>> blocks;
+    private EnumMap<E, BitSet> flags;
+    private BlockMap<C> costs;
+
+    protected DominatorOptimizationProblem(Class<E> flagType, AbstractControlFlowGraph<?> cfg) {
+        this.blocks = cfg.getBlocks();
+        flags = new EnumMap<>(flagType);
+        costs = new BlockMap<>(cfg);
+        assert verify(blocks);
+    }
+
+    private static boolean verify(List<? extends AbstractBlock<?>> blocks) {
+        for (int i = 0; i < blocks.size(); i++) {
+            AbstractBlock<?> block = blocks.get(i);
+            if (i != block.getId()) {
+                assert false : String.format("Id index mismatch @ %d vs. %s.getId()==%d", i, block, block.getId());
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public final List<? extends AbstractBlock<?>> getBlocks() {
+        return blocks;
+    }
+
+    public final AbstractBlock<?> getBlockForId(int id) {
+        AbstractBlock<?> block = blocks.get(id);
+        assert block.getId() == id : "wrong block-to-id mapping";
+        return block;
+    }
+
+    /**
+     * Sets a flag for a block.
+     */
+    public final void set(E flag, AbstractBlock<?> block) {
+        BitSet bitSet = flags.get(flag);
+        if (bitSet == null) {
+            bitSet = new BitSet(blocks.size());
+            flags.put(flag, bitSet);
+        }
+        bitSet.set(block.getId());
+    }
+
+    /**
+     * Checks whether a flag is set for a block.
+     */
+    public final boolean get(E flag, AbstractBlock<?> block) {
+        BitSet bitSet = flags.get(flag);
+        return bitSet == null ? false : bitSet.get(block.getId());
+    }
+
+    /**
+     * Returns a {@linkplain Stream} of blocks for which {@code flag} is set.
+     */
+    public final Stream<? extends AbstractBlock<?>> stream(E flag) {
+        return getBlocks().stream().filter(block -> get(flag, block));
+    }
+
+    /**
+     * Returns the cost object associated with {@code block}. Might return {@code null} if not set.
+     */
+    public final C getCost(AbstractBlock<?> block) {
+        C cost = costs.get(block);
+        return cost;
+    }
+
+    /**
+     * Sets the cost for a {@code block}.
+     */
+    public final void setCost(AbstractBlock<?> block, C cost) {
+        costs.put(block, cost);
+    }
+
+    /**
+     * Sets {@code flag} for all blocks along the dominator path from {@code block} to the root
+     * until a block it finds a block where {@code flag} is already set.
+     */
+    public final void setDominatorPath(E flag, AbstractBlock<?> block) {
+        BitSet bitSet = flags.get(flag);
+        if (bitSet == null) {
+            bitSet = new BitSet(blocks.size());
+            flags.put(flag, bitSet);
+        }
+        for (AbstractBlock<?> b = block; b != null && !bitSet.get(b.getId()); b = b.getDominator()) {
+            // mark block
+            bitSet.set(b.getId());
+        }
+    }
+
+    /**
+     * Returns a {@link Stream} of flags associated with {@code block}.
+     */
+    public final Stream<E> getFlagsForBlock(AbstractBlock<?> block) {
+        return getFlags().stream().filter(flag -> get(flag, block));
+    }
+
+    /**
+     * Returns the {@link Set} of flags that can be set for this
+     * {@linkplain DominatorOptimizationProblem problem}.
+     */
+    public final Set<E> getFlags() {
+        return flags.keySet();
+    }
+
+    /**
+     * Returns the name of a flag.
+     */
+    public String getName(E flag) {
+        return flag.toString();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableCFG.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2014, 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.compiler.common.cfg;
+
+import java.util.*;
+import java.util.function.*;
+
+/**
+ * Represents a control-flow graph where each node can be annotated with arbitrary property pairs of
+ * the form ({@linkplain String name}, {@linkplain String value}).
+ */
+public interface PrintableCFG {
+
+    List<? extends AbstractBlock<?>> getBlocks();
+
+    /**
+     * Applies {@code action} to all extra property pairs (name, value) of {@code block}.
+     *
+     * @param block a block from {@link #getBlocks()}.
+     * @param action a {@link BiConsumer consumer}.
+     */
+    default void forEachPropertyPair(AbstractBlock<?> block, BiConsumer<String, String> action) {
+        // no extra properties per default
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PrintableDominatorOptimizationProblem.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, 2014, 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.compiler.common.cfg;
+
+import java.util.function.*;
+
+/**
+ * A {@linkplain PrintableCFG printable} {@link DominatorOptimizationProblem}.
+ */
+public abstract class PrintableDominatorOptimizationProblem<E extends Enum<E>, C extends PropertyConsumable> extends DominatorOptimizationProblem<E, C> implements PrintableCFG {
+
+    protected PrintableDominatorOptimizationProblem(Class<E> keyType, AbstractControlFlowGraph<?> cfg) {
+        super(keyType, cfg);
+    }
+
+    public void forEachPropertyPair(AbstractBlock<?> block, BiConsumer<String, String> action) {
+        // for each flag
+        getFlags().forEach(flag -> ((BiConsumer<String, Boolean>) (name, value) -> action.accept(name, value ? "true" : "false")).accept(getName(flag), get(flag, block)));
+        // for each property
+        C cost = getCost(block);
+        if (cost != null) {
+            cost.forEachProperty((name, value) -> action.accept(name, value));
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/PropertyConsumable.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 2014, 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.compiler.common.cfg;
+
+import java.util.function.*;
+
+public interface PropertyConsumable {
+
+    void forEachProperty(BiConsumer<String, String> action);
+}
--- a/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc.test/src/com/oracle/graal/compiler/sparc/test/SPARCAllocatorTest.java	Tue Aug 26 09:35:08 2014 -0700
@@ -55,7 +55,7 @@
 
     @Test
     public void test3() {
-        test("test3snippet", 4, 0, 0);
+        test("test3snippet", 3, 1, 0);
     }
 
     public static long test3snippet(long x) {
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Tue Aug 26 09:35:08 2014 -0700
@@ -35,6 +35,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -232,7 +233,7 @@
                 break;
             case Float:
             case Double:
-                append(new BranchOp(cond, trueDestination, falseDestination, kind));
+                append(new BranchOp(finalCondition, trueDestination, falseDestination, kind));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -241,8 +242,7 @@
 
     @Override
     public void emitOverflowCheckBranch(LabelRef overflow, LabelRef noOverflow, double overflowProbability) {
-        // append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, label));
-        throw GraalInternalError.unimplemented();
+        append(new BranchOp(ConditionFlag.CarrySet, overflow, noOverflow, Kind.Long));
     }
 
     @Override
@@ -308,10 +308,10 @@
         switch ((Kind) cmpKind) {
             case Short:
             case Char:
-                append(new CompareOp(ICMP, emitZeroExtend(left, 16, 32), emitZeroExtend(right, 16, 32)));
+                append(new CompareOp(ICMP, emitSignExtend(left, 16, 32), emitSignExtend(right, 16, 32)));
                 break;
             case Byte:
-                append(new CompareOp(ICMP, emitZeroExtend(left, 8, 32), emitZeroExtend(right, 8, 32)));
+                append(new CompareOp(ICMP, emitSignExtend(left, 8, 32), emitSignExtend(right, 8, 32)));
                 break;
             case Int:
                 append(new CompareOp(ICMP, left, right));
@@ -355,9 +355,7 @@
 
     @Override
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
-        // a temp is needed for loading long and object constants
-        boolean needsTemp = key.getKind() == Kind.Long || key.getKind() == Kind.Object;
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL));
+        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, newVariable(key.getLIRKind())));
     }
 
     @Override
@@ -457,16 +455,16 @@
         Variable result = newVariable(LIRKind.derive(input));
         switch (input.getKind().getStackKind()) {
             case Long:
-                append(new Op1Stack(LNEG, result, input));
+                append(new Unary2Op(LNEG, result, load(input)));
                 break;
             case Int:
-                append(new Op1Stack(INEG, result, input));
+                append(new Unary2Op(INEG, result, load(input)));
                 break;
             case Float:
-                append(new Op1Stack(FNEG, result, input));
+                append(new Unary2Op(FNEG, result, load(input)));
                 break;
             case Double:
-                append(new Op1Stack(DNEG, result, input));
+                append(new Unary2Op(DNEG, result, load(input)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -479,10 +477,10 @@
         Variable result = newVariable(LIRKind.derive(input));
         switch (input.getKind().getStackKind()) {
             case Int:
-                append(new Op1Stack(INOT, result, input));
+                append(new Unary2Op(INOT, result, load(input)));
                 break;
             case Long:
-                append(new Op1Stack(LNOT, result, input));
+                append(new Unary2Op(LNOT, result, load(input)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -597,12 +595,33 @@
 
     @Override
     public Value emitMulHigh(Value a, Value b) {
-        throw GraalInternalError.unimplemented();
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitMulHigh(IMUL, a, b);
+            case Long:
+                return emitMulHigh(LMUL, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     @Override
     public Value emitUMulHigh(Value a, Value b) {
-        throw GraalInternalError.unimplemented();
+        switch (a.getKind().getStackKind()) {
+            case Int:
+                return emitMulHigh(IUMUL, a, b);
+            case Long:
+                return emitMulHigh(LUMUL, a, b);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private Value emitMulHigh(SPARCArithmetic opcode, Value a, Value b) {
+        Variable result = newVariable(LIRKind.derive(a, b));
+        MulHighOp mulHigh = new MulHighOp(opcode, load(a), load(b), result, newVariable(LIRKind.derive(a, b)));
+        append(mulHigh);
+        return result;
     }
 
     @Override
@@ -665,10 +684,10 @@
         Variable result = newVariable(LIRKind.derive(a, b));
         switch (a.getKind().getStackKind()) {
             case Int:
-                append(new RemOp(IUREM, result, a, loadNonConst(b), state, this));
+                append(new RemOp(IUREM, result, load(a), load(b), state, this));
                 break;
             case Long:
-                append(new RemOp(LUREM, result, a, loadNonConst(b), state, this));
+                append(new RemOp(LUREM, result, load(a), loadNonConst(b), state, this));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -680,9 +699,13 @@
     @Override
     public Value emitUDiv(Value a, Value b, LIRFrameState state) {
         SPARCArithmetic op;
+        Value actualA = a;
+        Value actualB = b;
         switch (a.getKind().getStackKind()) {
             case Int:
                 op = IUDIV;
+                actualA = emitZeroExtend(actualA, 32, 64);
+                actualB = emitZeroExtend(actualB, 32, 64);
                 break;
             case Long:
                 op = LUDIV;
@@ -690,7 +713,7 @@
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
-        return emitBinary(op, false, a, b, state);
+        return emitBinary(op, false, actualA, actualB, state);
     }
 
     @Override
@@ -912,14 +935,14 @@
             append(new BinaryRegConst(SPARCArithmetic.LAND, result, asAllocatable(inputVal), Constant.forLong(mask), null));
             return result;
         } else {
-            assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte : inputVal.getKind();
+            assert inputVal.getKind() == Kind.Int || inputVal.getKind() == Kind.Short || inputVal.getKind() == Kind.Byte || inputVal.getKind() == Kind.Char : inputVal.getKind();
             Variable result = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
             long mask = IntegerStamp.defaultMask(fromBits);
-            Constant constant = Constant.forLong(mask);
-            if (canInlineConstant(constant)) {
+            Constant constant = Constant.forInt((int) mask);
+            if (fromBits == 32) {
+                append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0)));
+            } else if (canInlineConstant(constant)) {
                 append(new BinaryRegConst(SPARCArithmetic.IAND, result, asAllocatable(inputVal), constant, null));
-            } else if (fromBits == 32) {
-                append(new ShiftOp(IUSHR, result, inputVal, Constant.forInt(0)));
             } else {
                 Variable maskVar = newVariable(LIRKind.derive(inputVal).changeType(Kind.Int));
                 emitMove(maskVar, constant);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Tue Aug 26 09:35:08 2014 -0700
@@ -41,6 +41,7 @@
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.constopt.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
@@ -256,6 +257,15 @@
                 throw Debug.handle(e);
             }
 
+            if (ConstantLoadOptimization.Options.ConstantLoadOptimization.getValue()) {
+                try (Scope s = Debug.scope("ConstantLoadOptimization", lir)) {
+                    ConstantLoadOptimization.optimize(lirGenRes.getLIR(), lirGen);
+                    Debug.dump(lir, "After constant load optimization");
+                } catch (Throwable e) {
+                    throw Debug.handle(e);
+                }
+            }
+
             try (Scope s = Debug.scope("Allocator", nodeLirGen)) {
                 if (backend.shouldAllocateRegisters()) {
                     new LinearScan(target, lir, frameMap).allocate();
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Tue Aug 26 09:35:08 2014 -0700
@@ -929,6 +929,9 @@
     private static DebugMetric createMetric(String format, Object arg1, Object arg2) {
         String name = formatDebugName(format, arg1, arg2);
         boolean conditional = enabledMetrics == null || !enabledMetrics.contains(name);
+        if (!ENABLED && conditional) {
+            return VOID_METRIC;
+        }
         return new MetricImpl(name, conditional);
     }
 
@@ -1203,6 +1206,9 @@
     private static DebugTimer createTimer(String format, Object arg1, Object arg2) {
         String name = formatDebugName(format, arg1, arg2);
         boolean conditional = enabledTimers == null || !enabledTimers.contains(name);
+        if (!ENABLED && conditional) {
+            return VOID_TIMER;
+        }
         return new TimerImpl(name, conditional);
     }
 
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Tue Aug 26 09:35:08 2014 -0700
@@ -42,12 +42,12 @@
     /**
      * The set of nodes in the graph, ordered by {@linkplain #register(Node) registration} time.
      */
-    private Node[] nodes;
+    Node[] nodes;
 
     /**
      * The number of valid entries in {@link #nodes}.
      */
-    private int nodesSize;
+    int nodesSize;
 
     /**
      * Records the modification count for nodes. This is only used in assertions.
@@ -562,56 +562,6 @@
         return new Mark(this);
     }
 
-    private class NodeIterator implements Iterator<Node> {
-
-        private int index;
-
-        public NodeIterator() {
-            this(0);
-        }
-
-        public NodeIterator(int index) {
-            this.index = index - 1;
-            forward();
-        }
-
-        private void forward() {
-            if (index < nodesSize) {
-                do {
-                    index++;
-                } while (index < nodesSize && nodes[index] == null);
-            }
-        }
-
-        @Override
-        public boolean hasNext() {
-            checkForDeletedNode();
-            return index < nodesSize;
-        }
-
-        private void checkForDeletedNode() {
-            if (index < nodesSize) {
-                while (index < nodesSize && nodes[index] == null) {
-                    index++;
-                }
-            }
-        }
-
-        @Override
-        public Node next() {
-            try {
-                return nodes[index];
-            } finally {
-                forward();
-            }
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
     /**
      * Returns an {@link Iterable} providing all nodes added since the last {@link Graph#getMark()
      * mark}.
@@ -622,7 +572,7 @@
 
             @Override
             public Iterator<Node> iterator() {
-                return new NodeIterator(index);
+                return new GraphNodeIterator(Graph.this, index);
             }
         };
     }
@@ -637,7 +587,7 @@
 
             @Override
             public Iterator<Node> iterator() {
-                return new NodeIterator();
+                return new GraphNodeIterator(Graph.this);
             }
 
             @Override
@@ -709,15 +659,17 @@
         return true;
     }
 
-    private class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
+    private static class TypedNodeIterator<T extends IterableNodeType> implements Iterator<T> {
 
+        private final Graph graph;
         private final int[] ids;
         private final Node[] current;
 
         private int currentIdIndex;
         private boolean needsForward;
 
-        public TypedNodeIterator(NodeClass clazz) {
+        public TypedNodeIterator(NodeClass clazz, Graph graph) {
+            this.graph = graph;
             ids = clazz.iterableIds();
             currentIdIndex = 0;
             current = new Node[ids.length];
@@ -743,7 +695,7 @@
             return current();
         }
 
-        private Node skipDeleted(Node node) {
+        private static Node skipDeleted(Node node) {
             Node n = node;
             while (n != null && n.isDeleted()) {
                 n = n.typeCacheNext;
@@ -757,7 +709,7 @@
             while (true) {
                 Node next;
                 if (current() == PLACE_HOLDER) {
-                    next = getStartNode(ids[currentIdIndex]);
+                    next = graph.getStartNode(ids[currentIdIndex]);
                 } else {
                     next = current().typeCacheNext;
                 }
@@ -821,7 +773,7 @@
 
             @Override
             public Iterator<T> iterator() {
-                return new TypedNodeIterator<>(nodeClass);
+                return new TypedNodeIterator<>(nodeClass, Graph.this);
             }
         };
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/GraphNodeIterator.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, 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.graph;
+
+import java.util.*;
+
+/**
+ * Iterates over the nodes in a given graph.
+ */
+class GraphNodeIterator implements Iterator<Node> {
+
+    private final Graph graph;
+    private int index;
+
+    public GraphNodeIterator(Graph graph) {
+        this(graph, 0);
+    }
+
+    public GraphNodeIterator(Graph graph, int index) {
+        this.graph = graph;
+        this.index = index - 1;
+        forward();
+    }
+
+    private void forward() {
+        if (index < graph.nodesSize) {
+            do {
+                index++;
+            } while (index < graph.nodesSize && graph.nodes[index] == null);
+        }
+    }
+
+    @Override
+    public boolean hasNext() {
+        checkForDeletedNode();
+        return index < graph.nodesSize;
+    }
+
+    private void checkForDeletedNode() {
+        while (index < graph.nodesSize && graph.nodes[index] == null) {
+            index++;
+        }
+    }
+
+    @Override
+    public Node next() {
+        try {
+            return graph.nodes[index];
+        } finally {
+            forward();
+        }
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Tue Aug 26 09:35:08 2014 -0700
@@ -152,16 +152,16 @@
     // therefore points to the next Node of the same type.
     Node typeCacheNext;
 
-    private static final int INLINE_USAGE_COUNT = 2;
+    static final int INLINE_USAGE_COUNT = 2;
     private static final Node[] NO_NODES = {};
 
     /**
      * Head of usage list. The elements of the usage list in order are {@link #usage0},
      * {@link #usage1} and {@link #extraUsages}. The first null entry terminates the list.
      */
-    private Node usage0;
-    private Node usage1;
-    private Node[] extraUsages;
+    Node usage0;
+    Node usage1;
+    Node[] extraUsages;
 
     private Node predecessor;
 
@@ -210,95 +210,6 @@
         return getNodeClass().getSuccessorIterable(this);
     }
 
-    class NodeUsageIterator implements java.util.Iterator<Node> {
-
-        int index = -1;
-        Node current;
-
-        private void advance() {
-            current = null;
-            index++;
-            if (index == 0) {
-                current = usage0;
-            } else if (index == 1) {
-                current = usage1;
-            } else {
-                if (index - INLINE_USAGE_COUNT < extraUsages.length) {
-                    current = extraUsages[index - INLINE_USAGE_COUNT];
-                }
-            }
-        }
-
-        public NodeUsageIterator() {
-            advance();
-        }
-
-        public boolean hasNext() {
-            return current != null;
-        }
-
-        public Node next() {
-            Node result = current;
-            if (result == null) {
-                throw new NoSuchElementException();
-            }
-            advance();
-            return result;
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-    }
-
-    class NodeUsageWithModCountIterator extends NodeUsageIterator {
-
-        private final int expectedModCount = usageModCount();
-
-        @Override
-        public boolean hasNext() {
-            if (expectedModCount != usageModCount()) {
-                throw new ConcurrentModificationException();
-            }
-            return super.hasNext();
-        }
-
-        @Override
-        public Node next() {
-            if (expectedModCount != usageModCount()) {
-                throw new ConcurrentModificationException();
-            }
-            return super.next();
-        }
-    }
-
-    class NodeUsageIterable implements com.oracle.graal.graph.iterators.NodeIterable<Node> {
-
-        public NodeUsageIterator iterator() {
-            if (MODIFICATION_COUNTS_ENABLED) {
-                return new NodeUsageWithModCountIterator();
-            } else {
-                return new NodeUsageIterator();
-            }
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return usage0 == null;
-        }
-
-        @Override
-        public boolean isNotEmpty() {
-            return usage0 != null;
-        }
-
-        @Override
-        public int count() {
-            return usageCount();
-        }
-    }
-
     int getUsageCountUpperBound() {
         assert recordsUsages();
         if (usage0 == null) {
@@ -315,7 +226,7 @@
      */
     public final NodeIterable<Node> usages() {
         assert recordsUsages() : this;
-        return new NodeUsageIterable();
+        return new NodeUsageIterable(this);
     }
 
     /**
@@ -392,7 +303,7 @@
         }
     }
 
-    private int usageCount() {
+    int usageCount() {
         if (usage0 == null) {
             return 0;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterable.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014, 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.graph;
+
+import static com.oracle.graal.graph.Graph.*;
+
+import com.oracle.graal.graph.iterators.*;
+
+class NodeUsageIterable implements NodeIterable<Node> {
+
+    final Node node;
+
+    NodeUsageIterable(Node node) {
+        this.node = node;
+    }
+
+    public NodeUsageIterator iterator() {
+        if (MODIFICATION_COUNTS_ENABLED) {
+            return new NodeUsageWithModCountIterator(node);
+        } else {
+            return new NodeUsageIterator(node);
+        }
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return node.usage0 == null;
+    }
+
+    @Override
+    public boolean isNotEmpty() {
+        return node.usage0 != null;
+    }
+
+    @Override
+    public int count() {
+        return node.usageCount();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageIterator.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, 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.graph;
+
+import java.util.*;
+
+class NodeUsageIterator implements Iterator<Node> {
+
+    final Node node;
+    int index = -1;
+    Node current;
+
+    void advance() {
+        current = null;
+        index++;
+        if (index == 0) {
+            current = node.usage0;
+        } else if (index == 1) {
+            current = node.usage1;
+        } else {
+            if (index - Node.INLINE_USAGE_COUNT < node.extraUsages.length) {
+                current = node.extraUsages[index - Node.INLINE_USAGE_COUNT];
+            }
+        }
+    }
+
+    public NodeUsageIterator(Node node) {
+        this.node = node;
+        advance();
+    }
+
+    public boolean hasNext() {
+        return current != null;
+    }
+
+    public Node next() {
+        Node result = current;
+        if (result == null) {
+            throw new NoSuchElementException();
+        }
+        advance();
+        return result;
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsageWithModCountIterator.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, 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.graph;
+
+import java.util.*;
+
+class NodeUsageWithModCountIterator extends NodeUsageIterator {
+
+    public NodeUsageWithModCountIterator(Node n) {
+        super(n);
+    }
+
+    private final int expectedModCount = node.usageModCount();
+
+    @Override
+    public boolean hasNext() {
+        if (expectedModCount != node.usageModCount()) {
+            throw new ConcurrentModificationException();
+        }
+        return super.hasNext();
+    }
+
+    @Override
+    public Node next() {
+        if (expectedModCount != node.usageModCount()) {
+            throw new ConcurrentModificationException();
+        }
+        return super.next();
+    }
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Tue Aug 26 09:35:08 2014 -0700
@@ -26,11 +26,10 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.compiler.common.UnsafeAccess.*;
 
 import java.util.*;
 
-import sun.misc.*;
-
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
@@ -61,8 +60,6 @@
  */
 public class SPARCHotSpotBackend extends HotSpotHostBackend {
 
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-
     public SPARCHotSpotBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
         super(runtime, providers);
     }
@@ -139,12 +136,18 @@
         @Override
         public void enter(CompilationResultBuilder crb) {
             final int frameSize = crb.frameMap.totalFrameSize();
-
+            final int stackpoinerChange = -frameSize;
             SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
             if (!isStub && pagesToBang > 0) {
                 emitStackOverflowCheck(crb, pagesToBang, false);
             }
-            new Save(sp, -frameSize, sp).emit(masm);
+
+            if (SPARCAssembler.isSimm13(stackpoinerChange)) {
+                new Save(sp, stackpoinerChange, sp).emit(masm);
+            } else {
+                new Setx(stackpoinerChange, g3).emit(masm);
+                new Save(sp, g3, sp).emit(masm);
+            }
 
             if (ZapStackOnMethodEntry.getValue()) {
                 final int slotSize = 8;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -29,12 +29,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
-import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Jmpl;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw;
-import com.oracle.graal.asm.sparc.SPARCAssembler.Movcc;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp;
+import com.oracle.graal.asm.sparc.SPARCAssembler.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -74,5 +70,6 @@
         new Movcc(ConditionFlag.NotZero, CC.Icc, l7, sp).emit(masm);
 
         new Jmpl(asRegister(handlerInCallerPc), 0, g0).emit(masm);
+        new Nop().emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Aug 26 09:35:08 2014 -0700
@@ -206,12 +206,15 @@
     }
 
     public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        Variable newValueTemp = newVariable(newValue.getLIRKind());
+        emitMove(newValueTemp, newValue);
+
         LIRKind kind = newValue.getLIRKind();
         assert kind.equals(expectedValue.getLIRKind());
         Kind memKind = (Kind) kind.getPlatformKind();
         SPARCAddressValue addressValue = asAddressValue(address);
-        append(new CompareAndSwapOp(asAllocatable(addressValue), asAllocatable(expectedValue), asAllocatable(newValue)));
-        return emitConditionalMove(memKind, expectedValue, newValue, Condition.EQ, true, trueValue, falseValue);
+        append(new CompareAndSwapOp(asAllocatable(addressValue), asAllocatable(expectedValue), asAllocatable(newValueTemp)));
+        return emitConditionalMove(memKind, expectedValue, newValueTemp, Condition.EQ, true, trueValue, falseValue);
     }
 
     public StackSlot getDeoptimizationRescueSlot() {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveCurrentStackFrameOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -36,6 +36,9 @@
 @Opcode("LEAVE_CURRENT_STACK_FRAME")
 final class SPARCHotSpotLeaveCurrentStackFrameOp extends SPARCLIRInstruction {
 
+    public SPARCHotSpotLeaveCurrentStackFrameOp() {
+    }
+
     @Override
     public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
         // Save O registers over restore.
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -63,5 +63,7 @@
         new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm);
         new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm);
         new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm);
+
+        new Movdtox(f31, i0).emit(masm);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Tue Aug 26 09:35:08 2014 -0700
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
@@ -85,8 +86,14 @@
     private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
 
     private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
-
-    private final Register[] callerSaveRegisters = {g1, g3, g4, g5, o0, o1, o2, o3, o4, o5, o7};
+    // @formatter:off
+    private final Register[] callerSaveRegisters =
+                   {g1, g3, g4, g5, o0, o1, o2, o3, o4, o5, o7,
+                    f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
+                    f8,  f9,  f10, f11, f12, f13, f14, f15,
+                    f16, f17, f18, f19, f20, f21, f22, f23,
+                    f24, f25, f26, f27, f28, f29, f30, f31};
+    // @formatter:on
 
     /**
      * Registers saved by the callee. This lists all L and I registers which are saved in the
@@ -238,10 +245,7 @@
             if (locations[i] == null) {
                 // Stack slot is always aligned to its size in bytes but minimum wordsize
                 int typeSize = SPARC.spillSlotSize(target, kind);
-                int modulus = currentStackOffset % typeSize;
-                if (modulus != 0) {
-                    currentStackOffset += typeSize - modulus;
-                }
+                currentStackOffset = NumUtil.roundUp(currentStackOffset, typeSize);
                 locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), currentStackOffset, !type.out);
                 currentStackOffset += typeSize;
             }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotUnwindOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -28,6 +28,7 @@
 import static com.oracle.graal.sparc.SPARC.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov;
 import com.oracle.graal.hotspot.stubs.*;
@@ -61,7 +62,7 @@
 
         // Get return address (is in o7 after leave).
         Register returnAddress = asRegister(cc.getArgument(1));
-        new Mov(o7, returnAddress).emit(masm);
+        new Add(o7, Return.PC_RETURN_OFFSET, returnAddress).emit(masm);
         Register scratch = g5;
         SPARCCall.indirectJmp(crb, masm, scratch, linkage);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java	Tue Aug 26 09:35:08 2014 -0700
@@ -223,25 +223,48 @@
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask();
 
+        Unsigned vectorSize = Word.unsigned(VECTOR_SIZE);
         Unsigned srcOffset = Word.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize);
         Unsigned destOffset = Word.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize);
         Unsigned destStart = destOffset;
-        Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize);
         Unsigned destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize));
 
-        Unsigned nonVectorBytes = sizeInBytes.unsignedRemainder(Word.unsigned(VECTOR_SIZE));
+        Unsigned destVectorEnd = null;
+        Unsigned nonVectorBytes = null;
+        Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize);
+        if (supportsUnalignedMemoryAccess) {
+            nonVectorBytes = sizeInBytes.unsignedRemainder(vectorSize);
+            destVectorEnd = destEnd;
+        } else {
+            boolean inPhase = srcOffset.and((int) VECTOR_SIZE - 1).equal(destOffset.and((int) VECTOR_SIZE - 1));
+            boolean hasAtLeastOneVector = sizeInBytes.aboveOrEqual(vectorSize);
+            // We must have at least one full vector, otherwise we must copy each byte separately
+            if (hasAtLeastOneVector && inPhase) { // If in phase, we can vectorize
+                nonVectorBytes = vectorSize.subtract(destStart.unsignedRemainder(vectorSize));
+            } else { // fallback is byte-wise
+                nonVectorBytes = sizeInBytes;
+            }
+            destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(vectorSize));
+        }
+
         Unsigned destNonVectorEnd = destStart.add(nonVectorBytes);
-
         while (destOffset.belowThan(destNonVectorEnd)) {
             ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, ANY_LOCATION), ANY_LOCATION);
             destOffset = destOffset.add(1);
             srcOffset = srcOffset.add(1);
         }
-        while (destOffset.belowThan(destEnd)) {
+        // Unsigned destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(8));
+        while (destOffset.belowThan(destVectorEnd)) {
             ObjectAccess.writeWord(dest, destOffset, ObjectAccess.readWord(src, srcOffset, ANY_LOCATION), ANY_LOCATION);
             destOffset = destOffset.add(wordSize());
             srcOffset = srcOffset.add(wordSize());
         }
+        // Do the last bytes each when it is required to have absolute alignment.
+        while (!supportsUnalignedMemoryAccess && destOffset.belowThan(destEnd)) {
+            ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, ANY_LOCATION), ANY_LOCATION);
+            destOffset = destOffset.add(1);
+            srcOffset = srcOffset.add(1);
+        }
     }
 
     public static class Templates extends AbstractTemplates {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ddiv.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_ddiv.java	Tue Aug 26 09:35:08 2014 -0700
@@ -39,4 +39,8 @@
         runTest("test", 311.0D, 10D);
     }
 
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 311.0D, 0D);
+    }
 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fdiv.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_fdiv.java	Tue Aug 26 09:35:08 2014 -0700
@@ -39,4 +39,8 @@
         runTest("test", 311.0f, 10f);
     }
 
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 311.0f, 0f);
+    }
 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java	Tue Aug 26 09:35:08 2014 -0700
@@ -103,4 +103,60 @@
     public void run10() {
         runTest("test4", 0xffffffff);
     }
+
+    @Test
+    public void run11() {
+        runTest("test2", 0xFFFFFFFF);
+    }
+
+    @Test
+    public void run12() {
+        runTest("test2", 0x7FFFFFFF);
+    }
+
+    @Test
+    public void run17() {
+        runTest("test2", 0x80000000);
+    }
+
+    @Test
+    public void run18() {
+        runTest("test2", 0x40000000);
+    }
+
+    @Test
+    public void run13() {
+        runTest("test3", 0x7FFFFFFF);
+    }
+
+    @Test
+    public void run14() {
+        runTest("test3", 0xFFFFFFFF);
+    }
+
+    @Test
+    public void run15() {
+        runTest("test3", 0x80000000);
+    }
+
+    @Test
+    public void run16() {
+        runTest("test3", 0x40000000);
+    }
+
+    @Test
+    public void run19() {
+        runTest("test4", 0x80000000);
+    }
+
+    @Test
+    public void run20() {
+        runTest("test4", 0x40000000);
+    }
+
+    @Test
+    public void run21() {
+        runTest("test4", 0x00000001);
+    }
+
 }
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/micro/BigMixedParams04.java	Tue Aug 26 09:35:08 2014 -0700
@@ -53,6 +53,212 @@
         return 42;
     }
 
+    /**
+     * Test SPARC mixed params with double/single float register overlapping
+     *
+     * @param f1
+     * @param d2
+     * @param f3
+     * @return Must always return the argument d2
+     */
+    @SuppressWarnings("all")
+    public static double test2(int i1, float f1, double d2, float f3,
+    // @formatter:off
+                    double ad1 ,
+                    double ad2 ,
+                    double ad3 ,
+                    double ad4 ,
+                    double ad5 ,
+                    double ad6 ,
+                    double ad7 ,
+                    double ad8 ,
+                    double ad9 ,
+                    double ad10,
+                    double ad11,
+                    double ad12,
+                    double ad13,
+                    double ad14,
+                    double ad15,
+                    double ad16,
+                    float  af1 ,
+                    float  af2 ,
+                    float  af3 ,
+                    float  af4 ,
+                    float  af5 ,
+                    float  af6 ,
+                    float  af7 ,
+                    float  af8 ,
+                    float  af9 ,
+                    float  af10,
+                    float  af11,
+                    float  af12,
+                    float  af13,
+                    float  af14,
+                    float  af15,
+                    float  af16
+    // @formatter:on
+    ) {
+
+        // now do something with the locals to make sure the locals don't get optimized away.
+        for (int i = 0; i < i1; i++) {
+            af1 += f1;
+            af2 += f1;
+            af3 += f1;
+            af4 += f1;
+            af5 += f1;
+            af6 += f1;
+            af7 += f1;
+            af8 += f1;
+            af9 += f1;
+            af10 += f1;
+            af11 += f1;
+            af12 += f1;
+            af13 += f1;
+            af14 += f1;
+            af15 += f1;
+            af16 += f1;
+            ad1 += f1;
+            ad2 += f1;
+            ad3 += f1;
+            ad4 += f1;
+            ad5 += f1;
+            ad6 += f1;
+            ad7 += f1;
+            ad8 += f1;
+            ad9 += f1;
+            ad10 += f1;
+            ad11 += f1;
+            ad12 += f1;
+            ad13 += f1;
+            ad14 += f1;
+            ad15 += f1;
+            ad16 += f1;
+        }
+        // @formatter:off
+        boolean orderFloat =
+                        af1  < af2  &&
+                        af2  < af3  &&
+                        af3  < af4  &&
+                        af4  < af5  &&
+                        af5  < af6  &&
+                        af6  < af7  &&
+                        af7  < af8  &&
+                        af8  < af9  &&
+                        af9  < af10 &&
+                        af10 < af11 &&
+                        af11 < af12 &&
+                        af12 < af13 &&
+                        af13 < af14 &&
+                        af14 < af15 &&
+                        af15 < af16;
+        boolean orderDouble =
+                        ad1  < ad2  &&
+                        ad2  < ad3  &&
+                        ad3  < ad4  &&
+                        ad4  < ad5  &&
+                        ad5  < ad6  &&
+                        ad6  < ad7  &&
+                        ad7  < ad8  &&
+                        ad8  < ad9  &&
+                        ad9  < ad10 &&
+                        ad10 < ad11 &&
+                        ad11 < ad12 &&
+                        ad12 < ad13 &&
+                        ad13 < ad14 &&
+                        ad14 < ad15 &&
+                        ad15 < ad16;
+        // @formatter:on
+        if (orderDouble && orderFloat) {
+            return f1 + d2 + f3; // this should not be destroyed
+        }
+        Assert.fail();
+        return 0.0;
+    }
+
+    /**
+     * Test SPARC mixed params with double/single float register overlapping
+     *
+     * @param f1
+     * @param d2
+     * @param f3
+     * @return Must always return the argument d2
+     */
+    @SuppressWarnings("all")
+    public static double test3(boolean f, int idx,
+    // @formatter:off
+                    double ad1 ,
+                    double ad2 ,
+                    double ad3 ,
+                    double ad4 ,
+                    double ad5 ,
+                    double ad6 ,
+                    double ad7 ,
+                    double ad8 ,
+                    double ad9 ,
+                    double ad10,
+                    double ad11,
+                    double ad12,
+                    double ad13,
+                    double ad14,
+                    double ad15,
+                    double ad16,
+                    float  af1 ,
+                    float  af2 ,
+                    float  af3 ,
+                    float  af4 ,
+                    float  af5 ,
+                    float  af6 ,
+                    float  af7 ,
+                    float  af8 ,
+                    float  af9 ,
+                    float  af10,
+                    float  af11,
+                    float  af12,
+                    float  af13,
+                    float  af14,
+                    float  af15,
+                    float  af16
+    ) {
+        switch(f ? idx + 16 : idx) {
+            case 1 : return ad1 ;
+            case 2 : return ad2 ;
+            case 3 : return ad3 ;
+            case 4 : return ad4 ;
+            case 5 : return ad5 ;
+            case 6 : return ad6 ;
+            case 7 : return ad7 ;
+            case 8 : return ad8 ;
+            case 9 : return ad9 ;
+            case 10: return ad10;
+            case 11: return ad11;
+            case 12: return ad12;
+            case 13: return ad13;
+            case 14: return ad14;
+            case 15: return ad15;
+            case 16: return ad16;
+            case 1  + 16: return af1 ;
+            case 2  + 16: return af2 ;
+            case 3  + 16: return af3 ;
+            case 4  + 16: return af4 ;
+            case 5  + 16: return af5 ;
+            case 6  + 16: return af6 ;
+            case 7  + 16: return af7 ;
+            case 8  + 16: return af8 ;
+            case 9  + 16: return af9 ;
+            case 10 + 16: return af10;
+            case 11 + 16: return af11;
+            case 12 + 16: return af12;
+            case 13 + 16: return af13;
+            case 14 + 16: return af14;
+            case 15 + 16: return af15;
+            case 16 + 16: return af16;
+        }
+        Assert.fail(); // should not reach here
+        return 0;
+
+    }
+    // @formatter:on
+
     @Test
     public void run0() throws Throwable {
         runTest("test", 0, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
@@ -82,4 +288,86 @@
     public void run5() throws Throwable {
         runTest("test", 5, -1, -1, -1, -1, 1d, 2d, true, false, (byte) -128, (short) -0x7FFF, (char) 0xFFFF, -0x7FFFFFF);
     }
+
+    @Test
+    public void run6() throws Throwable {
+        // @formatter:off
+        runTest("test2", 20, 1.0f, -3.2912948246387967943231233d, 3.0f,
+                        1d,
+                        2d,
+                        3d,
+                        4d,
+                        5d,
+                        6d,
+                        7d,
+                        8d,
+                        9d,
+                        10d,
+                        11d,
+                        12d,
+                        13d,
+                        14d,
+                        15d,
+                        16d,
+                        1f,
+                        2f,
+                        3f,
+                        4f,
+                        5f,
+                        6f,
+                        7f,
+                        8f,
+                        9f,
+                        10f,
+                        11f,
+                        12f,
+                        13f,
+                        14f,
+                        15f,
+                        16f
+                        );
+        // @formatter:on
+    }
+
+    @Test
+    public void run7() throws Throwable {
+        // @formatter:off
+        for(int i =0; i<32*2; i++)
+        runTest("test3", i%2==0, i/2,
+                        1d,
+                        2d,
+                        3d,
+                        4d,
+                        5d,
+                        6d,
+                        7d,
+                        8d,
+                        9d,
+                        10d,
+                        11d,
+                        12d,
+                        13d,
+                        14d,
+                        15d,
+                        16d,
+                        1f,
+                        2f,
+                        3f,
+                        4f,
+                        5f,
+                        6f,
+                        7f,
+                        8f,
+                        9f,
+                        10f,
+                        11f,
+                        12f,
+                        13f,
+                        14f,
+                        15f,
+                        16f
+                        );
+        // @formatter:on
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/SignExtendShort.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,65 @@
+/*
+ * 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.jtt.optimize;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+/*
+ */
+public class SignExtendShort extends JTTTest {
+
+    public static int val;
+
+    public static boolean test(short[] b) {
+        val = b[2];
+        int x = 0;
+        return val >= x;
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", new short[]{0, 0, 0});
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", new short[]{0, 0, 1});
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", new short[]{0, 0, -1});
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        runTest("test", new short[]{0, 0, Short.MAX_VALUE});
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        runTest("test", new short[]{0, 0, Short.MIN_VALUE});
+    }
+}
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Switch02.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/Switch02.java	Tue Aug 26 09:35:08 2014 -0700
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.jtt.optimize;
 
+import java.util.*;
+
 import org.junit.*;
 
 import com.oracle.graal.jtt.*;
@@ -30,6 +32,9 @@
  * Tests optimization of switches.
  */
 public class Switch02 extends JTTTest {
+    private static char staticCharVal = 0;
+    private static short staticShortVal = 0;
+    private static byte staticByteVal = 0;
 
     public static int test(int arg) {
         switch (arg) {
@@ -40,6 +45,168 @@
         }
     }
 
+    public static int test2char(char arg) {
+        int result = 392123;
+        Object x = null;
+        char val = staticCharVal != 0 ? staticCharVal : arg;
+        switch (val) {
+            case (char) 0xFFFF:
+                result = 23212 / val;
+                break;
+            case (char) 0xFFFF - 3:
+                result = 932991439 / val;
+                break;
+            case (char) 0xFFFF - 6:
+                result = 47329561 / val;
+                break;
+            case (char) 0xFFFF - 9:
+                result = 1950976984 / val;
+                break;
+            case (char) 0xFFFF - 10:
+                result = 97105581 / val;
+                switch (result) {
+                    case 1:
+                        result = 321;
+                        break;
+                    default:
+                        result = 2391;
+                        break;
+                }
+                break;
+            case (char) 0xFFFF - 12:
+                result = 99757362 / val;
+                break;
+            case (char) 0xFFFF - 15:
+                result = 912573 / val;
+                x = new LinkedList<>();
+                break;
+            case (char) 0xFFFF - 18:
+                x = new HashSet<>();
+                result = 876765 / val;
+                break;
+            case (char) 0xFFFF - 19:
+                result = 75442917 / val;
+                break;
+            case (char) 0xFFFF - 21:
+                result = 858112498 / val;
+                x = new Hashtable<>();
+                break;
+            default:
+                result = 34324341 / val;
+        }
+        result = result + (x == null ? 0 : x.hashCode());
+        return result;
+    }
+
+    public static int test2short(short arg) {
+        int result = 392123;
+        Object x = null;
+        short val = staticShortVal != 0 ? staticShortVal : arg;
+        switch (val) {
+            case (short) -0x7FFF:
+                result = 23212 / val;
+                break;
+            case (short) -0x7FFF + 3:
+                result = 932991439 / val;
+                break;
+            case (short) -0x7FFF + 6:
+                result = 47329561 / val;
+                break;
+            case (short) -0x7FFF + 9:
+                result = 1950976984 / val;
+                break;
+            case (short) -0x7FFF + 10:
+                result = 97105581 / val;
+                switch (result) {
+                    case 1:
+                        result = 321;
+                        break;
+                    default:
+                        result = 2391;
+                        break;
+                }
+                break;
+            case (short) -0x7FFF + 12:
+                result = 99757362 / val;
+                break;
+            case (short) -0x7FFF + 15:
+                result = 912573 / val;
+                x = new LinkedList<>();
+                break;
+            case (short) -0x7FFF + 18:
+                x = new HashSet<>();
+                result = 876765 / val;
+                break;
+            case (short) -0x7FFF + 19:
+                result = 75442917 / val;
+                break;
+            case (short) -0x7FFF + 21:
+                result = 858112498 / val;
+                x = new Hashtable<>();
+                break;
+            default:
+                result = 34324341 / val;
+        }
+        result = result + (x == null ? 0 : x.hashCode());
+        return result;
+    }
+
+    public static int test2byte(byte arg) {
+        int result = 392123;
+        Object x = null;
+        byte val = staticByteVal != 0 ? staticByteVal : arg;
+        switch (val) {
+            case (byte) -0x7F:
+                result = 23212 / val;
+                break;
+            case (byte) -0x7F + 3:
+                result = 932991439 / val;
+                break;
+            case (byte) -0x7F + 6:
+                result = 47329561 / val;
+                break;
+            case (byte) -0x7F + 9:
+                result = 1950976984 / val;
+                break;
+            case (byte) -0x7F + 10:
+                result = 97105581 / val;
+                switch (result) {
+                    case 1:
+                        result = 321;
+                        break;
+                    default:
+                        result = 2391;
+                        break;
+                }
+                break;
+            case (byte) -0x7F + 12:
+                result = 99757362 / val;
+                break;
+            case (byte) -0x7F + 15:
+                result = 912573 / val;
+                x = new LinkedList<>();
+                break;
+            case (byte) -0x7F + 18:
+                x = new HashSet<>();
+                result = 876765 / val;
+                break;
+            case (byte) -0x7F + 19:
+                result = 75442917 / val;
+                break;
+            case (byte) -0x7F + 20:
+                result = 856261268 / val;
+                break;
+            case (byte) -0x7F + 21:
+                result = 858112498 / val;
+                x = new Hashtable<>();
+                break;
+            default:
+                result = 34324341 / val;
+        }
+        result = result + (x == null ? 0 : x.hashCode());
+        return result;
+    }
+
     @Test
     public void run0() throws Throwable {
         runTest("test", 0);
@@ -50,4 +217,63 @@
         runTest("test", 1);
     }
 
+    @Test
+    public void run2() throws Throwable {
+        runTest("test2char", (char) (0x0));
+        runTest("test2char", (char) (0xFFFF));
+        runTest("test2char", (char) (0xFFFF - 21)); // miss
+        runTest("test2char", (char) (0xFFFF - 22)); // hit
+        runTest("test2char", (char) (0xFFFF - 23)); // miss (out of bound)
+
+        staticCharVal = (char) 0xFFFF;
+        runTest("test2char", (char) 0);
+        staticCharVal = (char) (0xFFFF - 21);
+        runTest("test2char", (char) 0xFFFF);
+        staticCharVal = (char) (0xFFFF - 22);
+        runTest("test2char", (char) 0xFFFF);
+        staticCharVal = (char) (0xFFFF - 23);
+        runTest("test2char", (char) 0xFFFF);
+    }
+
+    @Test
+    public void run3() throws Throwable {
+        runTest("test2short", (short) 0x0);
+        runTest("test2short", (short) -0x7FFF);
+        runTest("test2short", (short) (-0x7FFF + 21)); // Miss
+        runTest("test2short", (short) (-0x7FFF + 22)); // hit
+        runTest("test2short", (short) (-0x7FFF + 23)); // miss (out of bound)
+        runTest("test2short", (short) 0x7FFF);         // miss (out of bound)
+
+        staticShortVal = (short) -0x7FFF;
+        runTest("test2short", (short) 0);
+        staticShortVal = (short) (-0x7FFF + 21);
+        runTest("test2short", (short) 0);
+        staticShortVal = (short) (-0x7FFF + 22);
+        runTest("test2short", (short) 0);
+        staticShortVal = (short) (-0x7FFF + 23);
+        runTest("test2short", (short) 0);
+        staticShortVal = (short) 0x7FFF;
+        runTest("test2short", (short) 0);
+    }
+
+    @Test
+    public void run4() throws Throwable {
+        runTest("test2byte", (byte) 0);
+        runTest("test2byte", (byte) -0x7F);
+        runTest("test2byte", (byte) (-0x7F + 21)); // Miss
+        runTest("test2byte", (byte) (-0x7F + 22)); // hit
+        runTest("test2byte", (byte) (-0x7F + 23)); // miss (out of bound)
+        runTest("test2byte", (byte) 0x7F);         // miss (out of bound)
+
+        staticByteVal = (byte) -0x7F;
+        runTest("test2short", (short) 0);
+        staticByteVal = (byte) (-0x7F + 21);
+        runTest("test2short", (short) 0);
+        staticByteVal = (byte) (-0x7F + 22);
+        runTest("test2short", (short) 0);
+        staticByteVal = (byte) (-0x7F + 23);
+        runTest("test2short", (short) 0);
+        staticByteVal = (byte) 0x7F;
+        runTest("test2short", (short) 0);
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Tue Aug 26 09:35:08 2014 -0700
@@ -27,6 +27,7 @@
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.compiler.common.*;
@@ -37,8 +38,8 @@
 
 public enum SPARCArithmetic {
     // @formatter:off
-    IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
-    LADD, LSUB, LMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
+    IADD, ISUB, IMUL, IUMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
+    LADD, LSUB, LMUL, LUMUL, LDIV, LREM, LUDIV, LUREM, LAND, LOR, LXOR, LSHL, LSHR, LUSHR,
     FADD, FSUB, FMUL, FDIV, FREM, FAND, FOR, FXOR,
     DADD, DSUB, DMUL, DDIV, DREM, DAND, DOR, DXOR,
     INEG, LNEG, FNEG, DNEG, INOT, LNOT,
@@ -161,6 +162,10 @@
         @State protected LIRFrameState state;
         protected Constant y;
 
+        public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) {
+            this(opcode, result, x, y, null);
+        }
+
         public BinaryRegConst(SPARCArithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y, LIRFrameState state) {
             this.opcode = opcode;
             this.result = result;
@@ -248,7 +253,7 @@
 
         @Opcode private final SPARCArithmetic opcode;
         @Def({REG}) protected Value result;
-        @Use({REG, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value x;
         @Alive({REG, CONST}) protected Value y;
         @Temp({REG}) protected Value scratch1;
         @Temp({REG}) protected Value scratch2;
@@ -282,9 +287,16 @@
             switch (opcode) {
                 case ISUB:
                     assert isSimm13(crb.asIntConst(src1));
-                    new Sub(SPARC.g0, asIntReg(src2), asIntReg(src2)).emit(masm);
-                    new Add(asIntReg(src2), crb.asIntConst(src1), asIntReg(dst)).emit(masm);
+                    new Sub(SPARC.g0, asIntReg(src2), asIntReg(dst)).emit(masm);
+                    new Add(asIntReg(dst), crb.asIntConst(src1), asIntReg(dst)).emit(masm);
                     break;
+                case LSUB: {
+                    long c = crb.asLongConst(src1);
+                    assert isSimm13(c);
+                    new Sub(SPARC.g0, asLongReg(src2), asLongReg(dst)).emit(masm);
+                    new Add(asLongReg(dst), (int) c, asLongReg(dst)).emit(masm);
+                    break;
+                }
                 case IAND:
                     throw GraalInternalError.unimplemented();
                 case IDIV:
@@ -292,13 +304,14 @@
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(dst), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
-                case LDIV:
+                case LDIV: {
                     int c = crb.asIntConst(src1);
                     assert isSimm13(c);
                     exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src2), c, asLongReg(dst)).emit(masm);
                     new Mulx(asLongReg(src1), asLongReg(dst), asLongReg(dst)).emit(masm);
                     break;
+                }
                 case FSUB:
                 case FDIV:
                 case DSUB:
@@ -410,6 +423,7 @@
                     break;
                 case DAND:
                     SPARCAddress addr = (SPARCAddress) crb.recordDataReferenceInCode(asConstant(src2), 4);
+                    addr = SPARCMove.guaranueeLoadable(addr, masm);
                     new Lddf(addr, asDoubleReg(dst)).emit(masm);
                     new Fandd(asDoubleReg(src1), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     break;
@@ -440,7 +454,6 @@
                     new Sdivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
                 case IUDIV:
-                    new Srl(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
                     exceptionOffset = masm.position();
                     new Udivx(asIntReg(src1), asIntReg(src2), asIntReg(dst)).emit(masm);
                     break;
@@ -506,7 +519,11 @@
                     new Fsubs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
                     break;
                 case FMUL:
-                    new Fmuls(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
+                    if (dst.getPlatformKind() == Kind.Double) {
+                        new Fsmuld(asFloatReg(src1), asFloatReg(src2), asDoubleReg(dst)).emit(masm);
+                    } else if (dst.getPlatformKind() == Kind.Float) {
+                        new Fmuls(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
+                    }
                     break;
                 case FDIV:
                     new Fdivs(asFloatReg(src1), asFloatReg(src2), asFloatReg(dst)).emit(masm);
@@ -569,22 +586,25 @@
         } else if (isConstant(src2)) {
             switch (opcode) {
                 case IREM:
+                    assert !src1.equals(scratch1);
+                    assert !src1.equals(scratch2);
+                    assert !src2.equals(scratch1);
+                    // But src2 can be scratch2
                     assert isSimm13(crb.asIntConst(src2));
-                    new Sra(asIntReg(src1), 0, asIntReg(src1)).emit(masm);
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(src1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
                     new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch2)).emit(masm);
                     new Sub(asIntReg(src1), asIntReg(scratch2), asIntReg(dst)).emit(masm);
                     break;
                 case IUREM:
-                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
-                    exceptionOffset = masm.position();
-                    new Udivx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
-                    new Mulx(asIntReg(scratch1), crb.asIntConst(src2), asIntReg(scratch1)).emit(masm);
-                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    GraalInternalError.unimplemented();
                     break;
                 case LREM:
                     assert isSimm13(crb.asIntConst(src2));
+                    assert !src1.equals(scratch1);
+                    assert !src1.equals(scratch2);
+                    assert !src2.equals(scratch1);
+                    // But src2 can be scratch2
                     exceptionOffset = masm.position();
                     new Sdivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm);
                     new Mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)).emit(masm);
@@ -592,6 +612,10 @@
                     break;
                 case LUREM:
                     assert isSimm13(crb.asIntConst(src2));
+                    assert !src1.equals(scratch1);
+                    assert !src1.equals(scratch2);
+                    assert !src2.equals(scratch1);
+                    // But src2 can be scratch2
                     exceptionOffset = masm.position();
                     new Udivx(asLongReg(src1), crb.asIntConst(src2), asLongReg(scratch1)).emit(masm);
                     new Mulx(asLongReg(scratch1), crb.asIntConst(src2), asLongReg(scratch2)).emit(masm);
@@ -608,6 +632,9 @@
                         new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm);
                         srcLeft = scratch2;
                     }
+                    assert !asLongReg(srcLeft).equals(asLongReg(scratch1));
+                    assert !asLongReg(src2).equals(asLongReg(scratch1));
+                    // But src2 can be scratch2
                     exceptionOffset = masm.position();
                     new Sdivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm);
                     new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
@@ -618,6 +645,8 @@
                         new Setx(crb.asLongConst(src1), asLongReg(scratch2), false).emit(masm);
                         srcLeft = scratch2;
                     }
+                    assert !asLongReg(srcLeft).equals(asLongReg(scratch1));
+                    assert !asLongReg(src2).equals(asLongReg(scratch1));
                     exceptionOffset = masm.position();
                     new Udivx(asLongReg(srcLeft), asLongReg(src2), asLongReg(scratch1)).emit(masm);
                     new Mulx(asLongReg(scratch1), asLongReg(src2), asLongReg(scratch1)).emit(masm);
@@ -628,17 +657,22 @@
                         new Setx(crb.asIntConst(src1), asIntReg(scratch2), false).emit(masm);
                         srcLeft = scratch2;
                     }
+                    assert !asIntReg(srcLeft).equals(asIntReg(scratch1));
+                    assert !asIntReg(src2).equals(asIntReg(scratch1));
                     exceptionOffset = masm.position();
                     new Sdivx(asIntReg(srcLeft), asIntReg(src2), asIntReg(scratch1)).emit(masm);
                     new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
                     new Sub(asIntReg(srcLeft), asIntReg(scratch1), asIntReg(dst)).emit(masm);
                     break;
                 case IUREM:
-                    new Sra(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    assert !asIntReg(dst).equals(asIntReg(scratch1));
+                    assert !asIntReg(dst).equals(asIntReg(scratch2));
+                    new Srl(asIntReg(src1), 0, asIntReg(scratch1)).emit(masm);
+                    new Srl(asIntReg(src2), 0, asIntReg(dst)).emit(masm);
                     exceptionOffset = masm.position();
-                    new Udivx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    new Mulx(asIntReg(scratch1), asIntReg(src2), asIntReg(scratch1)).emit(masm);
-                    new Sub(asIntReg(src1), asIntReg(scratch1), asIntReg(dst)).emit(masm);
+                    new Udivx(asIntReg(scratch1), asIntReg(dst), asIntReg(scratch2)).emit(masm);
+                    new Mulx(asIntReg(scratch2), asIntReg(dst), asIntReg(dst)).emit(masm);
+                    new Sub(asIntReg(scratch1), asIntReg(dst), asIntReg(dst)).emit(masm);
                     break;
                 default:
                     throw GraalInternalError.shouldNotReachHere();
@@ -653,6 +687,7 @@
 
     public static void emit(CompilationResultBuilder crb, SPARCAssembler masm, SPARCArithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
+        Label notOrdered = new Label();
         if (isRegister(src)) {
             switch (opcode) {
                 case INEG:
@@ -716,18 +751,20 @@
                     new Fstod(asFloatReg(src), asDoubleReg(dst)).emit(masm);
                     break;
                 case F2L:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbe(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fstox(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case F2I:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(dst), asFloatReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmps, asFloatReg(src), asFloatReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fstoi(asFloatReg(src), asFloatReg(dst)).emit(masm);
                     new Fitos(asFloatReg(dst), asFloatReg(dst)).emit(masm);
                     new Fsubs(asFloatReg(dst), asFloatReg(dst), asFloatReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case MOV_D2L:
                     new Movdtox(asDoubleReg(src), asLongReg(dst)).emit(masm);
@@ -742,18 +779,20 @@
                     new Movwtos(asIntReg(src), asFloatReg(dst)).emit(masm);
                     break;
                 case D2L:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(src), asDoubleReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fdtox(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fxtod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case D2I:
-                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
-                    new Fbo(false, 4 * 4).emit(masm);
+                    new Fcmp(CC.Fcc0, Opfs.Fcmpd, asDoubleReg(src), asDoubleReg(src)).emit(masm);
+                    new Fbo(false, notOrdered).emit(masm);
                     new Fdtoi(asDoubleReg(src), asDoubleReg(dst)).emit(masm);
                     new Fitod(asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
                     new Fsubd(asDoubleReg(dst), asDoubleReg(dst), asDoubleReg(dst)).emit(masm);
+                    masm.bind(notOrdered);
                     break;
                 case FNEG:
                     new Fnegs(asFloatReg(src), asFloatReg(dst)).emit(masm);
@@ -803,10 +842,14 @@
             case IUSHR:
             case IUDIV:
             case IUREM:
-                rk = result.getKind();
+                rk = result.getKind().getStackKind();
                 xsk = x.getKind().getStackKind();
                 ysk = y.getKind().getStackKind();
-                assert rk == Kind.Int && xsk == Kind.Int && ysk == Kind.Int;
+                boolean valid = false;
+                for (Kind k : new Kind[]{Kind.Int, Kind.Short, Kind.Byte, Kind.Char}) {
+                    valid |= rk == k && xsk == k && ysk == k;
+                }
+                assert valid : "rk: " + rk + " xsk: " + xsk + " ysk: " + ysk;
                 break;
             case LADD:
             case LSUB:
@@ -839,7 +882,7 @@
                 rk = result.getKind();
                 xk = x.getKind();
                 yk = y.getKind();
-                assert rk == Kind.Float && xk == Kind.Float && yk == Kind.Float;
+                assert (rk == Kind.Float || rk == Kind.Double) && xk == Kind.Float && yk == Kind.Float;
                 break;
             case DAND:
             case DADD:
@@ -856,4 +899,56 @@
                 throw GraalInternalError.shouldNotReachHere("missing: " + opcode);
         }
     }
+
+    public static class MulHighOp extends SPARCLIRInstruction {
+
+        @Opcode private final SPARCArithmetic opcode;
+        @Def({REG}) public AllocatableValue result;
+        @Alive({REG}) public AllocatableValue x;
+        @Alive({REG}) public AllocatableValue y;
+        @Temp({REG}) public AllocatableValue scratch;
+
+        public MulHighOp(SPARCArithmetic opcode, AllocatableValue x, AllocatableValue y, AllocatableValue result, AllocatableValue scratch) {
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
+            this.scratch = scratch;
+            this.result = result;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            assert isRegister(x) && isRegister(y) && isRegister(result) && isRegister(scratch);
+            switch (opcode) {
+                case IMUL:
+                    new Mulx(asIntReg(x), asIntReg(y), asIntReg(result)).emit(masm);
+                    new Srax(asIntReg(result), 32, asIntReg(result)).emit(masm);
+                    break;
+                case IUMUL:
+                    assert !asIntReg(scratch).equals(asIntReg(result));
+                    new Srl(asIntReg(x), 0, asIntReg(scratch)).emit(masm);
+                    new Srl(asIntReg(y), 0, asIntReg(result)).emit(masm);
+                    new Mulx(asIntReg(result), asIntReg(scratch), asIntReg(result)).emit(masm);
+                    new Srlx(asIntReg(result), 32, asIntReg(result)).emit(masm);
+                    break;
+                case LMUL:
+                    assert !asLongReg(scratch).equals(asLongReg(result));
+                    new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+
+                    new Srlx(asLongReg(x), 63, asLongReg(scratch)).emit(masm);
+                    new Mulx(asLongReg(scratch), asLongReg(y), asLongReg(scratch)).emit(masm);
+                    new Sub(asLongReg(result), asLongReg(scratch), asLongReg(result)).emit(masm);
+
+                    new Srlx(asLongReg(y), 63, asLongReg(scratch)).emit(masm);
+                    new Mulx(asLongReg(scratch), asLongReg(x), asLongReg(scratch)).emit(masm);
+                    new Sub(asLongReg(result), asLongReg(scratch), asLongReg(result)).emit(masm);
+                    break;
+                case LUMUL:
+                    new Umulxhi(asLongReg(x), asLongReg(y), asLongReg(result)).emit(masm);
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCBitManipulationOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -96,9 +96,10 @@
                     Kind ikind = input.getKind();
                     assert ikind == Kind.Int;
                     Register tmp = asRegister(scratch);
+                    assert !tmp.equals(dst);
                     new Srl(src, 1, tmp).emit(masm);
                     new Srl(src, 0, dst).emit(masm);
-                    new Or(src, tmp, dst).emit(masm);
+                    new Or(dst, tmp, dst).emit(masm);
                     new Srl(dst, 2, tmp).emit(masm);
                     new Or(dst, tmp, dst).emit(masm);
                     new Srl(dst, 4, tmp).emit(masm);
@@ -115,6 +116,7 @@
                     Kind lkind = input.getKind();
                     assert lkind == Kind.Long;
                     Register tmp = asRegister(scratch);
+                    assert !tmp.equals(dst);
                     new Srlx(src, 1, tmp).emit(masm);
                     new Or(src, tmp, dst).emit(masm);
                     new Srlx(dst, 2, tmp).emit(masm);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Tue Aug 26 09:35:08 2014 -0700
@@ -25,12 +25,12 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 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.compiler.common.calc.*;
@@ -62,30 +62,44 @@
     }
 
     public static class BranchOp extends SPARCLIRInstruction implements StandardOp.BranchOp {
-
+        // TODO: Conditioncode/flag handling needs to be improved;
         protected final Condition condition;
+        protected final ConditionFlag conditionFlag;
         protected final LabelRef trueDestination;
         protected final LabelRef falseDestination;
         protected final Kind kind;
 
+        public BranchOp(ConditionFlag condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind) {
+            this.conditionFlag = condition;
+            this.trueDestination = trueDestination;
+            this.falseDestination = falseDestination;
+            this.kind = kind;
+            this.condition = null;
+        }
+
         public BranchOp(Condition condition, LabelRef trueDestination, LabelRef falseDestination, Kind kind) {
             this.condition = condition;
             this.trueDestination = trueDestination;
             this.falseDestination = falseDestination;
             this.kind = kind;
+            this.conditionFlag = null;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            assert condition == null && conditionFlag != null || condition != null && conditionFlag == null;
             Label actualTarget;
             Condition actualCondition;
+            ConditionFlag actualConditionFlag;
             boolean needJump;
             if (crb.isSuccessorEdge(trueDestination)) {
-                actualCondition = condition.negate();
+                actualCondition = condition != null ? condition.negate() : null;
+                actualConditionFlag = conditionFlag != null ? conditionFlag.negate() : null;
                 actualTarget = falseDestination.label();
                 needJump = false;
             } else {
                 actualCondition = condition;
+                actualConditionFlag = conditionFlag;
                 actualTarget = trueDestination.label();
                 needJump = !crb.isSuccessorEdge(falseDestination);
             }
@@ -94,7 +108,13 @@
                 emitFloatCompare(masm, actualTarget, actualCondition);
             } else {
                 CC cc = kind == Kind.Int ? CC.Icc : CC.Xcc;
-                emitCompare(masm, actualTarget, actualCondition, cc);
+                if (actualCondition != null) {
+                    emitCompare(masm, actualTarget, actualCondition, cc);
+                } else if (actualConditionFlag != null) {
+                    emitCompare(masm, actualTarget, actualConditionFlag);
+                } else {
+                    GraalInternalError.shouldNotReachHere();
+                }
                 new Nop().emit(masm);  // delay slot
             }
             if (needJump) {
@@ -104,7 +124,7 @@
     }
 
     private static void emitFloatCompare(SPARCMacroAssembler masm, Label target, Condition actualCondition) {
-        switch (actualCondition.mirror()) {
+        switch (actualCondition) {
             case EQ:
                 new Fbe(false, target).emit(masm);
                 break;
@@ -134,6 +154,10 @@
         new Nop().emit(masm);
     }
 
+    private static void emitCompare(SPARCMacroAssembler masm, Label target, ConditionFlag actualCondition) {
+        new Fmt00b(false, actualCondition, Op2s.Br, target).emit(masm);
+    }
+
     private static void emitCompare(SPARCMacroAssembler masm, Label target, Condition actualCondition, CC cc) {
         switch (actualCondition) {
             case EQ:
@@ -176,7 +200,7 @@
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         @Alive({REG}) protected Value key;
-        @Temp({REG, ILLEGAL}) protected Value scratch;
+        @Temp({REG}) protected Value scratch;
         private final SwitchStrategy strategy;
 
         public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
@@ -188,7 +212,6 @@
             this.scratch = scratch;
             assert keyConstants.length == keyTargets.length;
             assert keyConstants.length == strategy.keyProbabilities.length;
-            assert (scratch.getKind() == Kind.Illegal) == (key.getKind() == Kind.Int);
         }
 
         @Override
@@ -204,8 +227,13 @@
                                 crb.recordInlineDataInCode(keyConstants[index]);
                             }
                             long lc = keyConstants[index].asLong();
-                            assert NumUtil.isInt(lc);
-                            new Cmp(keyRegister, (int) lc).emit(masm);
+                            if (SPARCAssembler.isSimm13(lc)) {
+                                assert NumUtil.isInt(lc);
+                                new Cmp(keyRegister, (int) lc).emit(masm);
+                            } else {
+                                new Setx(lc, asIntReg(scratch)).emit(masm);
+                                new Cmp(keyRegister, asIntReg(scratch)).emit(masm);
+                            }
                             emitCompare(masm, target, condition, CC.Icc);
                             break;
                         case Long: {
@@ -253,12 +281,20 @@
 
             // Compare index against jump table bounds
             int highKey = lowKey + targets.length - 1;
-            if (lowKey != 0) {
-                // subtract the low value from the switch value
-                new Sub(value, lowKey, value).emit(masm);
-                new Cmp(value, highKey - lowKey).emit(masm);
+
+            // subtract the low value from the switch value
+            if (isSimm13(lowKey)) {
+                new Sub(value, lowKey, scratchReg).emit(masm);
             } else {
-                new Cmp(value, highKey).emit(masm);
+                new Setx(lowKey, g3).emit(masm);
+                new Sub(value, g3, scratchReg).emit(masm);
+            }
+            int upperLimit = highKey - lowKey;
+            if (isSimm13(upperLimit)) {
+                new Cmp(scratchReg, upperLimit).emit(masm);
+            } else {
+                new Setx(upperLimit, g3).emit(masm);
+                new Cmp(scratchReg, upperLimit).emit(masm);
             }
 
             // Jump to default target if index is not within the jump table
@@ -268,19 +304,20 @@
             }
 
             // Load jump table entry into scratch and jump to it
-            new Sll(value, 3, value).emit(masm); // Multiply by 8
-            new Rdpc(scratchReg).emit(masm);
+            new Sll(scratchReg, 3, scratchReg).emit(masm); // Multiply by 8
+            // Zero the left bits sll with shcnt>0 does not mask upper 32 bits
+            new Srl(scratchReg, 0, scratchReg).emit(masm);
+            new Rdpc(g3).emit(masm);
 
             // The jump table follows four instructions after rdpc
             new Add(scratchReg, 4 * 4, scratchReg).emit(masm);
-            new Jmpl(value, scratchReg, g0).emit(masm);
-            new Sra(value, 3, value).emit(masm); // delay slot, correct the value (division by 8)
+            new Jmpl(g3, scratchReg, g0).emit(masm);
+            new Nop().emit(masm);
+            // new Sra(value, 3, value).emit(masm); // delay slot, correct the value (division by 8)
 
             // Emit jump table entries
             for (LabelRef target : targets) {
-                Label label = target.label();
-                label.addPatchAt(masm.position());
-                new Bpa(0).emit(masm);
+                new Bpa(target.label()).emit(masm);
                 new Nop().emit(masm); // delay slot
             }
         }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Tue Aug 26 09:35:08 2014 -0700
@@ -25,16 +25,18 @@
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static com.oracle.graal.sparc.SPARC.*;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.*;
 
 import com.oracle.graal.api.code.CompilationResult.RawData;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 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.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.StandardOp.NullCheck;
 import com.oracle.graal.lir.asm.*;
 
 public class SPARCMove {
@@ -135,7 +137,7 @@
 
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
-            final SPARCAddress addr = address.toAddress();
+            final SPARCAddress addr = guaranueeLoadable(address.toAddress(), masm);
             final Register dst = asRegister(result);
             switch (kind) {
                 case Boolean:
@@ -172,21 +174,17 @@
     public static class LoadAddressOp extends SPARCLIRInstruction {
 
         @Def({REG}) protected AllocatableValue result;
-        @Use({COMPOSITE, UNINITIALIZED}) protected SPARCAddressValue address;
+        @Use({COMPOSITE, UNINITIALIZED}) protected SPARCAddressValue addressValue;
 
         public LoadAddressOp(AllocatableValue result, SPARCAddressValue address) {
             this.result = result;
-            this.address = address;
+            this.addressValue = address;
         }
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            SPARCAddress addr = address.toAddress();
-            if (addr.hasIndex()) {
-                new Add(addr.getBase(), addr.getIndex(), asLongReg(result)).emit(masm);
-            } else {
-                new Add(addr.getBase(), addr.getDisplacement(), asLongReg(result)).emit(masm);
-            }
+            SPARCAddress address = addressValue.toAddress();
+            loadEffectiveAddress(address, asLongReg(result), masm);
         }
     }
 
@@ -283,7 +281,21 @@
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             SPARCAddress address = (SPARCAddress) crb.asAddress(slot);
-            new Add(address.getBase(), address.getDisplacement(), asLongReg(result)).emit(masm);
+            loadEffectiveAddress(address, asLongReg(result), masm);
+        }
+    }
+
+    private static void loadEffectiveAddress(SPARCAddress address, Register result, SPARCMacroAssembler masm) {
+        if (address.getIndex().equals(Register.None)) {
+            if (isSimm13(address.getDisplacement())) {
+                new Add(address.getBase(), address.getDisplacement(), result).emit(masm);
+            } else {
+                assert result.encoding() != address.getBase().encoding();
+                new Setx(address.getDisplacement(), result).emit(masm);
+                new Add(address.getBase(), result, result).emit(masm);
+            }
+        } else {
+            new Add(address.getBase(), address.getIndex(), result).emit(masm);
         }
     }
 
@@ -299,7 +311,7 @@
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
             assert isRegister(input);
-            SPARCAddress addr = address.toAddress();
+            SPARCAddress addr = guaranueeLoadable(address.toAddress(), masm);
             switch (kind) {
                 case Boolean:
                 case Byte:
@@ -344,21 +356,22 @@
 
         @Override
         public void emitMemAccess(SPARCMacroAssembler masm) {
+            SPARCAddress addr = guaranueeLoadable(address.toAddress(), masm);
             switch (kind) {
                 case Boolean:
                 case Byte:
-                    new Stb(g0, address.toAddress()).emit(masm);
+                    new Stb(g0, addr).emit(masm);
                     break;
                 case Short:
                 case Char:
-                    new Sth(g0, address.toAddress()).emit(masm);
+                    new Sth(g0, addr).emit(masm);
                     break;
                 case Int:
-                    new Stw(g0, address.toAddress()).emit(masm);
+                    new Stw(g0, addr).emit(masm);
                     break;
                 case Long:
                 case Object:
-                    new Stx(g0, address.toAddress()).emit(masm);
+                    new Stx(g0, addr).emit(masm);
                     break;
                 case Float:
                 case Double:
@@ -451,8 +464,29 @@
         }
     }
 
+    /**
+     * Guarantees that the given SPARCAddress given before is loadable by subsequent call. If the
+     * displacement exceeds the imm13 value, the value is put into a scratch register o7, which must
+     * be used as soon as possible.
+     *
+     * @param addr Address to modify
+     * @param masm assembler to output the prior stx command
+     * @return a loadable SPARCAddress
+     */
+    public static SPARCAddress guaranueeLoadable(SPARCAddress addr, SPARCMacroAssembler masm) {
+        boolean displacementOutOfBound = addr.getIndex().equals(Register.None) && !SPARCAssembler.isSimm13(addr.getDisplacement());
+        if (displacementOutOfBound) {
+            Register scratch = g3;
+            new Setx(addr.getDisplacement(), scratch, false).emit(masm);
+            return new SPARCAddress(addr.getBase(), scratch);
+        } else {
+            return addr;
+        }
+    }
+
     private static void reg2stack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input) {
         SPARCAddress dst = (SPARCAddress) crb.asAddress(result);
+        dst = guaranueeLoadable(dst, masm);
         Register src = asRegister(input);
         switch (input.getKind()) {
             case Byte:
@@ -483,6 +517,7 @@
 
     private static void stack2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input) {
         SPARCAddress src = (SPARCAddress) crb.asAddress(input);
+        src = guaranueeLoadable(src, masm);
         Register dst = asRegister(result);
         switch (input.getKind()) {
             case Boolean:
@@ -517,28 +552,10 @@
         Register scratch = g5;
         switch (input.getKind().getStackKind()) {
             case Int:
-                if (crb.codeCache.needsDataPatch(input)) {
-                    crb.recordInlineDataInCode(input);
-                    new Setuw(input.asInt(), asRegister(result)).emit(masm);
-                } else {
-                    if (input.isDefaultForKind()) {
-                        new Clr(asRegister(result)).emit(masm);
-                    } else {
-                        new Setuw(input.asInt(), asRegister(result)).emit(masm);
-                    }
-                }
+                new Setx(input.asLong(), asIntReg(result)).emit(masm);
                 break;
             case Long:
-                if (crb.codeCache.needsDataPatch(input)) {
-                    crb.recordInlineDataInCode(input);
-                    new Setx(input.asLong(), asRegister(result), true).emit(masm);
-                } else {
-                    if (input.isDefaultForKind()) {
-                        new Clr(asRegister(result)).emit(masm);
-                    } else {
-                        new Setx(input.asLong(), asRegister(result)).emit(masm);
-                    }
-                }
+                new Setx(input.asLong(), asLongReg(result)).emit(masm);
                 break;
             case Float:
                 // TODO: Handle it the same way, as in the double case with Movwtos
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java	Tue Aug 26 09:35:08 2014 -0700
@@ -27,10 +27,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.asm.sparc.SPARCAssembler.Movxtod;
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.sparc.*;
 
 /**
  * Saves registers to stack slots.
@@ -78,6 +80,7 @@
                 saveRegister(crb, masm, slots[i], savedRegisters[i]);
             }
         }
+        new Movxtod(SPARC.i0, SPARC.f31).emit(masm);
     }
 
     public StackSlot[] getSlots() {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java	Tue Aug 26 09:35:08 2014 -0700
@@ -204,7 +204,8 @@
         // @formatter:off
         assert (!slot.getRawAddFrameSize() && slot.getRawOffset() <  outgoingSize) ||
                ( slot.getRawAddFrameSize() && slot.getRawOffset() <  0 && -slot.getRawOffset() <= spillSize) ||
-               ( slot.getRawAddFrameSize() && slot.getRawOffset() >= 0);
+               ( slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) :
+                   String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize);
         // @formatter:on
         if (slot.isInCallerFrame()) {
             accessesCallerFrame = true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantLoadOptimization.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+import com.oracle.graal.lir.constopt.ConstantTree.Flags;
+import com.oracle.graal.lir.constopt.ConstantTree.NodeCost;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.options.*;
+
+/**
+ * This optimization tries to improve the handling of constants by replacing a single definition of
+ * a constant, which is potentially scheduled into a block with high probability, with one or more
+ * definitions in blocks with a lower probability.
+ */
+public class ConstantLoadOptimization {
+
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Enable constant load optimization.")
+        public static final OptionValue<Boolean> ConstantLoadOptimization = new OptionValue<>(true);
+        // @formatter:on
+    }
+
+    public static void optimize(LIR lir, LIRGeneratorTool lirGen) {
+        new ConstantLoadOptimization(lir, lirGen).apply();
+    }
+
+    private LIR lir;
+    private LIRGeneratorTool lirGen;
+    private VariableMap<DefUseTree> map;
+    private BitSet phiConstants;
+    private BitSet defined;
+    private BlockMap<List<UseEntry>> blockMap;
+    private BlockMap<LIRInsertionBuffer> insertionBuffers;
+
+    private static DebugMetric constantsTotal = Debug.metric("ConstantLoadOptimization[total]");
+    private static DebugMetric phiConstantsSkipped = Debug.metric("ConstantLoadOptimization[PhisSkipped]");
+    private static DebugMetric singleUsageConstantsSkipped = Debug.metric("ConstantLoadOptimization[SingleUsageSkipped]");
+    private static DebugMetric usageAtDefinitionSkipped = Debug.metric("ConstantLoadOptimization[UsageAtDefinitionSkipped]");
+    private static DebugMetric materializeAtDefinitionSkipped = Debug.metric("ConstantLoadOptimization[MaterializeAtDefinitionSkipped]");
+    private static DebugMetric constantsOptimized = Debug.metric("ConstantLoadOptimization[optimized]");
+
+    private ConstantLoadOptimization(LIR lir, LIRGeneratorTool lirGen) {
+        this.lir = lir;
+        this.lirGen = lirGen;
+        this.map = new VariableMap<>();
+        this.phiConstants = new BitSet();
+        this.defined = new BitSet();
+        this.insertionBuffers = new BlockMap<>(lir.getControlFlowGraph());
+        this.blockMap = new BlockMap<>(lir.getControlFlowGraph());
+    }
+
+    private void apply() {
+        try (Indent indent = Debug.logAndIndent("ConstantLoadOptimization")) {
+            try (Scope s = Debug.scope("BuildDefUseTree")) {
+                // build DefUseTree
+                lir.getControlFlowGraph().getBlocks().forEach(this::analyzeBlock);
+                // remove all with only one use
+                map.filter(t -> {
+                    if (t.usageCount() > 1) {
+                        return true;
+                    } else {
+                        singleUsageConstantsSkipped.increment();
+                        return false;
+                    }
+                });
+                // collect block map
+                map.forEach(tree -> tree.forEach(this::addUsageToBlockMap));
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+
+            try (Scope s = Debug.scope("BuildConstantTree")) {
+                // create ConstantTree
+                map.forEach(this::createConstantTree);
+
+                // insert moves, delete null instructions and reset instruction ids
+                lir.getControlFlowGraph().getBlocks().forEach(this::rewriteBlock);
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+        }
+    }
+
+    private static boolean isConstantLoad(LIRInstruction inst) {
+        if (!(inst instanceof MoveOp)) {
+            return false;
+        }
+        MoveOp move = (MoveOp) inst;
+        return isConstant(move.getInput()) && isVariable(move.getResult());
+    }
+
+    private void addUsageToBlockMap(UseEntry entry) {
+        AbstractBlock<?> block = entry.getBlock();
+        List<UseEntry> list = blockMap.get(block);
+        if (list == null) {
+            list = new ArrayList<>();
+            blockMap.put(block, list);
+        }
+        list.add(entry);
+    }
+
+    /**
+     * Collects def-use information for a {@code block}.
+     */
+    private void analyzeBlock(AbstractBlock<?> block) {
+        try (Indent indent = Debug.logAndIndent("Block: %s", block)) {
+
+            InstructionValueConsumer loadConsumer = new InstructionValueConsumer() {
+                @Override
+                public void visitValue(LIRInstruction instruction, Value value) {
+                    if (isVariable(value)) {
+                        Variable var = (Variable) value;
+
+                        if (!phiConstants.get(var.index)) {
+                            if (!defined.get(var.index)) {
+                                defined.set(var.index);
+                                if (isConstantLoad(instruction)) {
+                                    Debug.log("constant load: %s", instruction);
+                                    map.put(var, new DefUseTree(instruction, block));
+                                    constantsTotal.increment();
+                                }
+                            } else {
+                                // Variable is redefined, this only happens for constant loads
+                                // introduced by phi resolution -> ignore.
+                                DefUseTree removed = map.remove(var);
+                                if (removed != null) {
+                                    phiConstantsSkipped.increment();
+                                }
+                                phiConstants.set(var.index);
+                                Debug.log(3, "Removing phi variable: %s", var);
+                            }
+                        } else {
+                            assert defined.get(var.index) : "phi but not defined? " + var;
+                        }
+
+                    }
+                }
+
+            };
+
+            ValuePositionProcedure useProcedure = new ValuePositionProcedure() {
+                @Override
+                public void doValue(LIRInstruction instruction, ValuePosition position) {
+                    Value value = position.get(instruction);
+                    if (isVariable(value)) {
+                        Variable var = (Variable) value;
+                        if (!phiConstants.get(var.index)) {
+                            DefUseTree tree = map.get(var);
+                            if (tree != null) {
+                                tree.addUsage(block, instruction, position);
+                                Debug.log("usage of %s : %s", var, instruction);
+                            }
+                        }
+                    }
+                }
+
+            };
+
+            int opId = 0;
+            for (LIRInstruction inst : lir.getLIRforBlock(block)) {
+                // set instruction id to the index in the lir instruction list
+                inst.setId(opId++);
+                inst.visitEachOutput(loadConsumer);
+                inst.forEachInput(useProcedure);
+                inst.forEachAlive(useProcedure);
+
+            }
+        }
+    }
+
+    /**
+     * Creates the dominator tree and searches for an solution.
+     */
+    private void createConstantTree(DefUseTree tree) {
+        ConstantTree constTree = new ConstantTree(lir.getControlFlowGraph(), tree);
+        constTree.set(Flags.SUBTREE, tree.getBlock());
+        tree.forEach(u -> constTree.set(Flags.USAGE, u.getBlock()));
+
+        if (constTree.get(Flags.USAGE, tree.getBlock())) {
+            // usage in the definition block -> no optimization
+            usageAtDefinitionSkipped.increment();
+            return;
+        }
+
+        constTree.markBlocks();
+
+        NodeCost cost = ConstantTreeAnalyzer.analyze(constTree, tree.getBlock());
+        int usageCount = cost.getUsages().size();
+        assert usageCount == tree.usageCount() : "Usage count differs: " + usageCount + " vs. " + tree.usageCount();
+
+        if (Debug.isLogEnabled()) {
+            try (Indent i = Debug.logAndIndent("Variable: %s, Block: %s, prob.: %f", tree.getVariable(), tree.getBlock(), tree.getBlock().probability())) {
+                Debug.log("Usages result: %s", cost);
+            }
+
+        }
+
+        if (cost.getNumMaterializations() > 1 || cost.getBestCost() < tree.getBlock().probability()) {
+            try (Scope s = Debug.scope("CLOmodify", constTree); Indent i = Debug.logAndIndent("Replacing %s = %s", tree.getVariable(), tree.getConstant().toValueString())) {
+                // mark original load for removal
+                deleteInstruction(tree);
+                constantsOptimized.increment();
+
+                // collect result
+                createLoads(tree, constTree, tree.getBlock());
+
+            } catch (Throwable e) {
+                throw Debug.handle(e);
+            }
+        } else {
+            // no better solution found
+            materializeAtDefinitionSkipped.increment();
+        }
+        Debug.dump(constTree, "ConstantTree for " + tree.getVariable());
+    }
+
+    private void createLoads(DefUseTree tree, ConstantTree constTree, AbstractBlock<?> startBlock) {
+        Deque<AbstractBlock<?>> worklist = new ArrayDeque<>();
+        worklist.add(startBlock);
+        while (!worklist.isEmpty()) {
+            AbstractBlock<?> block = worklist.pollLast();
+            if (constTree.get(Flags.CANDIDATE, block)) {
+                constTree.set(Flags.MATERIALIZE, block);
+                // create and insert load
+                insertLoad(tree.getConstant(), tree.getVariable().getLIRKind(), block, constTree.getCost(block).getUsages());
+            } else {
+                for (AbstractBlock<?> dominated : block.getDominated()) {
+                    if (constTree.isMarked(dominated)) {
+                        worklist.addLast(dominated);
+                    }
+                }
+            }
+        }
+    }
+
+    private void insertLoad(Constant constant, LIRKind kind, AbstractBlock<?> block, List<UseEntry> usages) {
+        assert usages != null && usages.size() > 0 : String.format("No usages %s %s %s", constant, block, usages);
+        // create variable
+        Variable variable = lirGen.newVariable(kind);
+        // create move
+        LIRInstruction move = lir.getSpillMoveFactory().createMove(variable, constant);
+        // insert instruction
+        getInsertionBuffer(block).append(1, move);
+        Debug.log("new move (%s) and inserted in block %s", move, block);
+        // update usages
+        for (UseEntry u : usages) {
+            u.getPosition().set(u.getInstruction(), variable);
+            Debug.log("patched instruction %s", u.getInstruction());
+        }
+    }
+
+    /**
+     * Inserts the constant loads created in {@link #createConstantTree} and deletes the original
+     * definition.
+     */
+    private void rewriteBlock(AbstractBlock<?> block) {
+        // insert moves
+        LIRInsertionBuffer buffer = insertionBuffers.get(block);
+        if (buffer != null) {
+            assert buffer.initialized() : "not initialized?";
+            buffer.finish();
+        }
+
+        // delete instructions
+        List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+        boolean hasDead = false;
+        for (LIRInstruction inst : instructions) {
+            if (inst == null) {
+                hasDead = true;
+            } else {
+                inst.setId(-1);
+            }
+        }
+        if (hasDead) {
+            // Remove null values from the list.
+            instructions.removeAll(Collections.singleton(null));
+        }
+    }
+
+    private void deleteInstruction(DefUseTree tree) {
+        AbstractBlock<?> block = tree.getBlock();
+        LIRInstruction instruction = tree.getInstruction();
+        Debug.log("deleting instruction %s from block %s", instruction, block);
+        lir.getLIRforBlock(block).set(instruction.id(), null);
+    }
+
+    private LIRInsertionBuffer getInsertionBuffer(AbstractBlock<?> block) {
+        LIRInsertionBuffer insertionBuffer = insertionBuffers.get(block);
+        if (insertionBuffer == null) {
+            insertionBuffer = new LIRInsertionBuffer();
+            insertionBuffers.put(block, insertionBuffer);
+            assert !insertionBuffer.initialized() : "already initialized?";
+            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+            insertionBuffer.init(instructions);
+        }
+        return insertionBuffer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTree.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import java.util.*;
+import java.util.function.*;
+
+import com.oracle.graal.compiler.common.cfg.*;
+
+/**
+ * Represents a dominator (sub-)tree for a constant definition.
+ */
+public class ConstantTree extends PrintableDominatorOptimizationProblem<ConstantTree.Flags, ConstantTree.NodeCost> {
+
+    public enum Flags {
+        SUBTREE,
+        USAGE,
+        MATERIALIZE,
+        CANDIDATE,
+    }
+
+    /**
+     * Costs associated with a block.
+     */
+    public static class NodeCost implements PropertyConsumable {
+        private List<UseEntry> usages;
+        private double bestCost;
+        private int numMat;
+
+        public NodeCost(double bestCost, List<UseEntry> usages, int numMat) {
+            this.bestCost = bestCost;
+            this.usages = usages;
+            this.numMat = numMat;
+        }
+
+        public void forEachProperty(BiConsumer<String, String> action) {
+            action.accept("bestCost", Double.toString(getBestCost()));
+            action.accept("numMat", Integer.toString(getNumMaterializations()));
+            action.accept("numUsages", Integer.toString(usages.size()));
+        }
+
+        public void addUsage(UseEntry usage) {
+            if (usages == null) {
+                usages = new ArrayList<>();
+            }
+            usages.add(usage);
+        }
+
+        public List<UseEntry> getUsages() {
+            if (usages == null) {
+                Collections.emptyList();
+            }
+            return usages;
+        }
+
+        public double getBestCost() {
+            return bestCost;
+        }
+
+        public int getNumMaterializations() {
+            return numMat;
+        }
+
+        public void setBestCost(double cost) {
+            bestCost = cost;
+        }
+
+        @Override
+        public String toString() {
+            return "NodeCost [bestCost=" + bestCost + ", numUsages=" + usages.size() + ", numMat=" + numMat + "]";
+        }
+    }
+
+    private final BlockMap<List<UseEntry>> blockMap;
+
+    public ConstantTree(AbstractControlFlowGraph<?> cfg, DefUseTree tree) {
+        super(Flags.class, cfg);
+        this.blockMap = new BlockMap<>(cfg);
+        tree.forEach(u -> getOrInitList(u.getBlock()).add(u));
+    }
+
+    private List<UseEntry> getOrInitList(AbstractBlock<?> block) {
+        List<UseEntry> list = blockMap.get(block);
+        if (list == null) {
+            list = new ArrayList<>();
+            blockMap.put(block, list);
+        }
+        return list;
+    }
+
+    public List<UseEntry> getUsages(AbstractBlock<?> block) {
+        List<UseEntry> list = blockMap.get(block);
+        if (list == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    /**
+     * Returns the cost object associated with {@code block}. If there is none, a new cost object is
+     * created.
+     */
+    NodeCost getOrInitCost(AbstractBlock<?> block) {
+        NodeCost cost = getCost(block);
+        if (cost == null) {
+            cost = new NodeCost(block.probability(), blockMap.get(block), 1);
+            setCost(block, cost);
+        }
+        return cost;
+    }
+
+    @Override
+    public String getName(Flags type) {
+        switch (type) {
+            case USAGE:
+                return "hasUsage";
+            case SUBTREE:
+                return "inSubtree";
+            case MATERIALIZE:
+                return "materialize";
+            case CANDIDATE:
+                return "candidate";
+        }
+        return super.getName(type);
+    }
+
+    @Override
+    public void forEachPropertyPair(AbstractBlock<?> block, BiConsumer<String, String> action) {
+        if (get(Flags.SUBTREE, block) && (block.getDominator() == null || !get(Flags.SUBTREE, block.getDominator()))) {
+            action.accept("hasDefinition", "true");
+        }
+        super.forEachPropertyPair(block, action);
+    }
+
+    public long subTreeSize() {
+        return stream(Flags.SUBTREE).count();
+    }
+
+    public AbstractBlock<?> getStartBlock() {
+        return stream(Flags.SUBTREE).findFirst().get();
+    }
+
+    public void markBlocks() {
+        stream(Flags.USAGE).forEach(block -> setDominatorPath(Flags.SUBTREE, block));
+    }
+
+    public boolean isMarked(AbstractBlock<?> block) {
+        return get(Flags.SUBTREE, block);
+    }
+
+    public boolean isLeafBlock(AbstractBlock<?> block) {
+        return block.getDominated().stream().noneMatch(this::isMarked);
+    }
+
+    public void setSolution(AbstractBlock<?> block) {
+        set(Flags.MATERIALIZE, block);
+    }
+
+    public int size() {
+        return getBlocks().size();
+    }
+
+    public void traverseTreeWhileTrue(AbstractBlock<?> block, Predicate<AbstractBlock<?>> action) {
+        assert block != null : "block must not be null!";
+        if (action.test(block)) {
+            block.getDominated().stream().filter(this::isMarked).forEach(dominated -> traverseTreeWhileTrue(dominated, action));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/ConstantTreeAnalyzer.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import java.util.*;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.Debug.Scope;
+import com.oracle.graal.lir.constopt.ConstantTree.Flags;
+import com.oracle.graal.lir.constopt.ConstantTree.NodeCost;
+
+/**
+ * Analyzes a {@link ConstantTree} and marks potential materialization positions.
+ */
+public class ConstantTreeAnalyzer {
+    private final ConstantTree tree;
+    private final BitSet visited;
+
+    public static NodeCost analyze(ConstantTree tree, AbstractBlock<?> startBlock) {
+        try (Scope s = Debug.scope("ConstantTreeAnalyzer")) {
+            ConstantTreeAnalyzer analyzer = new ConstantTreeAnalyzer(tree);
+            analyzer.analyzeBlocks(startBlock);
+            return tree.getCost(startBlock);
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
+
+    private ConstantTreeAnalyzer(ConstantTree tree) {
+        this.tree = tree;
+        this.visited = new BitSet(tree.size());
+    }
+
+    /**
+     * Queues all relevant blocks for {@linkplain #process processing}.
+     *
+     * This is a worklist-style algorithm because a (more elegant) recursive implementation may
+     * cause {@linkplain StackOverflowError stack overflows} on larger graphs.
+     *
+     * @param startBlock The start block of the dominator subtree.
+     */
+    private void analyzeBlocks(AbstractBlock<?> startBlock) {
+        Deque<AbstractBlock<?>> worklist = new ArrayDeque<>();
+        worklist.offerLast(startBlock);
+        while (!worklist.isEmpty()) {
+            AbstractBlock<?> block = worklist.pollLast();
+            try (Indent i = Debug.logAndIndent(3, "analyze: %s", block)) {
+                assert block != null : "worklist is empty!";
+                assert isMarked(block) : "Block not part of the dominator tree: " + block;
+
+                if (isLeafBlock(block)) {
+                    Debug.log(3, "leaf block");
+                    leafCost(block);
+                    continue;
+                }
+
+                if (!visited.get(block.getId())) {
+                    // if not yet visited (and not a leaf block) process all children first!
+                    Debug.log(3, "not marked");
+                    worklist.offerLast(block);
+                    List<? extends AbstractBlock<?>> children = block.getDominated();
+                    children.forEach(child -> filteredPush(worklist, child));
+                    visited.set(block.getId());
+                } else {
+                    Debug.log(3, "marked");
+                    // otherwise, process block
+                    process(block);
+                }
+            }
+        }
+    }
+
+    /**
+     * Calculates the cost of a {@code block}. It is assumed that all {@code children} have already
+     * been {@linkplain #process processed}
+     *
+     * @param block The block to be processed.
+     */
+    private void process(AbstractBlock<?> block) {
+        List<UseEntry> usages = new ArrayList<>();
+        double bestCost = 0;
+        int numMat = 0;
+        List<? extends AbstractBlock<?>> children = block.getDominated();
+        assert children.stream().anyMatch(this::isMarked) : "no children? should have called leafCost(): " + block;
+
+        // collect children costs
+        for (AbstractBlock<?> child : children) {
+            if (isMarked(child)) {
+                NodeCost childCost = tree.getCost(child);
+                assert childCost != null : "Child with null cost? block: " + child;
+                usages.addAll(childCost.getUsages());
+                numMat += childCost.getNumMaterializations();
+                bestCost += childCost.getBestCost();
+            }
+        }
+        assert numMat > 0 : "No materialization? " + numMat;
+
+        // choose block
+        List<UseEntry> usagesBlock = tree.getUsages(block);
+        double probabilityBlock = block.probability();
+
+        if (!usagesBlock.isEmpty() || shouldMaterializerInCurrentBlock(probabilityBlock, bestCost, numMat)) {
+            // mark current block as potential materialization position
+            usages.addAll(usagesBlock);
+            bestCost = probabilityBlock;
+            numMat = 1;
+            tree.set(Flags.CANDIDATE, block);
+        } else {
+            // stick with the current solution
+        }
+
+        assert (new HashSet<>(usages)).size() == usages.size() : "doulbe entries? " + usages;
+        NodeCost nodeCost = new NodeCost(bestCost, usages, numMat);
+        tree.setCost(block, nodeCost);
+    }
+
+    /**
+     * This is the cost function that decides whether a materialization should be inserted in the
+     * current block.
+     * <p>
+     * Note that this function does not take into account if a materialization is required despite
+     * the probabilities (e.g. there are usages in the current block).
+     *
+     * @param probabilityBlock Probability of the current block.
+     * @param probabilityChildren Accumulated probability of the children.
+     * @param numMat Number of materializations along the subtrees. We use {@code numMat - 1} to
+     *            insert materializations as late as possible if the probabilities are the same.
+     */
+    private static boolean shouldMaterializerInCurrentBlock(double probabilityBlock, double probabilityChildren, int numMat) {
+        return probabilityBlock * Math.pow(0.9, numMat - 1) < probabilityChildren;
+    }
+
+    private void filteredPush(Deque<AbstractBlock<?>> worklist, AbstractBlock<?> block) {
+        if (isMarked(block)) {
+            Debug.log(3, "adding %s to the worklist", block);
+            worklist.offerLast(block);
+        }
+    }
+
+    private void leafCost(AbstractBlock<?> block) {
+        tree.set(Flags.CANDIDATE, block);
+        tree.getOrInitCost(block);
+    }
+
+    private boolean isMarked(AbstractBlock<?> block) {
+        return tree.isMarked(block);
+    }
+
+    private boolean isLeafBlock(AbstractBlock<?> block) {
+        return tree.isLeafBlock(block);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/DefUseTree.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import java.util.*;
+import java.util.function.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+
+/**
+ * Represents def-use tree of a constant.
+ */
+class DefUseTree {
+    private final LIRInstruction instruction;
+    private final AbstractBlock<?> block;
+    private final List<UseEntry> uses;
+
+    public DefUseTree(LIRInstruction instruction, AbstractBlock<?> block) {
+        assert instruction instanceof MoveOp : "Not a MoveOp: " + instruction;
+        this.instruction = instruction;
+        this.block = block;
+        this.uses = new ArrayList<>();
+    }
+
+    public Variable getVariable() {
+        return (Variable) ((MoveOp) instruction).getResult();
+    }
+
+    public Constant getConstant() {
+        return (Constant) ((MoveOp) instruction).getInput();
+    }
+
+    public LIRInstruction getInstruction() {
+        return instruction;
+    }
+
+    public AbstractBlock<?> getBlock() {
+        return block;
+    }
+
+    @Override
+    public String toString() {
+        return "DefUseTree [" + instruction + "|" + block + "," + uses + "]";
+    }
+
+    public void addUsage(AbstractBlock<?> b, LIRInstruction inst, ValuePosition position) {
+        uses.add(new UseEntry(b, inst, position));
+    }
+
+    public int usageCount() {
+        return uses.size();
+    }
+
+    public void forEach(Consumer<? super UseEntry> action) {
+        uses.forEach(action);
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/UseEntry.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.lir.*;
+
+/**
+ * Represents a usage of a constant.
+ */
+class UseEntry {
+
+    private final AbstractBlock<?> block;
+    private final LIRInstruction instruction;
+    private final ValuePosition position;
+
+    public UseEntry(AbstractBlock<?> block, LIRInstruction instruction, ValuePosition position) {
+        this.block = block;
+        this.instruction = instruction;
+        this.position = position;
+    }
+
+    public LIRInstruction getInstruction() {
+        return instruction;
+    }
+
+    public AbstractBlock<?> getBlock() {
+        return block;
+    }
+
+    public ValuePosition getPosition() {
+        return position;
+    }
+
+    public Value getValue() {
+        return position.get(instruction);
+    }
+
+    @Override
+    public String toString() {
+        return "Use[" + getValue() + ":" + instruction + ":" + block + "]";
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/constopt/VariableMap.java	Tue Aug 26 09:35:08 2014 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014, 2014, 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.constopt;
+
+import java.util.*;
+import java.util.function.*;
+
+import com.oracle.graal.lir.*;
+
+/**
+ * Maps variables to a generic type.
+ *
+ * TODO (je) evaluate data structure
+ */
+class VariableMap<T> {
+
+    private final ArrayList<T> content;
+
+    public VariableMap() {
+        content = new ArrayList<>();
+    }
+
+    public T get(Variable key) {
+        if (key == null || key.index >= content.size()) {
+            return null;
+        }
+        return content.get(key.index);
+    }
+
+    public T put(Variable key, T value) {
+        assert key != null : "Key cannot be null";
+        assert value != null : "Value cannot be null";
+        while (key.index >= content.size()) {
+            content.add(null);
+        }
+        return content.set(key.index, value);
+    }
+
+    public T remove(Variable key) {
+        assert key != null : "Key cannot be null";
+        if (key.index >= content.size()) {
+            return null;
+        }
+        return content.set(key.index, null);
+    }
+
+    public void forEach(Consumer<T> action) {
+        for (T e : content) {
+            if (e != null) {
+                action.accept(e);
+            }
+        }
+    }
+
+    /**
+     * Keeps only keys which match the given predicate.
+     */
+    public void filter(Predicate<T> predicate) {
+        for (int i = 0; i < content.size(); i++) {
+            T e = content.get(i);
+            if (e != null && !predicate.test(e)) {
+                content.set(i, null);
+            }
+        }
+    }
+
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Tue Aug 26 09:35:08 2014 -0700
@@ -273,24 +273,20 @@
             }
         }
 
-        // Currently no node printing for lir
-        if (lir == null) {
-            Node cur = block.getBeginNode();
-            while (true) {
-                printNode(cur, false);
+        Node cur = block.getBeginNode();
+        while (true) {
+            printNode(cur, false);
 
-                if (cur == block.getEndNode()) {
-                    for (Map.Entry<Node, Block> entry : latestScheduling.entries()) {
-                        if (entry.getValue() == block && !inFixedSchedule(entry.getKey()) && !printedNodes.isMarked(entry.getKey())) {
-                            printNode(entry.getKey(), true);
-                        }
+            if (cur == block.getEndNode()) {
+                for (Map.Entry<Node, Block> entry : latestScheduling.entries()) {
+                    if (entry.getValue() == block && !inFixedSchedule(entry.getKey()) && !printedNodes.isMarked(entry.getKey())) {
+                        printNode(entry.getKey(), true);
                     }
-                    break;
                 }
-                assert cur.successors().count() == 1;
-                cur = cur.successors().first();
+                break;
             }
-
+            assert cur.successors().count() == 1;
+            cur = cur.successors().first();
         }
 
         out.enableIndentation();
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Tue Aug 26 09:35:08 2014 -0700
@@ -50,7 +50,6 @@
     private JavaMethod curMethod;
     private List<String> curDecorators = Collections.emptyList();
     private final boolean dumpFrontend;
-    private Object previousObject;
 
     public CFGPrinterObserver(boolean dumpFrontend) {
         this.dumpFrontend = dumpFrontend;
@@ -162,10 +161,8 @@
             }
 
         } else if (object instanceof LIR) {
-            // No need to print the HIR nodes again if this is not the first
-            // time dumping the same LIR since the HIR will not have changed.
-            boolean printNodes = previousObject != object && cfgPrinter.cfg != null;
-            cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), printNodes);
+            // Currently no node printing for lir
+            cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder(), false);
 
         } else if (object instanceof SchedulePhase) {
             cfgPrinter.printSchedule(message, (SchedulePhase) object);
@@ -193,7 +190,6 @@
         cfgPrinter.cfg = null;
         cfgPrinter.flush();
 
-        previousObject = object;
     }
 
     private static boolean isCompilationResultAndInstalledCode(Object object) {
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java	Tue Aug 26 09:35:08 2014 -0700
@@ -108,7 +108,7 @@
     public void test7() {
         char[] src = "1234567890".toCharArray();
         char[] dst = new char[src.length];
-        int n = Runtime.getRuntime().availableProcessors();
+        int n = Math.min(32, Runtime.getRuntime().availableProcessors());
         testN(n, "copyArr", src, dst, 100);
     }
 
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java	Tue Aug 26 09:35:08 2014 -0700
@@ -72,7 +72,11 @@
     public void testMulHighUnsigned() {
         test("mulHighUnsigned", 7, 15);
         test("mulHighUnsigned", Integer.MAX_VALUE, 15);
+        test("mulHighUnsigned", 15, Integer.MAX_VALUE);
+        test("mulHighUnsigned", Integer.MAX_VALUE, Integer.MAX_VALUE);
+        test("mulHighUnsigned", 15, Integer.MIN_VALUE);
         test("mulHighUnsigned", Integer.MIN_VALUE, 15);
+        test("mulHighUnsigned", Integer.MIN_VALUE, Integer.MIN_VALUE);
     }
 
     @Test
@@ -98,7 +102,11 @@
     public void testLongMulHigh() {
         test("longMulHigh", 7L, 15L);
         test("longMulHigh", Long.MAX_VALUE, 15L);
+        test("longMulHigh", 15L, Long.MAX_VALUE);
+        test("longMulHigh", Long.MAX_VALUE, Long.MAX_VALUE);
         test("longMulHigh", Long.MIN_VALUE, 15L);
+        test("longMulHigh", 15L, Long.MIN_VALUE);
+        test("longMulHigh", Long.MIN_VALUE, Long.MIN_VALUE);
     }
 
     @Test
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java	Tue Aug 26 09:35:08 2014 -0700
@@ -34,6 +34,7 @@
 import com.oracle.truffle.dsl.processor.*;
 import com.oracle.truffle.dsl.processor.java.model.*;
 import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror;
+import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.WildcardTypeMirror;
 
 /**
  * THIS IS NOT PUBLIC API.
@@ -1034,4 +1035,35 @@
         return actualType.getKind() == TypeKind.DECLARED && getQualifiedName(actualType).equals("java.lang.Object");
     }
 
+    public static TypeMirror fillInGenericWildcards(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        TypeElement element = (TypeElement) declaredType.asElement();
+        if (element == null) {
+            return type;
+        }
+        int typeParameters = element.getTypeParameters().size();
+        if (typeParameters > 0 && declaredType.getTypeArguments().size() != typeParameters) {
+            List<TypeMirror> genericTypes = new ArrayList<>();
+            for (int i = 0; i < typeParameters; i++) {
+                genericTypes.add(new WildcardTypeMirror(null, null));
+            }
+            return new DeclaredCodeTypeMirror(element, genericTypes);
+        }
+        return type;
+    }
+
+    public static TypeMirror eraseGenericTypes(TypeMirror type) {
+        if (type.getKind() != TypeKind.DECLARED) {
+            return type;
+        }
+        DeclaredType declaredType = (DeclaredType) type;
+        if (declaredType.getTypeArguments().size() == 0) {
+            return type;
+        }
+        return new DeclaredCodeTypeMirror((TypeElement) declaredType.asElement());
+    }
+
 }
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java	Tue Aug 26 09:35:08 2014 -0700
@@ -592,7 +592,7 @@
     }
 
     public CodeTreeBuilder typeLiteral(TypeMirror type) {
-        return startGroup().type(type).string(".class").end();
+        return startGroup().type(ElementUtils.eraseGenericTypes(type)).string(".class").end();
     }
 
     private void assertRoot() {
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTypeMirror.java	Tue Aug 26 09:35:08 2014 -0700
@@ -46,6 +46,27 @@
         throw new UnsupportedOperationException();
     }
 
+    public static class WildcardTypeMirror extends CodeTypeMirror implements WildcardType {
+
+        private final TypeMirror extendsBounds;
+        private final TypeMirror superBounds;
+
+        public WildcardTypeMirror(TypeMirror extendsBounds, TypeMirror superBounds) {
+            super(TypeKind.WILDCARD);
+            this.extendsBounds = extendsBounds;
+            this.superBounds = superBounds;
+        }
+
+        public TypeMirror getExtendsBound() {
+            return extendsBounds;
+        }
+
+        public TypeMirror getSuperBound() {
+            return superBounds;
+        }
+
+    }
+
     public static class ArrayCodeTypeMirror extends CodeTypeMirror implements ArrayType {
 
         private final TypeMirror component;
@@ -65,13 +86,13 @@
     public static class DeclaredCodeTypeMirror extends CodeTypeMirror implements DeclaredType {
 
         private final TypeElement clazz;
-        private final List<? extends TypeMirror> typeArguments;
+        private final List<TypeMirror> typeArguments;
 
         public DeclaredCodeTypeMirror(TypeElement clazz) {
             this(clazz, Collections.<TypeMirror> emptyList());
         }
 
-        public DeclaredCodeTypeMirror(TypeElement clazz, List<? extends TypeMirror> typeArguments) {
+        public DeclaredCodeTypeMirror(TypeElement clazz, List<TypeMirror> typeArguments) {
             super(TypeKind.DECLARED);
             this.clazz = clazz;
             this.typeArguments = typeArguments;
@@ -88,7 +109,7 @@
         }
 
         @Override
-        public List<? extends TypeMirror> getTypeArguments() {
+        public List<TypeMirror> getTypeArguments() {
             return typeArguments;
         }
 
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/transform/OrganizedImports.java	Tue Aug 26 09:35:08 2014 -0700
@@ -107,6 +107,8 @@
             b.append("? extends ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
         } else if (type.getSuperBound() != null) {
             b.append("? super ").append(createTypeReference(enclosedElement, type.getExtendsBound()));
+        } else {
+            b.append("?");
         }
         return b.toString();
     }
@@ -122,18 +124,23 @@
             }
         }
 
-        if (type.getTypeArguments().size() == 0) {
+        List<? extends TypeMirror> genericTypes = type.getTypeArguments();
+        if (genericTypes.size() == 0) {
             return name;
         }
 
         StringBuilder b = new StringBuilder(name);
         b.append("<");
-        if (type.getTypeArguments().size() > 0) {
-            for (int i = 0; i < type.getTypeArguments().size(); i++) {
-                b.append(createTypeReference(enclosedElement, type.getTypeArguments().get(i)));
-                if (i < type.getTypeArguments().size() - 1) {
-                    b.append(", ");
-                }
+        for (int i = 0; i < genericTypes.size(); i++) {
+            TypeMirror genericType = i < genericTypes.size() ? genericTypes.get(i) : null;
+            if (genericType != null) {
+                b.append(createTypeReference(enclosedElement, genericType));
+            } else {
+                b.append("?");
+            }
+
+            if (i < genericTypes.size() - 1) {
+                b.append(", ");
             }
         }
         b.append(">");
--- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Mon Aug 25 11:44:45 2014 -0700
+++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java	Tue Aug 26 09:35:08 2014 -0700
@@ -183,10 +183,12 @@
 
         int index = 0;
         for (TypeMirror primitiveType : typeMirrors) {
-            TypeMirror boxedType = ElementUtils.boxType(context, primitiveType);
-            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitiveType, boxedType);
+            TypeMirror primitive = ElementUtils.fillInGenericWildcards(primitiveType);
 
-            if (isPrimitiveWrapper(primitiveType)) {
+            TypeMirror boxedType = ElementUtils.boxType(context, primitive);
+            TypeData typeData = new TypeData(typeSystem, index, annotationValue, primitive, boxedType);
+
+            if (isPrimitiveWrapper(primitive)) {
                 typeData.addError("Types must not contain primitive wrapper types.");
             }
 
--- a/mx/projects	Mon Aug 25 11:44:45 2014 -0700
+++ b/mx/projects	Tue Aug 26 09:35:08 2014 -0700
@@ -390,7 +390,7 @@
 # graal.lir
 project@com.oracle.graal.lir@subDir=graal
 project@com.oracle.graal.lir@sourceDirs=src
-project@com.oracle.graal.lir@dependencies=com.oracle.graal.debug,com.oracle.graal.compiler.common,com.oracle.graal.asm
+project@com.oracle.graal.lir@dependencies=com.oracle.graal.compiler.common,com.oracle.graal.asm,com.oracle.graal.debug
 project@com.oracle.graal.lir@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.lir@javaCompliance=1.8
 project@com.oracle.graal.lir@workingSets=Graal,LIR
--- a/mxtool/mx.py	Mon Aug 25 11:44:45 2014 -0700
+++ b/mxtool/mx.py	Tue Aug 26 09:35:08 2014 -0700
@@ -1247,11 +1247,11 @@
     """
     Get the list of all loaded projects limited by --suite option if opt_limit_to_suite == True
     """
-
+    sortedProjects = sorted(_projects.values(), key=lambda p: p.name)
     if opt_limit_to_suite:
-        return _projects_opt_limit_to_suites(_projects.values())
+        return _projects_opt_limit_to_suites(sortedProjects)
     else:
-        return _projects.values()
+        return sortedProjects
 
 def projects_opt_limit_to_suites():
     """
@@ -2231,8 +2231,13 @@
                 self.proj.definedAnnotationProcessorsDist.make_archive()
 
         finally:
-            for n in toBeDeleted:
-                os.remove(n)
+            # Do not clean up temp files if verbose as there's
+            # a good chance the user wants to copy and paste the
+            # Java compiler command directly
+            if not _opts.verbose:
+                for n in toBeDeleted:
+                    os.remove(n)
+
             self.done = True
 
 def build(args, parser=None):
@@ -2413,6 +2418,8 @@
             logv('[no Java sources for {0} - skipping]'.format(p.name))
             continue
 
+        javafilelist = sorted(javafilelist)
+
         task = JavaCompileTask(args, p, buildReason, javafilelist, jdk, outputDir, jdtJar, taskDeps)
         if p.definedAnnotationProcessorsDist:
             updatedAnnotationProcessorDists.add(p.definedAnnotationProcessorsDist)
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Mon Aug 25 11:44:45 2014 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Aug 26 09:35:08 2014 -0700
@@ -3433,6 +3433,9 @@
   if (UseStackBanging) {
     pad += StackShadowPages*16 + 32;
   }
+#ifdef GRAAL
+  pad += 32; // Increase the buffer size when compiling for GRAAL
+#endif
 #ifdef _LP64
   CodeBuffer buffer("deopt_blob", 2100+pad, 512);
 #else
@@ -3567,6 +3570,33 @@
   // Restore G2_thread
   __ get_thread();
 
+#ifdef GRAAL
+  // load throwing pc from JavaThread and patch it as the return address
+  // of the current frame. Then clear the field in JavaThread
+  __ block_comment("load throwing pc and patch return");
+  Address exception_pc(G2_thread, JavaThread::exception_pc_offset());
+  Label has_no_pc;
+  // TODO: Remove this weird check if we should patch the return pc
+  // This is because when graal decides to deoptimize and the ExceptionHandlerStub.java
+  // jumps back to this code and the I7 register contains the pc pointing to the begin
+  // of this code. If this is the case (PC within a certain range) then we need to patch
+  // the return pc.
+  // THIS NEEDS REWORK! (sa)
+  __ rdpc(L0);
+  __ sub(L0, I7, L0);
+  __ cmp(L0, 0xFFF);
+  __ br(Assembler::greater, false, Assembler::pt, has_no_pc);
+  __ delayed() -> nop();
+  __ cmp(L0, -0xFFF);
+  __ br(Assembler::less, false, Assembler::pt, has_no_pc);
+  __ delayed() -> nop();
+  __ ld_ptr(exception_pc, I7);
+  __ sub(I7, 8, I7);
+  __ st_ptr(G0, exception_pc);
+  __ bind(has_no_pc);
+  __ block_comment("/load throwing pc and patch return");
+#endif // GAAL
+
 #ifdef ASSERT
   {
     // verify that there is really an exception oop in exception_oop
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Mon Aug 25 11:44:45 2014 -0700
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue Aug 26 09:35:08 2014 -0700
@@ -199,6 +199,22 @@
 address InterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
   address entry = __ pc();
   __ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
+#ifdef GRAAL
+  // Check if we need to take lock at entry of synchronized method.
+  {
+    Label L;
+
+    //__ cmp(, 0);
+    Address pending_monitor_enter_addr(G2_thread, Thread::pending_monitorenter_offset());
+    __ ldbool(pending_monitor_enter_addr, Gtemp);  // Load if pending monitor enter
+    __ cmp_and_br_short(Gtemp, G0, Assembler::equal, Assembler::pn, L);
+    // Clear flag.
+    __ stbool(G0, pending_monitor_enter_addr);
+    // Take lock.
+    lock_method();
+    __ bind(L);
+  }
+#endif
   { Label L;
     Address exception_addr(G2_thread, Thread::pending_exception_offset());
     __ ld_ptr(exception_addr, Gtemp);  // Load pending exception.
@@ -1689,8 +1705,13 @@
         // make sure I5_savedSP and the entry frames notion of saved SP
         // agree.  This assertion duplicate a check in entry frame code
         // but catches the failure earlier.
-        assert(*caller->register_addr(Lscratch) == *interpreter_frame->register_addr(I5_savedSP),
+        /*
+         * Sanzinger: This does not make sense to me, since when we call stub_call -> i2c, the i2c may change the
+         * sp, which then is not in sync with Lscratch anymore.
+         */
+        /**assert(*caller->register_addr(Lscratch) == *interpreter_frame->register_addr(I5_savedSP),
                "would change callers SP");
+               */
       }
       if (caller->is_entry_frame()) {
         tty->print("entry ");
--- a/src/share/vm/graal/graalCodeInstaller.cpp	Mon Aug 25 11:44:45 2014 -0700
+++ b/src/share/vm/graal/graalCodeInstaller.cpp	Tue Aug 26 09:35:08 2014 -0700
@@ -231,6 +231,8 @@
       Location::Type locationType;
       if (type == T_INT) {
         locationType = reference ? Location::narrowoop : Location::int_in_long;
+      } else if(type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
+        locationType = Location::int_in_long;
       } else if (type == T_FLOAT) {
         locationType = Location::int_in_long;
       } else if (type == T_LONG) {
@@ -264,7 +266,7 @@
 #ifdef TARGET_ARCH_sparc
       ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_FloatRegister(encoding)->as_VMReg()));
       if (type == T_DOUBLE) {
-        second = new ConstantIntValue(0);
+        second = value;
       }
       return value;
 #else
@@ -278,6 +280,8 @@
       locationType = reference ? Location::oop : Location::lng;
     } else if (type == T_INT) {
       locationType = reference ? Location::narrowoop : Location::normal;
+    } else if(type == T_SHORT || type == T_CHAR || type == T_BYTE || type == T_BOOLEAN) {
+      locationType = Location::normal;
     } else if (type == T_FLOAT) {
       assert(!reference, "unexpected type in stack slot");
       locationType = Location::normal;
@@ -289,6 +293,11 @@
       locationType = Location::oop;
     }
     jint offset = StackSlot::offset(value);
+#ifdef TARGET_ARCH_sparc
+    if(offset >= 0) {
+      offset += 128;
+    }
+#endif
     if (StackSlot::addFrameSize(value)) {
       offset += total_frame_size;
     }