changeset 15024:2ee777221036

Use high level CompressionNode in lowering of CompareAndSwapNode.
author Roland Schatz <roland.schatz@oracle.com>
date Tue, 08 Apr 2014 16:04:00 +0200
parents 652564fe42d5
children 292353f2645c
files graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java
diffstat 23 files changed, 133 insertions(+), 203 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java	Tue Apr 08 16:04:00 2014 +0200
@@ -288,10 +288,10 @@
      *            float compares.
      * @param isUnsignedCompare - flag specifying if this is a compare of unsigned values.
      */
-    public void emitCompare(Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
+    public void emitCompare(Kind compareKind, Value src0, Value src1, String condition, boolean unordered, boolean isUnsignedCompare) {
         // Formulate the prefix of the instruction.
         // if unordered is true, it should be ignored unless the src type is f32 or f64
-        String argType = getArgTypeFromKind(src1.getKind().getStackKind());
+        String argType = getArgTypeFromKind(compareKind);
         String unorderedPrefix = (argType.startsWith("f") && unordered ? "u" : "");
         String prefix = "cmp_" + condition + unorderedPrefix + "_b1_" + (isUnsignedCompare ? getArgTypeForceUnsigned(src1) : argType);
         // Generate a comment for debugging purposes
@@ -507,7 +507,7 @@
      */
     private void emitWithOptionalTestForNull(boolean testForNull, String mnemonic, Value result, Value... sources) {
         if (testForNull) {
-            emitCompare(result, Constant.forLong(0), "eq", false, true);
+            emitCompare(Kind.Long, result, Constant.forLong(0), "eq", false, true);
         }
         emitForceUnsigned(mnemonic, result, sources);
         if (testForNull) {
@@ -524,8 +524,8 @@
      * @param newValue the new value that will be written to the memory location if the cmpValue
      *            comparison matches
      */
-    public void emitAtomicCas(AllocatableValue result, HSAILAddress address, Value cmpValue, Value newValue) {
-        emitString(String.format("atomic_cas_global_b%d   %s, %s, %s, %s;", getArgSize(cmpValue), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(cmpValue),
+    public void emitAtomicCas(Kind accessKind, AllocatableValue result, HSAILAddress address, Value cmpValue, Value newValue) {
+        emitString(String.format("atomic_cas_global_b%d   %s, %s, %s, %s;", getArgSizeFromKind(accessKind), HSAIL.mapRegister(result), mapAddress(address), mapRegOrConstToString(cmpValue),
                         mapRegOrConstToString(newValue)));
     }
 
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Tue Apr 08 16:04:00 2014 +0200
@@ -93,7 +93,7 @@
 
     @Override
     public Variable emitMove(Value input) {
-        Variable result = newVariable(input.getKind());
+        Variable result = newVariable(input.getPlatformKind());
         emitMove(result, input);
         return result;
     }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Tue Apr 08 16:04:00 2014 +0200
@@ -908,4 +908,7 @@
         return (new Variable(kind, 0));
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitCompareAndSwap()");
+    }
 }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXNodeLIRBuilder.java	Tue Apr 08 16:04:00 2014 +0200
@@ -33,7 +33,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.ptx.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * This class implements the PTX specific portion of the LIR generator.
@@ -122,11 +121,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()");
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()");
     }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java	Tue Apr 08 16:04:00 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * This class implements the SPARC specific portion of the LIR generator.
@@ -47,11 +46,6 @@
     }
 
     @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address) {
-        throw new InternalError("NYI");
-    }
-
-    @Override
     public void visitBreakpointNode(BreakpointNode node) {
         JavaType[] sig = new JavaType[node.arguments().size()];
         for (int i = 0; i < sig.length; i++) {
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Apr 08 16:04:00 2014 +0200
@@ -45,6 +45,8 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
+import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.LoadOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
@@ -52,6 +54,7 @@
 import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp;
 import com.oracle.graal.lir.amd64.AMD64Move.StoreOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 
 /**
@@ -504,4 +507,20 @@
         }
     }
 
+    @Override
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        assert kind == expectedValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+
+        AMD64AddressValue addressValue = asAddressValue(address);
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expectedValue);
+        append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue)));
+
+        assert trueValue.getPlatformKind() == falseValue.getPlatformKind();
+        Variable result = newVariable(trueValue.getPlatformKind());
+        append(new CondMoveOp(result, Condition.EQ, asAllocatable(trueValue), falseValue));
+        return result;
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Tue Apr 08 16:04:00 2014 +0200
@@ -39,17 +39,13 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotLIRGenerator.SaveRbp;
-import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.amd64.*;
-import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
 import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 
 /**
@@ -198,32 +194,10 @@
 
         RegisterValue raxLocal = AMD64.rax.asValue(kind);
         gen.emitMove(raxLocal, expected);
-        append(new CompareAndSwapOp(raxLocal, address, raxLocal, newVal));
+        append(new CompareAndSwapOp(kind, raxLocal, address, raxLocal, newVal));
 
         Variable result = newVariable(x.getKind());
         gen.emitMove(result, raxLocal);
         setResult(x, result);
     }
-
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Value expected = gen.loadNonConst(operand(node.getExpectedValue()));
-        Variable newValue = gen.load(operand(node.getNewValue()));
-        AMD64AddressValue addressValue = getGen().asAddressValue(address);
-        RegisterValue raxRes = AMD64.rax.asValue(kind);
-        gen.emitMove(raxRes, expected);
-        if (getGen().config.useCompressedOops && node.isCompressible()) {
-            Variable scratch = newVariable(Kind.Long);
-            Register heapBaseReg = getGen().getProviders().getRegisters().getHeapBaseRegister();
-            append(new CompareAndSwapCompressedOp(raxRes, addressValue, raxRes, newValue, scratch, getGen().config.getOopEncoding(), heapBaseReg));
-        } else {
-            append(new CompareAndSwapOp(raxRes, addressValue, raxRes, newValue));
-        }
-        Variable result = newVariable(node.getKind());
-        append(new CondMoveOp(result, Condition.EQ, gen.load(Constant.TRUE), Constant.FALSE));
-        setResult(node, result);
-    }
-
 }
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Tue Apr 08 16:04:00 2014 +0200
@@ -552,7 +552,7 @@
             asm.emitLoadKernelArg(scratch64, asm.getDeoptInfoName(), "u64");
             asm.emitComment("// Check if a deopt has occurred and abort if true before doing any work");
             asm.emitLoadAcquire(scratch32, deoptInfoAddr);
-            asm.emitCompare(scratch32, Constant.forInt(0), "ne", false, false);
+            asm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "ne", false, false);
             asm.cbr(deoptInProgressLabel);
         }
 
@@ -680,7 +680,7 @@
             // scratch32 now holds next index to use
             // set error condition if no room in save area
             asm.emitComment("// assert room to save deopt");
-            asm.emitCompare(scratch32, Constant.forInt(maxDeoptIndex), "lt", false, false);
+            asm.emitCompare(Kind.Int, scratch32, Constant.forInt(maxDeoptIndex), "lt", false, false);
             asm.cbr("@L_StoreDeopt");
             // if assert fails, store a guaranteed negative workitemid in top level deopt occurred
             // flag
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerator.java	Tue Apr 08 16:04:00 2014 +0200
@@ -36,10 +36,12 @@
 import com.oracle.graal.hotspot.nodes.type.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.hsail.*;
+import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizeOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall1ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCall2ArgOp;
 import com.oracle.graal.lir.hsail.HSAILControlFlow.ForeignCallNoArgOp;
+import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadCompressedPointer;
 import com.oracle.graal.lir.hsail.HSAILMove.LoadOp;
 import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp;
@@ -48,6 +50,7 @@
 import com.oracle.graal.lir.hsail.HSAILMove.StoreConstantOp;
 import com.oracle.graal.lir.hsail.HSAILMove.StoreOp;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.phases.util.*;
 
@@ -179,6 +182,22 @@
         }
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        PlatformKind kind = newValue.getPlatformKind();
+        assert kind == expectedValue.getPlatformKind();
+        Kind memKind = getMemoryKind(kind);
+
+        HSAILAddressValue addressValue = asAddressValue(address);
+        Variable expected = emitMove(expectedValue);
+        Variable casResult = newVariable(kind);
+        append(new CompareAndSwapOp(memKind, casResult, addressValue, expected, asAllocatable(newValue)));
+
+        assert trueValue.getPlatformKind() == falseValue.getPlatformKind();
+        Variable nodeResult = newVariable(trueValue.getPlatformKind());
+        append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(memKind), casResult, expected, nodeResult, Condition.EQ, trueValue, falseValue));
+        return nodeResult;
+    }
+
     @Override
     public void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting) {
         emitDeoptimizeInner(actionAndReason, state(deopting), "emitDeoptimize");
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotNodeLIRBuilder.java	Tue Apr 08 16:04:00 2014 +0200
@@ -23,8 +23,6 @@
 
 package com.oracle.graal.hotspot.hsail;
 
-import sun.misc.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.hsail.*;
@@ -32,14 +30,7 @@
 import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.nodes.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.hsail.*;
-import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp;
-import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapCompressedOp;
-import com.oracle.graal.lir.hsail.HSAILMove.CompareAndSwapOp;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
 
 /**
  * The HotSpot specific portion of the HSAIL LIR generator.
@@ -50,45 +41,6 @@
         super(graph, lirGen);
     }
 
-    private HSAILHotSpotLIRGenerator getGen() {
-        return (HSAILHotSpotLIRGenerator) gen;
-    }
-
-    /**
-     * Appends either a {@link CompareAndSwapOp} or a {@link CompareAndSwapCompressedOp} depending
-     * on whether the memory location of a given {@link LoweredCompareAndSwapNode} contains a
-     * compressed oop. For the {@link CompareAndSwapCompressedOp} case, allocates a number of
-     * scratch registers. The result {@link #operand(ValueNode) operand} for {@code node} complies
-     * with the API for {@link Unsafe#compareAndSwapInt(Object, long, int, int)}.
-     *
-     * @param address the memory location targeted by the operation
-     */
-    @Override
-    public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        Kind kind = node.getNewValue().getKind();
-        assert kind == node.getExpectedValue().getKind();
-        Variable expected = gen.load(operand(node.getExpectedValue()));
-        Variable newValue = gen.load(operand(node.getNewValue()));
-        HSAILAddressValue addressValue = getGen().asAddressValue(address);
-        Variable casResult = newVariable(kind);
-        if (getGen().config.useCompressedOops && node.isCompressible()) {
-            // make 64-bit scratch variables for expected and new
-            Variable scratchExpected64 = newVariable(Kind.Long);
-            Variable scratchNewValue64 = newVariable(Kind.Long);
-            // make 32-bit scratch variables for expected and new and result
-            Variable scratchExpected32 = newVariable(Kind.Int);
-            Variable scratchNewValue32 = newVariable(Kind.Int);
-            Variable scratchCasResult32 = newVariable(Kind.Int);
-            append(new CompareAndSwapCompressedOp(casResult, addressValue, expected, newValue, scratchExpected64, scratchNewValue64, scratchExpected32, scratchNewValue32, scratchCasResult32,
-                            getGen().getNarrowOopBase(), getGen().getNarrowOopShift(), getGen().getLogMinObjectAlignment()));
-        } else {
-            append(new CompareAndSwapOp(casResult, addressValue, expected, newValue));
-        }
-        Variable nodeResult = newVariable(node.getKind());
-        append(new CondMoveOp(HSAILLIRGenerator.mapKindToCompareOp(kind), casResult, expected, nodeResult, Condition.EQ, Constant.INT_1, Constant.INT_0));
-        setResult(node, nodeResult);
-    }
-
     @Override
     protected void emitNode(ValueNode node) {
         if (node instanceof CurrentJavaThreadNode) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Tue Apr 08 16:04:00 2014 +0200
@@ -233,6 +233,10 @@
         }
     }
 
+    public Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        throw new InternalError("NYI");
+    }
+
     @Override
     public Value emitNot(Value input) {
         GraalInternalError.shouldNotReachHere("binary negation not implemented");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java	Tue Apr 08 16:04:00 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -370,12 +370,15 @@
         }
     }
 
