changeset 7727:be7b98533b17

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 05 Feb 2013 16:39:45 +0100
parents f629d4a264c6 (diff) fec77d5cd187 (current diff)
children 77c86cf33685
files
diffstat 18 files changed, 354 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Tue Feb 05 16:39:45 2013 +0100
@@ -2863,6 +2863,12 @@
         emitArith(0x85, 0xC0, dst, src);
     }
 
+    public final void testq(Register dst, Address src) {
+        prefixq(src, dst);
+        emitByte(0x85);
+        emitOperandHelper(dst, src);
+    }
+
     public final void xaddq(Address dst, Register src) {
         prefixq(dst, src);
         emitByte(0x0F);
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Tue Feb 05 16:39:45 2013 +0100
@@ -229,7 +229,7 @@
     }
 
     @Override
-    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
+    public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.getKind().getStackKind()) {
@@ -248,7 +248,13 @@
     }
 
     @Override
-    public Variable emitCMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
+    public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) {
+        emitIntegerTest(left, right);
+        append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info));
+    }
+
+    @Override
+    public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
 
@@ -263,11 +269,29 @@
             case Double:
                 append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
                 break;
-
+            default:
+                throw GraalInternalError.shouldNotReachHere("" + left.getKind());
         }
         return result;
     }
 
+    @Override
+    public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
+        emitIntegerTest(left, right);
+        Variable result = newVariable(trueValue.getKind());
+        append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue)));
+        return result;
+    }
+
+    private void emitIntegerTest(Value a, Value b) {
+        assert a.getKind().getStackKind() == Kind.Int || a.getKind() == Kind.Long;
+        if (LIRValueUtil.isVariable(b)) {
+            append(new AMD64TestOp(load(b), loadNonConst(a)));
+        } else {
+            append(new AMD64TestOp(load(a), loadNonConst(b)));
+        }
+    }
+
     /**
      * This method emits the compare instruction, and may reorder the operands. It returns true if
      * it did so.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Tue Feb 05 16:39:45 2013 +0100
@@ -22,14 +22,29 @@
  */
 package com.oracle.graal.compiler.test;
 
+import static org.junit.Assert.*;
+
 import org.junit.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.phases.common.*;
 
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
+    private StructuredGraph getCanonicalizedGraph(String name) {
+        StructuredGraph graph = parse(name);
+        new CanonicalizerPhase(null, runtime(), null).apply(graph);
+        return graph;
+    }
+
+    private static ValueNode getResult(StructuredGraph graph) {
+        assertTrue(graph.start().next() instanceof ReturnNode);
+        ReturnNode ret = (ReturnNode) graph.start().next();
+        return ret.result();
+    }
+
     @Test
     public void testCanonicalComparison() {
         StructuredGraph referenceGraph = parse("referenceCanonicalComparison");
@@ -40,8 +55,7 @@
         Assumptions assumptions = new Assumptions(false);
         new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph);
         for (int i = 1; i < 4; i++) {
-            StructuredGraph graph = parse("canonicalCompare" + i);
-            new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+            StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
         }
     }
@@ -77,4 +91,78 @@
             return 1;
         }
     }
