# HG changeset patch # User Lukas Stadler # Date 1360075961 -3600 # Node ID 301cff1a99d12d16d573069fffeffc09eb018087 # Parent ac3579b4adc9d1d11c65fcf043f0a71bc5596b7e backend support for integer test operation diff -r ac3579b4adc9 -r 301cff1a99d1 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Feb 05 15:51:23 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Feb 05 15:52:41 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); diff -r ac3579b4adc9 -r 301cff1a99d1 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Feb 05 15:51:23 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Feb 05 15:52:41 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. diff -r ac3579b4adc9 -r 301cff1a99d1 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Feb 05 15:51:23 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Feb 05 15:52:41 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) { diff -r ac3579b4adc9 -r 301cff1a99d1 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java --- /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 15:52:41 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(); + } + } + } +}