-    private static void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
-        // Separate out GC barrier semantics
+    private void lowerCompareAndSwapNode(CompareAndSwapNode cas) {
         StructuredGraph graph = cas.graph();
-        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), cas.expected().getKind(), cas.displacement(), cas.offset(), graph, 1);
-        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas),
-                        cas.expected().getKind() == Kind.Object));
+        Kind valueKind = cas.getValueKind();
+        LocationNode location = IndexedLocationNode.create(cas.getLocationIdentity(), valueKind, cas.displacement(), cas.offset(), graph, 1);
+
+        ValueNode expectedValue = implicitStoreConvert(graph, valueKind, cas.expected(), true);
+        ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue(), true);
+
+        LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, expectedValue, newValue, getCompareAndSwapBarrier(cas), false));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Tue Apr 08 16:04:00 2014 +0200
@@ -65,7 +65,8 @@
                             (name().startsWith("S") && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) ||
                             (name().startsWith("I") && x.getKind() == Kind.Int && y.getKind() == Kind.Int) || (name().startsWith("L") && x.getKind() == Kind.Long && y.getKind() == Kind.Long) ||
                             (name().startsWith("A") && x.getKind() == Kind.Object && y.getKind() == Kind.Object) ||
-                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double);
+                            (name().startsWith("F") && x.getKind() == Kind.Float && y.getKind() == Kind.Float) || (name().startsWith("D") && x.getKind() == Kind.Double && y.getKind() == Kind.Double) : String.format(
+                            "%s(%s, %s)", opcode, x, y);
         }
     }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Tue Apr 08 16:04:00 2014 +0200