+
+    @Test
+    public void testIntegerTest() {
+        for (int i = 1; i <= 4; i++) {
+            StructuredGraph graph = getCanonicalizedGraph("integerTest" + i);
+
+            ValueNode result = getResult(graph);
+            assertTrue(result instanceof ConditionalNode);
+            ConditionalNode mat = (ConditionalNode) result;
+            assertTrue(mat.condition() instanceof IntegerTestNode);
+            IntegerTestNode test = (IntegerTestNode) mat.condition();
+            LocalNode local0 = graph.getLocal(0);
+            LocalNode local1 = graph.getLocal(1);
+            assertTrue((test.x() == local0 && test.y() == local1) || (test.x() == local1 && test.y() == local0));
+        }
+    }
+
+    public static boolean integerTest1(int x, int y) {
+        return (x & y) == 0;
+    }
+
+    public static boolean integerTest2(long x, long y) {
+        return 0 == (x & y);
+    }
+
+    public static boolean integerTest3(long x, long y) {
+        int c = 5;
+        return (c - 5) == (x & y);
+    }
+
+    public static boolean integerTest4(int x, int y) {
+        int c = 10;
+        return (x & y) == (10 - c);
+    }
+
+    @Test
+    public void testIntegerTestCanonicalization() {
+        ValueNode result = getResult(getCanonicalizedGraph("integerTestCanonicalization1"));
+        assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
+        result = getResult(getCanonicalizedGraph("integerTestCanonicalization2"));
+        assertTrue(result.isConstant() && result.asConstant().asLong() == 1);
+        result = getResult(getCanonicalizedGraph("integerTestCanonicalization3"));
+        assertTrue(result instanceof ConditionalNode);
+    }
+
+    public static int integerTestCanonicalization1(boolean b) {
+        int x = b ? 128 : 256;
+        if ((x & 8) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    public static int integerTestCanonicalization2(boolean b) {
+        int x = b ? 128 : 256;
+        int y = b ? 32 : 64;
+        if ((x & y) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    public static int integerTestCanonicalization3(boolean b) {
+        int x = b ? 128 : 64;
+        int y = b ? 32 : 64;
+        if ((x & y) == 0) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Tue Feb 05 16:39:45 2013 +0100
@@ -30,6 +30,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -184,8 +185,8 @@
     public void testInstanceOf() {
         ReturnNode returnNode = testEscapeAnalysis("testInstanceOfSnippet", null, false);
         ValueNode result = returnNode.result();
-        Assert.assertTrue(result instanceof MaterializeNode);
-        Assert.assertEquals(Constant.TRUE, ((MaterializeNode) result).condition().asConstant());
+        Assert.assertTrue(result instanceof ConditionalNode);
+        Assert.assertEquals(Constant.TRUE, ((ConditionalNode) result).condition().asConstant());
     }
 
     public boolean testInstanceOfSnippet() {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Tue Feb 05 16:39:45 2013 +0100
@@ -612,6 +612,8 @@
             emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info);
         } else if (node instanceof ConstantNode) {
             emitConstantBranch(((ConstantNode) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info);
+        } else if (node instanceof IntegerTestNode) {
+            emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
@@ -619,23 +621,34 @@
 
     private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (falseSuccessor != null) {
-            emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
+            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
             if (trueSuccessor != null) {
                 emitJump(trueSuccessor, null);
             }
         } else {
-            emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
+            emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info);
         }
     }
 
     public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         if (falseSuccessorBlock != null) {
-            emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
+            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
             if (trueSuccessorBlock != null) {
                 emitJump(trueSuccessorBlock, null);
             }
         } else {
-            emitBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
+            emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info);
+        }
+    }
+
+    public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
+        if (falseSuccessorBlock != null) {
+            emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info);
+            if (trueSuccessorBlock != null) {
+                emitJump(trueSuccessorBlock, null);
+            }
+        } else {
+            emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessorBlock, info);
         }
     }
 
@@ -655,33 +668,31 @@
 
     public Variable emitConditional(BooleanNode node, Value trueValue, Value falseValue) {
         if (node instanceof IsNullNode) {
-            return emitNullCheckConditional((IsNullNode) node, trueValue, falseValue);
+            IsNullNode isNullNode = (IsNullNode) node;
+            return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
         } else if (node instanceof CompareNode) {
-            return emitCompareConditional((CompareNode) node, trueValue, falseValue);
+            CompareNode compare = (CompareNode) node;
+            return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
         } else if (node instanceof ConstantNode) {
-            return emitConstantConditional(((ConstantNode) node).asConstant().asBoolean(), trueValue, falseValue);
+            ConstantNode constantNode = (ConstantNode) node;
+            return emitMove(constantNode.asConstant().asBoolean() ? trueValue : falseValue);
+        } else if (node instanceof IntegerTestNode) {
+            IntegerTestNode test = (IntegerTestNode) node;
+            return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
     }
 
-    private Variable emitNullCheckConditional(IsNullNode node, Value trueValue, Value falseValue) {
-        return emitCMove(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue);
-    }
-
-    private Variable emitConstantConditional(boolean value, Value trueValue, Value falseValue) {
-        return emitMove(value ? trueValue : falseValue);
-    }
-
-    private Variable emitCompareConditional(CompareNode compare, Value trueValue, Value falseValue) {
-        return emitCMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
-    }
-
     public abstract void emitJump(LabelRef label, LIRFrameState info);
 
-    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+    public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
+
+    public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info);
 
-    public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+    public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
+
+    public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue);
 
     @Override
     public void emitInvoke(Invoke x) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java	Tue Feb 05 16:39:45 2013 +0100
@@ -27,7 +27,7 @@
 
 import java.lang.reflect.*;
 
-import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution;
 import com.oracle.graal.word.*;
@@ -113,6 +113,6 @@
 
     @MethodSubstitution(isStatic = false)
     public static boolean isInstance(final Class<?> thisObj, Object obj) {
-        return !thisObj.isPrimitive() && MaterializeNode.isInstance(thisObj, obj);
+        return !thisObj.isPrimitive() && ConditionalNode.materializeIsInstance(thisObj, obj);
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Tue Feb 05 16:39:45 2013 +0100
@@ -708,7 +708,8 @@
         if (type instanceof ResolvedJavaType) {
             ResolvedJavaType resolvedType = (ResolvedJavaType) type;
             InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType));
