src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java
changeset 47216 71c04702a3d5
parent 46680 2894e4262fd6
child 47798 9fe9292f5931
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 2011, 2016, 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 org.graalvm.compiler.lir.amd64;
+
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED;
+import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
+import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Float.floatToRawIntBits;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.type.DataPointerConstant;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.lir.LIRFrameState;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.StandardOp.LoadConstantOp;
+import org.graalvm.compiler.lir.StandardOp.NullCheck;
+import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
+import org.graalvm.compiler.lir.VirtualStackSlot;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.Value;
+
+public class AMD64Move {
+
+    private abstract static class AbstractMoveOp extends AMD64LIRInstruction implements ValueMoveOp {
+        public static final LIRInstructionClass<AbstractMoveOp> TYPE = LIRInstructionClass.create(AbstractMoveOp.class);
+
+        private AMD64Kind moveKind;
+
+        protected AbstractMoveOp(LIRInstructionClass<? extends AbstractMoveOp> c, AMD64Kind moveKind) {
+            super(c);
+            this.moveKind = moveKind;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(moveKind, crb, masm, getResult(), getInput());
+        }
+    }
+
+    @Opcode("MOVE")
+    public static final class MoveToRegOp extends AbstractMoveOp {
+        public static final LIRInstructionClass<MoveToRegOp> TYPE = LIRInstructionClass.create(MoveToRegOp.class);
+
+        @Def({REG, HINT}) protected AllocatableValue result;
+        @Use({REG, STACK}) protected AllocatableValue input;
+
+        public MoveToRegOp(AMD64Kind moveKind, AllocatableValue result, AllocatableValue input) {
+            super(TYPE, moveKind);
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public AllocatableValue getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("MOVE")
+    public static final class MoveFromRegOp extends AbstractMoveOp {
+        public static final LIRInstructionClass<MoveFromRegOp> TYPE = LIRInstructionClass.create(MoveFromRegOp.class);
+
+        @Def({REG, STACK}) protected AllocatableValue result;
+        @Use({REG, HINT}) protected AllocatableValue input;
+
+        public MoveFromRegOp(AMD64Kind moveKind, AllocatableValue result, AllocatableValue input) {
+            super(TYPE, moveKind);
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public AllocatableValue getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("MOVE")
+    public static class MoveFromConstOp extends AMD64LIRInstruction implements LoadConstantOp {
+        public static final LIRInstructionClass<MoveFromConstOp> TYPE = LIRInstructionClass.create(MoveFromConstOp.class);
+
+        @Def({REG, STACK}) protected AllocatableValue result;
+        private final JavaConstant input;
+
+        public MoveFromConstOp(AllocatableValue result, JavaConstant input) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (isRegister(result)) {
+                const2reg(crb, masm, asRegister(result), input);
+            } else {
+                assert isStackSlot(result);
+                const2stack(crb, masm, result, input);
+            }
+        }
+
+        @Override
+        public Constant getConstant() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+    }
+
+    @Opcode("STACKMOVE")
+    public static final class AMD64StackMove extends AMD64LIRInstruction implements ValueMoveOp {
+        public static final LIRInstructionClass<AMD64StackMove> TYPE = LIRInstructionClass.create(AMD64StackMove.class);
+
+        @Def({STACK}) protected AllocatableValue result;
+        @Use({STACK, HINT}) protected AllocatableValue input;
+        @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private AllocatableValue backupSlot;
+
+        private Register scratch;
+
+        public AMD64StackMove(AllocatableValue result, AllocatableValue input, Register scratch, AllocatableValue backupSlot) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+            this.backupSlot = backupSlot;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public AllocatableValue getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+
+        public Register getScratchRegister() {
+            return scratch;
+        }
+
+        public AllocatableValue getBackupSlot() {
+            return backupSlot;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            AMD64Kind backupKind = (AMD64Kind) backupSlot.getPlatformKind();
+            if (backupKind.isXMM()) {
+                // graal doesn't use vector values, so it's safe to backup using DOUBLE
+                backupKind = AMD64Kind.DOUBLE;
+            }
+
+            // backup scratch register
+            reg2stack(backupKind, crb, masm, backupSlot, scratch);
+            // move stack slot
+            stack2reg((AMD64Kind) getInput().getPlatformKind(), crb, masm, scratch, getInput());
+            reg2stack((AMD64Kind) getResult().getPlatformKind(), crb, masm, getResult(), scratch);
+            // restore scratch register
+            stack2reg(backupKind, crb, masm, scratch, backupSlot);
+        }
+    }
+
+    @Opcode("MULTISTACKMOVE")
+    public static final class AMD64MultiStackMove extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<AMD64MultiStackMove> TYPE = LIRInstructionClass.create(AMD64MultiStackMove.class);
+
+        @Def({STACK}) protected AllocatableValue[] results;
+        @Use({STACK}) protected Value[] inputs;
+        @Alive({OperandFlag.STACK, OperandFlag.UNINITIALIZED}) private AllocatableValue backupSlot;
+
+        private Register scratch;
+
+        public AMD64MultiStackMove(AllocatableValue[] results, Value[] inputs, Register scratch, AllocatableValue backupSlot) {
+            super(TYPE);
+            this.results = results;
+            this.inputs = inputs;
+            this.backupSlot = backupSlot;
+            this.scratch = scratch;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            AMD64Kind backupKind = (AMD64Kind) backupSlot.getPlatformKind();
+            if (backupKind.isXMM()) {
+                // graal doesn't use vector values, so it's safe to backup using DOUBLE
+                backupKind = AMD64Kind.DOUBLE;
+            }
+
+            // backup scratch register
+            move(backupKind, crb, masm, backupSlot, scratch.asValue(backupSlot.getValueKind()));
+            for (int i = 0; i < results.length; i++) {
+                Value input = inputs[i];
+                AllocatableValue result = results[i];
+                // move stack slot
+                move((AMD64Kind) input.getPlatformKind(), crb, masm, scratch.asValue(input.getValueKind()), input);
+                move((AMD64Kind) result.getPlatformKind(), crb, masm, result, scratch.asValue(result.getValueKind()));
+            }
+            // restore scratch register
+            move(backupKind, crb, masm, scratch.asValue(backupSlot.getValueKind()), backupSlot);
+        }
+    }
+
+    @Opcode("STACKMOVE")
+    public static final class AMD64PushPopStackMove extends AMD64LIRInstruction implements ValueMoveOp {
+        public static final LIRInstructionClass<AMD64PushPopStackMove> TYPE = LIRInstructionClass.create(AMD64PushPopStackMove.class);
+
+        @Def({STACK}) protected AllocatableValue result;
+        @Use({STACK, HINT}) protected AllocatableValue input;
+        private final OperandSize size;
+
+        public AMD64PushPopStackMove(OperandSize size, AllocatableValue result, AllocatableValue input) {
+            super(TYPE);
+            this.result = result;
+            this.input = input;
+            this.size = size;
+        }
+
+        @Override
+        public AllocatableValue getInput() {
+            return input;
+        }
+
+        @Override
+        public AllocatableValue getResult() {
+            return result;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            AMD64MOp.PUSH.emit(masm, size, (AMD64Address) crb.asAddress(input));
+            AMD64MOp.POP.emit(masm, size, (AMD64Address) crb.asAddress(result));
+        }
+    }
+
+    public static final class LeaOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<LeaOp> TYPE = LIRInstructionClass.create(LeaOp.class);
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address;
+
+        public LeaOp(AllocatableValue result, AMD64AddressValue address) {
+            super(TYPE);
+            this.result = result;
+            this.address = address;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            masm.leaq(asRegister(result, AMD64Kind.QWORD), address.toAddress());
+        }
+    }
+
+    public static final class LeaDataOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<LeaDataOp> TYPE = LIRInstructionClass.create(LeaDataOp.class);
+
+        @Def({REG}) protected AllocatableValue result;
+        private final DataPointerConstant data;
+
+        public LeaDataOp(AllocatableValue result, DataPointerConstant data) {
+            super(TYPE);
+            this.result = result;
+            this.data = data;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            masm.leaq(asRegister(result), (AMD64Address) crb.recordDataReferenceInCode(data));
+        }
+    }
+
+    public static final class StackLeaOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<StackLeaOp> TYPE = LIRInstructionClass.create(StackLeaOp.class);
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({STACK, UNINITIALIZED}) protected AllocatableValue slot;
+
+        public StackLeaOp(AllocatableValue result, AllocatableValue slot) {
+            super(TYPE);
+            this.result = result;
+            this.slot = slot;
+            assert slot instanceof VirtualStackSlot || slot instanceof StackSlot;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            masm.leaq(asRegister(result, AMD64Kind.QWORD), (AMD64Address) crb.asAddress(slot));
+        }
+    }
+
+    public static final class MembarOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<MembarOp> TYPE = LIRInstructionClass.create(MembarOp.class);
+
+        private final int barriers;
+
+        public MembarOp(final int barriers) {
+            super(TYPE);
+            this.barriers = barriers;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            masm.membar(barriers);
+        }
+    }
+
+    public static final class NullCheckOp extends AMD64LIRInstruction implements NullCheck {
+        public static final LIRInstructionClass<NullCheckOp> TYPE = LIRInstructionClass.create(NullCheckOp.class);
+
+        @Use({COMPOSITE}) protected AMD64AddressValue address;
+        @State protected LIRFrameState state;
+
+        public NullCheckOp(AMD64AddressValue address, LIRFrameState state) {
+            super(TYPE);
+            this.address = address;
+            this.state = state;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            crb.recordImplicitException(masm.position(), state);
+            masm.nullCheck(address.toAddress());
+        }
+
+        @Override
+        public Value getCheckedValue() {
+            return address.base;
+        }
+
+        @Override
+        public LIRFrameState getState() {
+            return state;
+        }
+    }
+
+    @Opcode("CAS")
+    public static final class CompareAndSwapOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
+
+        private final AMD64Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Use({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue cmpValue;
+        @Use protected AllocatableValue newValue;
+
+        public CompareAndSwapOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            super(TYPE);
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
+
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case DWORD:
+                    masm.cmpxchgl(asRegister(newValue), address.toAddress());
+                    break;
+                case QWORD:
+                    masm.cmpxchgq(asRegister(newValue), address.toAddress());
+                    break;
+                default:
+                    throw GraalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_ADD")
+    public static final class AtomicReadAndAddOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<AtomicReadAndAddOp> TYPE = LIRInstructionClass.create(AtomicReadAndAddOp.class);
+
+        private final AMD64Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue delta;
+
+        public AtomicReadAndAddOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue delta) {
+            super(TYPE);
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.delta = delta;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, delta);
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case DWORD:
+                    masm.xaddl(address.toAddress(), asRegister(result));
+                    break;
+                case QWORD:
+                    masm.xaddq(address.toAddress(), asRegister(result));
+                    break;
+                default:
+                    throw GraalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Opcode("ATOMIC_READ_AND_WRITE")
+    public static final class AtomicReadAndWriteOp extends AMD64LIRInstruction {
+        public static final LIRInstructionClass<AtomicReadAndWriteOp> TYPE = LIRInstructionClass.create(AtomicReadAndWriteOp.class);
+
+        private final AMD64Kind accessKind;
+
+        @Def protected AllocatableValue result;
+        @Alive({COMPOSITE}) protected AMD64AddressValue address;
+        @Use protected AllocatableValue newValue;
+
+        public AtomicReadAndWriteOp(AMD64Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue newValue) {
+            super(TYPE);
+            this.accessKind = accessKind;
+            this.result = result;
+            this.address = address;
+            this.newValue = newValue;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            move(accessKind, crb, masm, result, newValue);
+            switch (accessKind) {
+                case DWORD:
+                    masm.xchgl(asRegister(result), address.toAddress());
+                    break;
+                case QWORD:
+                    masm.xchgq(asRegister(result), address.toAddress());
+                    break;
+                default:
+                    throw GraalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static void move(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
+        move((AMD64Kind) result.getPlatformKind(), crb, masm, result, input);
+    }
+
+    public static void move(AMD64Kind moveKind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Value input) {
+        if (isRegister(input)) {
+            if (isRegister(result)) {
+                reg2reg(moveKind, masm, result, input);
+            } else if (isStackSlot(result)) {
+                reg2stack(moveKind, crb, masm, result, asRegister(input));
+            } else {
+                throw GraalError.shouldNotReachHere();
+            }
+        } else if (isStackSlot(input)) {
+            if (isRegister(result)) {
+                stack2reg(moveKind, crb, masm, asRegister(result), input);
+            } else {
+                throw GraalError.shouldNotReachHere();
+            }
+        } else if (isJavaConstant(input)) {
+            if (isRegister(result)) {
+                const2reg(crb, masm, asRegister(result), asJavaConstant(input));
+            } else if (isStackSlot(result)) {
+                const2stack(crb, masm, result, asJavaConstant(input));
+            } else {
+                throw GraalError.shouldNotReachHere();
+            }
+        } else {
+            throw GraalError.shouldNotReachHere();
+        }
+    }
+
+    private static void reg2reg(AMD64Kind kind, AMD64MacroAssembler masm, Value result, Value input) {
+        if (asRegister(input).equals(asRegister(result))) {
+            return;
+        }
+        switch (kind) {
+            case BYTE:
+            case WORD:
+            case DWORD:
+                masm.movl(asRegister(result), asRegister(input));
+                break;
+            case QWORD:
+                masm.movq(asRegister(result), asRegister(input));
+                break;
+            case SINGLE:
+                masm.movflt(asRegister(result, AMD64Kind.SINGLE), asRegister(input, AMD64Kind.SINGLE));
+                break;
+            case DOUBLE:
+                masm.movdbl(asRegister(result, AMD64Kind.DOUBLE), asRegister(input, AMD64Kind.DOUBLE));
+                break;
+            default:
+                throw GraalError.shouldNotReachHere("kind=" + kind);
+        }
+    }
+
+    public static void reg2stack(AMD64Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, Register input) {
+        AMD64Address dest = (AMD64Address) crb.asAddress(result);
+        switch (kind) {
+            case BYTE:
+                masm.movb(dest, input);
+                break;
+            case WORD:
+                masm.movw(dest, input);
+                break;
+            case DWORD:
+                masm.movl(dest, input);
+                break;
+            case QWORD:
+                masm.movq(dest, input);
+                break;
+            case SINGLE:
+                masm.movflt(dest, input);
+                break;
+            case DOUBLE:
+                masm.movsd(dest, input);
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+    }
+
+    public static void stack2reg(AMD64Kind kind, CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, Value input) {
+        AMD64Address src = (AMD64Address) crb.asAddress(input);
+        switch (kind) {
+            case BYTE:
+                masm.movsbl(result, src);
+                break;
+            case WORD:
+                masm.movswl(result, src);
+                break;
+            case DWORD:
+                masm.movl(result, src);
+                break;
+            case QWORD:
+                masm.movq(result, src);
+                break;
+            case SINGLE:
+                masm.movflt(result, src);
+                break;
+            case DOUBLE:
+                masm.movdbl(result, src);
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+    }
+
+    public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input) {
+        /*
+         * Note: we use the kind of the input operand (and not the kind of the result operand)
+         * because they don't match in all cases. For example, an object constant can be loaded to a
+         * long register when unsafe casts occurred (e.g., for a write barrier where arithmetic
+         * operations are then performed on the pointer).
+         */
+        switch (input.getJavaKind().getStackKind()) {
+            case Int:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                masm.movl(result, input.asInt());
+
+                break;
+            case Long:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                if (input.asLong() == (int) input.asLong()) {
+                    // Sign extended to long
+                    masm.movslq(result, (int) input.asLong());
+                } else if ((input.asLong() & 0xFFFFFFFFL) == input.asLong()) {
+                    // Zero extended to long
+                    masm.movl(result, (int) input.asLong());
+                } else {
+                    masm.movq(result, input.asLong());
+                }
+                break;
+            case Float:
+                // This is *not* the same as 'constant == 0.0f' in the case where constant is -0.0f
+                if (Float.floatToRawIntBits(input.asFloat()) == Float.floatToRawIntBits(0.0f)) {
+                    masm.xorps(result, result);
+                } else {
+                    masm.movflt(result, (AMD64Address) crb.asFloatConstRef(input));
+                }
+                break;
+            case Double:
+                // This is *not* the same as 'constant == 0.0d' in the case where constant is -0.0d
+                if (Double.doubleToRawLongBits(input.asDouble()) == Double.doubleToRawLongBits(0.0d)) {
+                    masm.xorpd(result, result);
+                } else {
+                    masm.movdbl(result, (AMD64Address) crb.asDoubleConstRef(input));
+                }
+                break;
+            case Object:
+                // Do not optimize with an XOR as this instruction may be between
+                // a CMP and a Jcc in which case the XOR will modify the condition
+                // flags and interfere with the Jcc.
+                if (input.isNull()) {
+                    masm.movq(result, 0x0L);
+                } else if (crb.target.inlineObjects) {
+                    crb.recordInlineDataInCode(input);
+                    masm.movq(result, 0xDEADDEADDEADDEADL);
+                } else {
+                    masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
+                }
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+    }
+
+    public static boolean canMoveConst2Stack(JavaConstant input) {
+        switch (input.getJavaKind().getStackKind()) {
+            case Int:
+                break;
+            case Long:
+                break;
+            case Float:
+                break;
+            case Double:
+                break;
+            case Object:
+                if (input.isNull()) {
+                    return true;
+                } else {
+                    return false;
+                }
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    public static void const2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, JavaConstant input) {
+        AMD64Address dest = (AMD64Address) crb.asAddress(result);
+        final long imm;
+        switch (input.getJavaKind().getStackKind()) {
+            case Int:
+                imm = input.asInt();
+                break;
+            case Long:
+                imm = input.asLong();
+                break;
+            case Float:
+                imm = floatToRawIntBits(input.asFloat());
+                break;
+            case Double:
+                imm = doubleToRawLongBits(input.asDouble());
+                break;
+            case Object:
+                if (input.isNull()) {
+                    imm = 0;
+                } else {
+                    throw GraalError.shouldNotReachHere("Non-null object constants must be in register");
+                }
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+
+        switch ((AMD64Kind) result.getPlatformKind()) {
+            case BYTE:
+                assert NumUtil.isByte(imm) : "Is not in byte range: " + imm;
+                AMD64MIOp.MOVB.emit(masm, OperandSize.BYTE, dest, (int) imm);
+                break;
+            case WORD:
+                assert NumUtil.isShort(imm) : "Is not in short range: " + imm;
+                AMD64MIOp.MOV.emit(masm, OperandSize.WORD, dest, (int) imm);
+                break;
+            case DWORD:
+            case SINGLE:
+                assert NumUtil.isInt(imm) : "Is not in int range: " + imm;
+                masm.movl(dest, (int) imm);
+                break;
+            case QWORD:
+            case DOUBLE:
+                masm.movlong(dest, imm);
+                break;
+            default:
+                throw GraalError.shouldNotReachHere("Unknown result Kind: " + result.getPlatformKind());
+        }
+    }
+}