@@ -261,7 +261,7 @@
         @Use({REG, STACK, CONST}) protected Value falseValue;
         private final ConditionFlag condition;
 
-        public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
+        public CondMoveOp(Variable result, Condition condition, AllocatableValue trueValue, Value falseValue) {
             this.result = result;
             this.condition = intCond(condition);
             this.trueValue = trueValue;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Tue Apr 08 16:04:00 2014 +0200
@@ -396,12 +396,15 @@
     @Opcode("CAS")
     public static class CompareAndSwapOp extends AMD64LIRInstruction {
 
+        private final Kind accessKind;
+
         @Def protected AllocatableValue result;
         @Use({COMPOSITE}) protected AMD64AddressValue address;
         @Use protected AllocatableValue cmpValue;
         @Use protected AllocatableValue newValue;
 
-        public CompareAndSwapOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        public CompareAndSwapOp(Kind accessKind, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.accessKind = accessKind;
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -410,7 +413,22 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            compareAndSwap(crb, masm, result, address, cmpValue, newValue);
+            assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
+
+            if (crb.target.isMP) {
+                masm.lock();
+            }
+            switch (accessKind) {
+                case Int:
+                    masm.cmpxchgl(asRegister(newValue), address.toAddress());
+                    break;
+                case Long:
+                case Object:
+                    masm.cmpxchgq(asRegister(newValue), address.toAddress());
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
         }
     }
 
@@ -641,24 +659,4 @@
                 throw GraalInternalError.shouldNotReachHere();
         }
     }