-            frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode))));
+            ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph)));
+            frameState.ipush(append(conditional));
         } else {
             BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode());
             DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java	Tue Feb 05 16:39:45 2013 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.amd64;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.asm.*;
+
+//@formatter:off
+public class AMD64TestOp extends AMD64LIRInstruction {
+
+    @Use({REG}) protected Value x;
+    @Use({REG, STACK, CONST}) protected Value y;
+
+    public AMD64TestOp(Value x, Value y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+        emit(tasm, masm, x, y);
+    }
+
+    @Override
+    protected void verify() {
+        super.verify();
+        assert (x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (x.getKind() == Kind.Long && y.getKind() == Kind.Long) : x + " " + y;
+    }
+
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value x, Value y) {
+        if (isRegister(y)) {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), asIntReg(y)); break;
+                case Long: masm.testq(asLongReg(x), asLongReg(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        } else if (isConstant(y)) {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), tasm.asIntConst(y)); break;
+                case Long: masm.testq(asLongReg(x), tasm.asIntConst(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        } else {
+            switch (x.getKind()) {
+                case Int: masm.testl(asIntReg(x), tasm.asIntAddr(y)); break;
+                case Long: masm.testq(asLongReg(x), tasm.asLongAddr(y)); break;
+                default: throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 05 16:39:45 2013 +0100
@@ -191,7 +191,7 @@
                             return false;
                         }
                         if (trueValue.isConstant() && falseValue.isConstant()) {
-                            MaterializeNode materialize = MaterializeNode.create(condition(), trueValue, falseValue);
+                            ConditionalNode materialize = graph().unique(new ConditionalNode(condition(), trueValue, falseValue));
                             ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize);
                             removeEmptyIf(tool);
                             return true;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java	Tue Feb 05 15:27:40 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, 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.nodes;
-
-import static com.oracle.graal.nodes.calc.CompareNode.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-
-public final class MaterializeNode extends ConditionalNode {
-
-    private MaterializeNode(Condition condition, ValueNode x, ValueNode y) {
-        this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph()));
-    }
-
-    private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
-        super(condition, trueValue, falseValue);
-    }
-
-    private MaterializeNode(ValueNode type, ValueNode object) {
-        super(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph()));
-    }
-
-    public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) {
-        Graph graph = condition.graph();
-        MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue);
-        return graph.unique(result);
-
-    }
-
-    public static MaterializeNode create(BooleanNode condition) {
-        return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph()));
-    }
-
-    @NodeIntrinsic
-    public static native boolean materialize(@ConstantNodeParameter Condition condition, int x, int y);
-
-    @NodeIntrinsic
-    public static native boolean materialize(@ConstantNodeParameter Condition condition, long x, long y);
-
-    @NodeIntrinsic
-    public static native boolean isInstance(Class mirror, Object object);
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 05 16:39:45 2013 +0100
@@ -22,15 +22,18 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import static com.oracle.graal.nodes.calc.CompareNode.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note
  * that these nodes are not built directly from the bytecode but are introduced by canonicalization.
  */
-public class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable {
+public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable {
 
     @Input private BooleanNode condition;
 
@@ -44,6 +47,11 @@
         this.condition = condition;
     }
 
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(x().stamp().meet(y().stamp()));
+    }
+
     public ValueNode trueValue() {
         return x();
     }
@@ -91,4 +99,21 @@
         ((StructuredGraph) graph()).replaceFloating(this, replacement);
         return replacement;
     }
+
+    private ConditionalNode(Condition condition, ValueNode x, ValueNode y) {
+        this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph()));
+    }
+
+    private ConditionalNode(ValueNode type, ValueNode object) {
+        this(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph()));
+    }
+
+    @NodeIntrinsic
+    public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, int x, int y);
+
+    @NodeIntrinsic
+    public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, long x, long y);
+
+    @NodeIntrinsic
+    public static native boolean materializeIsInstance(Class mirror, Object object);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Tue Feb 05 16:39:45 2013 +0100
@@ -74,6 +74,12 @@
         } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) {
             return ConstantNode.forBoolean(false, graph());
         }
