graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java
Print this page
rev 8661 : Graal PTX enhancements
rev 8662 : [mq]: ptx_switch
rev 8663 : [mq]: ptx_lookup_switch
*** 26,64 ****
import static com.oracle.graal.api.code.ValueUtil.*;
import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
import static com.oracle.graal.lir.ptx.PTXCompare.*;
! import com.oracle.graal.api.code.*;
! import com.oracle.graal.api.meta.*;
! import com.oracle.graal.asm.*;
! import com.oracle.graal.compiler.gen.*;
! import com.oracle.graal.compiler.target.*;
! import com.oracle.graal.graph.*;
! import com.oracle.graal.lir.*;
import com.oracle.graal.lir.StandardOp.JumpOp;
! import com.oracle.graal.lir.ptx.*;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
! import com.oracle.graal.nodes.*;
! import com.oracle.graal.nodes.calc.*;
! import com.oracle.graal.nodes.java.*;
/**
* This class implements the PTX specific portion of the LIR generator.
*/
public class PTXLIRGenerator extends LIRGenerator {
public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
@Override
public LIRInstruction createMove(Value result, Value input) {
throw new InternalError("NYI");
--- 26,94 ----
import static com.oracle.graal.api.code.ValueUtil.*;
import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
import static com.oracle.graal.lir.ptx.PTXCompare.*;
! import com.oracle.graal.api.code.AllocatableValue;
! import com.oracle.graal.api.code.CodeCacheProvider;
! import com.oracle.graal.api.code.DeoptimizationAction;
! import com.oracle.graal.api.code.RuntimeCallTarget;
! import com.oracle.graal.api.code.StackSlot;
! import com.oracle.graal.api.code.TargetDescription;
! import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor;
! import com.oracle.graal.api.meta.Constant;
! import com.oracle.graal.api.meta.DeoptimizationReason;
! import com.oracle.graal.api.meta.Kind;
! import com.oracle.graal.api.meta.ResolvedJavaMethod;
! import com.oracle.graal.api.meta.Value;
! import com.oracle.graal.asm.NumUtil;
! import com.oracle.graal.compiler.gen.LIRGenerator;
! import com.oracle.graal.compiler.target.LIRGenLowerable;
! import com.oracle.graal.graph.GraalInternalError;
! import com.oracle.graal.lir.FrameMap;
! import com.oracle.graal.lir.LIR;
! import com.oracle.graal.lir.LIRFrameState;
! import com.oracle.graal.lir.LIRInstruction;
! import com.oracle.graal.lir.LIRValueUtil;
! import com.oracle.graal.lir.LabelRef;
import com.oracle.graal.lir.StandardOp.JumpOp;
! import com.oracle.graal.lir.Variable;
! import com.oracle.graal.lir.ptx.PTXAddressValue;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg;
import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack;
import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp;
+ import com.oracle.graal.lir.ptx.PTXBitManipulationOp;
import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
+ import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
+ import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
+ import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
+ import com.oracle.graal.lir.ptx.PTXControlFlow.TableSwitchOp;
import com.oracle.graal.lir.ptx.PTXMove.LoadOp;
import com.oracle.graal.lir.ptx.PTXMove.MoveFromRegOp;
import com.oracle.graal.lir.ptx.PTXMove.MoveToRegOp;
import com.oracle.graal.lir.ptx.PTXMove.StoreOp;
! import com.oracle.graal.nodes.BreakpointNode;
! import com.oracle.graal.nodes.DirectCallTargetNode;
! import com.oracle.graal.nodes.IndirectCallTargetNode;
! import com.oracle.graal.nodes.SafepointNode;
! import com.oracle.graal.nodes.StructuredGraph;
! import com.oracle.graal.nodes.ValueNode;
! import com.oracle.graal.nodes.calc.Condition;
! import com.oracle.graal.nodes.calc.ConvertNode;
! import com.oracle.graal.nodes.java.CompareAndSwapNode;
/**
* This class implements the PTX specific portion of the LIR generator.
*/
public class PTXLIRGenerator extends LIRGenerator {
+ public static final Descriptor ARITHMETIC_FREM = new Descriptor("arithmeticFrem", false, float.class, float.class, float.class);
+ public static final Descriptor ARITHMETIC_DREM = new Descriptor("arithmeticDrem", false, double.class, double.class, double.class);
+
public static class PTXSpillMoveFactory implements LIR.SpillMoveFactory {
@Override
public LIRInstruction createMove(Value result, Value input) {
throw new InternalError("NYI");
*** 188,202 ****
--- 218,245 ----
switch (left.getKind().getStackKind()) {
case Int:
append(new CompareOp(ICMP, cond, left, right));
append(new BranchOp(cond, label));
break;
+ case Long:
+ append(new CompareOp(LCMP, cond, left, right));
+ append(new BranchOp(cond, label));
+ break;
+ case Float:
+ append(new CompareOp(FCMP, cond, left, right));
+ append(new BranchOp(cond, label));
+ break;
+ case Double:
+ append(new CompareOp(DCMP, cond, left, right));
+ append(new BranchOp(cond, label));
+ break;
case Object:
append(new CompareOp(ACMP, cond, left, right));
append(new BranchOp(cond, label));
break;
default:
+ System.err.println("missing: " + left.getKind());
throw GraalInternalError.shouldNotReachHere("" + left.getKind());
}
}
@Override
*** 209,219 ****
throw new InternalError("NYI");
}
@Override
public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
! throw new InternalError("NYI");
}
@Override
public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
throw new InternalError("NYI");
--- 252,322 ----
throw new InternalError("NYI");
}
@Override
public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
! boolean mirrored = emitCompare(cond, left, right);
! Condition finalCondition = mirrored ? cond.mirror() : cond;
!
! Variable result = newVariable(trueValue.getKind());
! switch (left.getKind().getStackKind()) {
! case Int:
! case Long:
! case Object:
! append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
! break;
! case Float:
! case Double:
! append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind());
! }
! return result;
! }
!
! /**
! * This method emits the compare instruction, and may reorder the operands. It returns true if
! * it did so.
! *
! * @param a the left operand of the comparison
! * @param b the right operand of the comparison
! * @return true if the left and right operands were switched, false otherwise
! */
! private boolean emitCompare(Condition cond, Value a, Value b) {
! Variable left;
! Value right;
! boolean mirrored;
! if (LIRValueUtil.isVariable(b)) {
! left = load(b);
! right = loadNonConst(a);
! mirrored = true;
! } else {
! left = load(a);
! right = loadNonConst(b);
! mirrored = false;
! }
! switch (left.getKind().getStackKind()) {
! case Int:
! append(new CompareOp(ICMP, cond, left, right));
! break;
! case Long:
! append(new CompareOp(LCMP, cond, left, right));
! break;
! case Object:
! append(new CompareOp(ACMP, cond, left, right));
! break;
! case Float:
! append(new CompareOp(FCMP, cond, left, right));
! break;
! case Double:
! append(new CompareOp(DCMP, cond, left, right));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere();
! }
! return mirrored;
}
@Override
public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
throw new InternalError("NYI");
*** 224,233 ****
--- 327,342 ----
Variable result = newVariable(input.getKind());
switch (input.getKind()) {
case Int:
append(new Op1Stack(INEG, result, input));
break;
+ case Float:
+ append(new Op1Stack(FNEG, result, input));
+ break;
+ case Double:
+ append(new Op1Stack(DNEG, result, input));
+ break;
default:
throw GraalInternalError.shouldNotReachHere();
}
return result;
}
*** 237,246 ****
--- 346,364 ----
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Stack(IADD, result, a, loadNonConst(b)));
break;
+ case Long:
+ append(new Op2Stack(LADD, result, a, loadNonConst(b)));
+ break;
+ case Float:
+ append(new Op2Stack(FADD, result, a, loadNonConst(b)));
+ break;
+ case Double:
+ append(new Op2Stack(DADD, result, a, loadNonConst(b)));
+ break;
default:
throw GraalInternalError.shouldNotReachHere();
}
return result;
}
*** 250,261 ****
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
break;
default:
! throw GraalInternalError.shouldNotReachHere();
}
return result;
}
@Override
--- 368,388 ----
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Stack(ISUB, result, a, loadNonConst(b)));
break;
+ case Long:
+ append(new Op2Stack(LSUB, result, a, loadNonConst(b)));
+ break;
+ case Float:
+ append(new Op2Stack(FSUB, result, a, loadNonConst(b)));
+ break;
+ case Double:
+ append(new Op2Stack(DSUB, result, a, loadNonConst(b)));
+ break;
default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
}
return result;
}
@Override
*** 263,274 ****
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
break;
default:
! throw GraalInternalError.shouldNotReachHere();
}
return result;
}
@Override
--- 390,410 ----
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Reg(IMUL, result, a, loadNonConst(b)));
break;
+ case Long:
+ append(new Op2Reg(LMUL, result, a, loadNonConst(b)));
+ break;
+ case Float:
+ append(new Op2Stack(FMUL, result, a, loadNonConst(b)));
+ break;
+ case Double:
+ append(new Op2Stack(DMUL, result, a, loadNonConst(b)));
+ break;
default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
}
return result;
}
@Override
*** 277,292 ****
return false;
}
@Override
public Value emitDiv(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Value emitRem(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Variable emitUDiv(Value a, Value b) {
throw new InternalError("NYI");
--- 413,467 ----
return false;
}
@Override
public Value emitDiv(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Reg(IDIV, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Reg(LDIV, result, a, loadNonConst(b)));
! break;
! case Float:
! append(new Op2Stack(FDIV, result, a, loadNonConst(b)));
! break;
! case Double:
! append(new Op2Stack(DDIV, result, a, loadNonConst(b)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
! }
! return result;
}
@Override
public Value emitRem(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Reg(IREM, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Reg(LREM, result, a, loadNonConst(b)));
! break;
! /*
! * not correct - these need to call the PTX double-precision remainder() function
! case Float: {
! RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM);
! return emitCall(stub, stub.getCallingConvention(), false, a, b);
! }
! case Double: {
! RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM);
! return emitCall(stub, stub.getCallingConvention(), false, a, b);
! }
! */
! default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
! }
! return result;
}
@Override
public Variable emitUDiv(Value a, Value b) {
throw new InternalError("NYI");
*** 302,353 ****
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Stack(IAND, result, a, loadNonConst(b)));
break;
default:
! throw GraalInternalError.shouldNotReachHere();
}
return result;
}
@Override
public Variable emitOr(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Variable emitXor(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Variable emitShl(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Variable emitShr(Value a, Value b) {
! throw new InternalError("NYI");
}
@Override
public Variable emitUShr(Value a, Value b) {
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new ShiftOp(IUSHR, result, a, b));
break;
default:
GraalInternalError.shouldNotReachHere();
}
return result;
}
@Override
public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
! throw new InternalError("NYI");
}
@Override
public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
append(new ReturnOp(Value.ILLEGAL));
--- 477,648 ----
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new Op2Stack(IAND, result, a, loadNonConst(b)));
break;
+ case Long:
+ append(new Op2Stack(LAND, result, a, loadNonConst(b)));
+ break;
+
default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
}
return result;
}
@Override
public Variable emitOr(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Stack(IOR, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Stack(LOR, result, a, loadNonConst(b)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere("missing: " + a.getKind());
! }
! return result;
}
@Override
public Variable emitXor(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Stack(IXOR, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Stack(LXOR, result, a, loadNonConst(b)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere();
! }
! return result;
}
@Override
public Variable emitShl(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Stack(LSHL, result, a, loadNonConst(b)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere();
! }
! return result;
}
@Override
public Variable emitShr(Value a, Value b) {
! Variable result = newVariable(a.getKind());
! switch (a.getKind()) {
! case Int:
! append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
! break;
! case Long:
! append(new Op2Stack(LSHR, result, a, loadNonConst(b)));
! break;
! default:
! throw GraalInternalError.shouldNotReachHere();
! }
! return result;
}
@Override
public Variable emitUShr(Value a, Value b) {
Variable result = newVariable(a.getKind());
switch (a.getKind()) {
case Int:
append(new ShiftOp(IUSHR, result, a, b));
break;
+ case Long:
+ append(new ShiftOp(LUSHR, result, a, b));
+ break;
default:
GraalInternalError.shouldNotReachHere();
}
return result;
}
@Override
public Variable emitConvert(ConvertNode.Op opcode, Value inputVal) {
! Variable input = load(inputVal);
! Variable result = newVariable(opcode.to);
! switch (opcode) {
! case I2L:
! append(new Unary2Op(I2L, result, input));
! break;
! case L2I:
! append(new Unary1Op(L2I, result, input));
! break;
! case I2B:
! append(new Unary2Op(I2B, result, input));
! break;
! case I2C:
! append(new Unary1Op(I2C, result, input));
! break;
! case I2S:
! append(new Unary2Op(I2S, result, input));
! break;
! case F2D:
! append(new Unary2Op(F2D, result, input));
! break;
! case D2F:
! append(new Unary2Op(D2F, result, input));
! break;
! case I2F:
! append(new Unary2Op(I2F, result, input));
! break;
! case I2D:
! append(new Unary2Op(I2D, result, input));
! break;
! case F2I:
! append(new Unary2Op(F2I, result, input));
! break;
! case D2I:
! append(new Unary2Op(D2I, result, input));
! break;
! case L2F:
! append(new Unary2Op(L2F, result, input));
! break;
! case L2D:
! append(new Unary2Op(L2D, result, input));
! break;
! case F2L:
! append(new Unary2Op(F2L, result, input));
! break;
! case D2L:
! append(new Unary2Op(D2L, result, input));
! break;
! case MOV_I2F:
! append(new Unary2Op(MOV_I2F, result, input));
! break;
! case MOV_L2D:
! append(new Unary2Op(MOV_L2D, result, input));
! break;
! case MOV_F2I:
! append(new Unary2Op(MOV_F2I, result, input));
! break;
! case MOV_D2L:
! append(new Unary2Op(MOV_D2L, result, input));
! break;
! case UNSIGNED_I2L:
! // Instructions that move or generate 32-bit register values also set the upper 32
! // bits of the register to zero.
! // Consequently, there is no need for a special zero-extension move.
! emitMove(result, input);
! break;
! default:
! throw GraalInternalError.shouldNotReachHere();
! }
! return result;
}
@Override
public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) {
append(new ReturnOp(Value.ILLEGAL));
*** 432,452 ****
append(new ReturnOp(input));
}
@Override
protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
! throw new InternalError("NYI");
}
@Override
protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
throw new InternalError("NYI");
}
@Override
protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
! throw new InternalError("NYI");
}
@Override
public void visitCompareAndSwap(CompareAndSwapNode node) {
throw new InternalError("NYI");
--- 727,757 ----
append(new ReturnOp(input));
}
@Override
protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
! // Making a copy of the switch value is necessary because jump table destroys the input
! // value
! if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
! append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
! } else {
! assert key.getKind() == Kind.Object : key.getKind();
! append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
! }
}
@Override
protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) {
throw new InternalError("NYI");
}
@Override
protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
! // Making a copy of the switch value is necessary because jump table destroys the input
! // value
! Variable tmp = emitMove(key);
! append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
}
@Override
public void visitCompareAndSwap(CompareAndSwapNode node) {
throw new InternalError("NYI");
*** 457,473 ****
throw new InternalError("NYI");
}
@Override
public void visitSafepointNode(SafepointNode i) {
throw new InternalError("NYI");
}
@Override
public void emitUnwind(Value operand) {
! // TODO Auto-generated method stub
!
}
@Override
public void emitNullCheck(ValueNode v) {
throw new InternalError("NYI");
--- 762,779 ----
throw new InternalError("NYI");
}
@Override
public void visitSafepointNode(SafepointNode i) {
+ // LIRFrameState info = state();
+ // append(new PTXSafepointOp(info, runtime().config, this));
throw new InternalError("NYI");
}
@Override
public void emitUnwind(Value operand) {
! throw new InternalError("NYI");
}
@Override
public void emitNullCheck(ValueNode v) {
throw new InternalError("NYI");