-
-    protected static void compareAndSwap(CompilationResultBuilder crb, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue,
-                    AllocatableValue newValue) {
-        assert asRegister(cmpValue).equals(AMD64.rax) && asRegister(result).equals(AMD64.rax);
-
-        if (crb.target.isMP) {
-            masm.lock();
-        }
-        switch (cmpValue.getKind()) {
-            case Int:
-                masm.cmpxchgl(asRegister(newValue), address.toAddress());
-                break;
-            case Long:
-            case Object:
-                masm.cmpxchgq(asRegister(newValue), address.toAddress());
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
 }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java	Tue Apr 08 16:04:00 2014 +0200
@@ -35,11 +35,17 @@
  * Implementation of compare operations.
  */
 public enum HSAILCompare {
-    ICMP,
-    LCMP,
-    ACMP,
-    FCMP,
-    DCMP;
+    ICMP(Kind.Int),
+    LCMP(Kind.Long),
+    ACMP(Kind.Object),
+    FCMP(Kind.Float),
+    DCMP(Kind.Double);
+
+    public final Kind kind;
+
+    private HSAILCompare(Kind kind) {
+        this.kind = kind;
+    }
 
     public static class CompareOp extends HSAILLIRInstruction {
 
@@ -60,7 +66,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            emit(crb, masm, condition, x, y, z, unordered);
+            emit(crb, masm, opcode, condition, x, y, z, unordered);
         }
 
         @Override
@@ -72,8 +78,8 @@
     }
 
     @SuppressWarnings("unused")
-    public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, Condition condition, Value x, Value y, Value z, boolean unorderedIsTrue) {
-        emitCompare(masm, condition, x, y, unorderedIsTrue);
+    public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILCompare opcode, Condition condition, Value x, Value y, Value z, boolean unorderedIsTrue) {
+        masm.emitCompare(opcode.kind, x, y, conditionToString(condition), unorderedIsTrue, isUnsignedCompare(condition));
     }
 
     public static String conditionToString(Condition condition) {
@@ -110,9 +116,4 @@
                 return false;
         }
     }