+
+        if (x() instanceof AndNode && y().isConstant() && y().asConstant().asLong() == 0) {
+            return graph().unique(new IntegerTestNode(((AndNode) x()).x(), ((AndNode) x()).y()));
+        } else if (y() instanceof AndNode && x().isConstant() && x().asConstant().asLong() == 0) {
+            return graph().unique(new IntegerTestNode(((AndNode) y()).x(), ((AndNode) y()).y()));
+        }
         return super.canonical(tool);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Tue Feb 05 16:39:45 2013 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, 2011, 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.nodes.calc;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class IntegerTestNode extends BooleanNode implements Canonicalizable, LIRLowerable {
+
+    @Input private ValueNode x;
+    @Input private ValueNode y;
+
+    public ValueNode x() {
+        return x;
+    }
+
+    public ValueNode y() {
+        return y;
+    }
+
+    /**
+     * Constructs a new Test instruction.
+     * 
+     * @param x the instruction producing the first input to the instruction
+     * @param y the instruction that produces the second input to this instruction
+     */
+    public IntegerTestNode(ValueNode x, ValueNode y) {
+        super(StampFactory.condition());
+        assert (x == null && y == null) || x.kind() == y.kind();
+        this.x = x;
+        this.y = y;
+    }
+
+    @Override
+    public void generate(LIRGeneratorTool gen) {
+    }
+
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (x().isConstant() && y().isConstant()) {
+            return ConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph());
+        }
+        if ((x().integerStamp().mask() & y().integerStamp().mask()) == 0) {
+            return ConstantNode.forBoolean(true, graph());
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Tue Feb 05 16:39:45 2013 +0100
@@ -61,8 +61,8 @@
             lessComp = graph.unique(new IntegerLessThanNode(x(), y()));
         }
 
-        MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph));
-        MaterializeNode value = MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue);
+        ConditionalNode equalValue = graph.unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)));
+        ConditionalNode value = graph.unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph), equalValue));
 
         graph.replaceFloating(this, value);
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Tue Feb 05 16:39:45 2013 +0100
@@ -496,8 +496,8 @@
                 for (PhiNode phi : endNode.merge().phis()) {
                     int index = endNode.merge().phiPredecessorIndex(endNode);
                     ValueNode value = phi.valueAt(index);
-                    if (value instanceof MaterializeNode) {
-                        MaterializeNode materialize = (MaterializeNode) value;
+                    if (value instanceof ConditionalNode) {
+                        ConditionalNode materialize = (ConditionalNode) value;
                         BooleanNode compare = materialize.condition();
                         ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue());
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java	Tue Feb 05 16:39:45 2013 +0100
@@ -172,7 +172,7 @@
                 // Can simply use the phi result if the same materialized values are expected.
                 return result;
             } else {
-                return MaterializeNode.create(asCondition(trueValue), t, f);
+                return t.graph().unique(new ConditionalNode(asCondition(trueValue), t, f));
             }
         }
     }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java	Tue Feb 05 16:39:45 2013 +0100
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.snippets;
 
-import static com.oracle.graal.nodes.MaterializeNode.*;
+import static com.oracle.graal.nodes.calc.ConditionalNode.*;
 import static com.oracle.graal.nodes.calc.Condition.*;
 
 import com.oracle.graal.api.code.*;
@@ -38,12 +38,12 @@
 
     @MethodSubstitution
     public static boolean aboveThan(int a, int b) {
-        return materialize(BT, b, a);
+        return materializeCondition(BT, b, a);
     }
 
     @MethodSubstitution
     public static boolean aboveOrEqual(int a, int b) {
-        return !materialize(BT, a, b);
+        return !materializeCondition(BT, a, b);
     }
 
     /**
@@ -51,7 +51,7 @@
      */
     @MethodSubstitution
     public static boolean belowThan(int a, int b) {
-        return materialize(BT, a, b);
+        return materializeCondition(BT, a, b);
     }
 
     /**
@@ -59,7 +59,7 @@
      */
     @MethodSubstitution
     public static boolean belowOrEqual(int a, int b) {
-        return !materialize(BT, b, a);
+        return !materializeCondition(BT, b, a);
     }
 
     /**
@@ -67,7 +67,7 @@
      */
     @MethodSubstitution
     public static boolean aboveThan(long a, long b) {
-        return materialize(BT, b, a);
+        return materializeCondition(BT, b, a);
     }
 
     /**
@@ -75,7 +75,7 @@
      */
     @MethodSubstitution
     public static boolean aboveOrEqual(long a, long b) {
-        return !materialize(BT, a, b);
+        return !materializeCondition(BT, a, b);
     }
 
     /**
@@ -83,7 +83,7 @@
      */
     @MethodSubstitution
     public static boolean belowThan(long a, long b) {
-        return materialize(BT, a, b);
+        return materializeCondition(BT, a, b);
     }
 
     /**
@@ -91,7 +91,7 @@
      */
     @MethodSubstitution
     public static boolean belowOrEqual(long a, long b) {
-        return !materialize(BT, b, a);
+        return !materializeCondition(BT, b, a);
     }
 
     /**
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Feb 05 15:27:40 2013 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Tue Feb 05 16:39:45 2013 +0100
@@ -248,7 +248,7 @@
         } else {
             comparison = new IntegerLessThanNode(a, b);
         }
-        MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison));
+        ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph)));
 
         ValueNode op;
         if (condition.canonicalNegate()) {