-
-    private static void emitCompare(HSAILAssembler masm, Condition condition, Value src0, Value src1, boolean unordered) {
-        masm.emitCompare(src0, src1, conditionToString(condition), unordered, isUnsignedCompare(condition));
-    }
-
 }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Tue Apr 08 16:04:00 2014 +0200
@@ -101,7 +101,7 @@
                         case Int:
                         case Long:
                             // Generate cascading compare and branches for each case.
-                            masm.emitCompare(key, keyConstants[index], HSAILCompare.conditionToString(condition), false, false);
+                            masm.emitCompare(key.getKind(), key, keyConstants[index], HSAILCompare.conditionToString(condition), false, false);
                             masm.cbr(masm.nameOf(target));
                             break;
                         case Object:
@@ -286,10 +286,10 @@
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
             if (crb.isSuccessorEdge(trueDestination)) {
-                HSAILCompare.emit(crb, masm, condition.negate(), x, y, z, !unordered);
+                HSAILCompare.emit(crb, masm, opcode, condition.negate(), x, y, z, !unordered);
                 masm.cbr(masm.nameOf(falseDestination.label()));
             } else {
-                HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
+                HSAILCompare.emit(crb, masm, opcode, condition, x, y, z, unordered);
                 masm.cbr(masm.nameOf(trueDestination.label()));
                 if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
@@ -320,7 +320,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, left, right, right, false);
+            HSAILCompare.emit(crb, masm, opcode, condition, left, right, right, false);
             cmove(masm, result, trueValue, falseValue);
         }
     }
@@ -336,7 +336,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            HSAILCompare.emit(crb, masm, condition, left, right, right, unorderedIsTrue);
+            HSAILCompare.emit(crb, masm, opcode, condition, left, right, right, unorderedIsTrue);
             cmove(masm, result, trueValue, falseValue);
         }
     }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java	Tue Apr 08 16:04:00 2014 +0200
@@ -414,12 +414,15 @@
     @Opcode("CAS")
     public static class CompareAndSwapOp extends HSAILLIRInstruction {
 
+        private final Kind accessKind;
+
         @Def protected AllocatableValue result;
         @Use({COMPOSITE}) protected HSAILAddressValue address;
         @Use protected AllocatableValue cmpValue;
         @Use protected AllocatableValue newValue;
 
-        public CompareAndSwapOp(AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+        public CompareAndSwapOp(Kind accessKind, AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) {
+            this.accessKind = accessKind;
             this.result = result;
             this.address = address;
             this.cmpValue = cmpValue;
@@ -428,54 +431,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            masm.emitAtomicCas(result, address.toAddress(), cmpValue, newValue);
-        }
-    }
-
-    @Opcode("CAS")
-    public static class CompareAndSwapCompressedOp extends CompareAndSwapOp {
-
-        @Temp({REG}) private AllocatableValue scratchCmpValue64;
-        @Temp({REG}) private AllocatableValue scratchNewValue64;
-        @Temp({REG}) private AllocatableValue scratchCmpValue32;
-        @Temp({REG}) private AllocatableValue scratchNewValue32;
-        @Temp({REG}) private AllocatableValue scratchCasResult32;
-        private final long base;
-        private final int shift;
-        private final int alignment;
-
-        public CompareAndSwapCompressedOp(AllocatableValue result, HSAILAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue, AllocatableValue scratchCmpValue64,
-                        AllocatableValue scratchNewValue64, AllocatableValue scratchCmpValue32, AllocatableValue scratchNewValue32, AllocatableValue scratchCasResult32, long base, int shift,
-                        int alignment) {
-            super(result, address, cmpValue, newValue);
-            this.scratchCmpValue64 = scratchCmpValue64;
-            this.scratchNewValue64 = scratchNewValue64;
-            this.scratchCmpValue32 = scratchCmpValue32;
-            this.scratchNewValue32 = scratchNewValue32;
-            this.scratchCasResult32 = scratchCasResult32;
-            this.base = base;
-            this.shift = shift;
-            this.alignment = alignment;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            // assume any encoded or decoded value could be null
-            boolean testForNull = true;
-            // set up scratch registers to be encoded versions
-            masm.emitMov(Kind.Long, scratchCmpValue64, cmpValue);
-            encodePointer(masm, scratchCmpValue64, base, shift, alignment, testForNull);
-            masm.emitMov(Kind.Long, scratchNewValue64, newValue);
-            encodePointer(masm, scratchNewValue64, base, shift, alignment, testForNull);
-            // get encoded versions into 32-bit registers
-            masm.emitConvertForceUnsigned(scratchCmpValue32, scratchCmpValue64);
-            masm.emitConvertForceUnsigned(scratchNewValue32, scratchNewValue64);
-            // finally do the cas
-            masm.emitAtomicCas(scratchCasResult32, address.toAddress(), scratchCmpValue32, scratchNewValue32);
-            // and convert the 32-bit CasResult back to 64-bit
-            masm.emitConvertForceUnsigned(result, scratchCasResult32);
-            // and decode/uncompress the 64-bit cas result
-            decodePointer(masm, result, base, shift, alignment, testForNull);
+            masm.emitAtomicCas(accessKind, result, address.toAddress(), cmpValue, newValue);
         }
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java	Tue Apr 08 16:04:00 2014 +0200
@@ -42,6 +42,8 @@
     @Input private ValueNode offset;
     @Input private ValueNode expected;
     @Input private ValueNode newValue;
+
+    private final Kind valueKind;
     private final int displacement;
 
     public ValueNode object() {
@@ -64,7 +66,11 @@
         return displacement;
     }
 
-    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue) {
+    public Kind getValueKind() {
+        return valueKind;
+    }
+
+    public CompareAndSwapNode(ValueNode object, int displacement, ValueNode offset, ValueNode expected, ValueNode newValue, Kind valueKind) {
         super(StampFactory.forKind(Kind.Boolean.getStackKind()));
         assert expected.stamp().isCompatible(newValue.stamp());
         this.object = object;
@@ -72,6 +78,7 @@
         this.expected = expected;
         this.newValue = newValue;
         this.displacement = displacement;
+        this.valueKind = valueKind;
     }
 
     @Override
@@ -86,17 +93,20 @@
 
     // specialized on value type until boxing/unboxing is sorted out in intrinsification
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, Object expected, Object newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
         return unsafe.compareAndSwapObject(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, long expected, long newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
         return unsafe.compareAndSwapLong(object, displacement + offset, expected, newValue);
     }
 
     @NodeIntrinsic
-    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue) {
+    public static boolean compareAndSwap(Object object, @ConstantNodeParameter int displacement, long offset, int expected, int newValue,
+                    @SuppressWarnings("unused") @ConstantNodeParameter Kind valueKind) {
         return unsafe.compareAndSwapInt(object, displacement + offset, expected, newValue);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Tue Apr 08 16:04:00 2014 +0200
@@ -79,7 +79,10 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object())));
+        assert getNewValue().stamp().isCompatible(getExpectedValue().stamp());
+        Value address = location().generateAddress(gen, gen.operand(object()));
+        Value result = gen.getLIRGeneratorTool().emitCompareAndSwap(address, gen.operand(getExpectedValue()), gen.operand(getNewValue()), Constant.INT_1, Constant.INT_0);
+        gen.setResult(this, result);
     }
 
     public MemoryCheckpoint asMemoryCheckpoint() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Tue Apr 08 16:04:00 2014 +0200
@@ -41,6 +41,8 @@
 
     void emitStore(PlatformKind kind, Value address, Value input, Access access);
 
+    Value emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue);
+
     void emitDeoptimize(Value actionAndReason, Value failedSpeculation, DeoptimizingNode deopting);
 
     Value emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/NodeLIRBuilderTool.java	Tue Apr 08 16:04:00 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
 
 public interface NodeLIRBuilderTool extends NodeMappableLIRBuilder {
 
@@ -50,8 +49,6 @@
 
     void visitLoopEnd(LoopEndNode i);
 
-    void visitCompareAndSwap(LoweredCompareAndSwapNode i, Value address);
-
     // These methods define the contract a runtime specific backend must provide.
 
     void visitSafepointNode(SafepointNode i);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Tue Apr 08 15:55:18 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsafeSubstitutions.java	Tue Apr 08 16:04:00 2014 +0200
@@ -42,17 +42,17 @@
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapObject(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, Object expected, Object x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Object);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapInt(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, int expected, int x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Int);
     }
 
     @MethodSubstitution(isStatic = false)
     public static boolean compareAndSwapLong(@SuppressWarnings("unused") final Object thisObj, Object o, long offset, long expected, long x) {
-        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x);
+        return CompareAndSwapNode.compareAndSwap(o, 0, offset, expected, x, Kind.Long);
     }
 
     @MethodSubstitution(isStatic = false)