mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-03 14:21:30 +00:00
ptx: add set.p instruction and related changes to predicate execution
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127577 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -31,7 +31,7 @@ namespace llvm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum Predicate {
|
enum Predicate {
|
||||||
PRED_IGNORE = 0,
|
PRED_NORMAL = 0,
|
||||||
PRED_NEGATE = 1
|
PRED_NEGATE = 1
|
||||||
};
|
};
|
||||||
} // namespace PTX
|
} // namespace PTX
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ printPredicateOperand(const MachineInstr *MI, raw_ostream &O) {
|
|||||||
|
|
||||||
DEBUG(dbgs() << "predicate: (" << reg << ", " << predOp << ")\n");
|
DEBUG(dbgs() << "predicate: (" << reg << ", " << predOp << ")\n");
|
||||||
|
|
||||||
if (reg && predOp != PTX::PRED_IGNORE) {
|
if (reg != PTX::NoRegister) {
|
||||||
O << '@';
|
O << '@';
|
||||||
if (predOp == PTX::PRED_NEGATE)
|
if (predOp == PTX::PRED_NEGATE)
|
||||||
O << '!';
|
O << '!';
|
||||||
|
|||||||
@@ -100,10 +100,7 @@ bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
|
|||||||
|
|
||||||
bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
|
bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
|
||||||
int i = MI->findFirstPredOperandIdx();
|
int i = MI->findFirstPredOperandIdx();
|
||||||
if (i == -1)
|
return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
|
||||||
llvm_unreachable("missing predicate operand");
|
|
||||||
return MI->getOperand(i).getReg() ||
|
|
||||||
MI->getOperand(i+1).getImm() != PTX::PRED_IGNORE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
|
bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
|
||||||
@@ -143,7 +140,29 @@ DefinesPredicate(MachineInstr *MI,
|
|||||||
// If the specified instruction defines any predicate or condition code
|
// If the specified instruction defines any predicate or condition code
|
||||||
// register(s) used for predication, returns true as well as the definition
|
// register(s) used for predication, returns true as well as the definition
|
||||||
// predicate(s) by reference.
|
// predicate(s) by reference.
|
||||||
|
|
||||||
|
switch (MI->getOpcode()) {
|
||||||
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
case PTX::SETPEQu32rr:
|
||||||
|
case PTX::SETPEQu32ri:
|
||||||
|
case PTX::SETPNEu32rr:
|
||||||
|
case PTX::SETPNEu32ri:
|
||||||
|
case PTX::SETPLTu32rr:
|
||||||
|
case PTX::SETPLTu32ri:
|
||||||
|
case PTX::SETPLEu32rr:
|
||||||
|
case PTX::SETPLEu32ri:
|
||||||
|
case PTX::SETPGTu32rr:
|
||||||
|
case PTX::SETPGTu32ri:
|
||||||
|
case PTX::SETPGEu32rr:
|
||||||
|
case PTX::SETPGEu32ri: {
|
||||||
|
const MachineOperand &MO = MI->getOperand(0);
|
||||||
|
assert(MO.isReg() && RI.getRegClass(MO.getReg()) == &PTX::PredsRegClass);
|
||||||
|
Pred.push_back(MO);
|
||||||
|
Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static helper routines
|
// static helper routines
|
||||||
@@ -151,8 +170,8 @@ DefinesPredicate(MachineInstr *MI,
|
|||||||
MachineSDNode *PTXInstrInfo::
|
MachineSDNode *PTXInstrInfo::
|
||||||
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
||||||
DebugLoc dl, EVT VT, SDValue Op1) {
|
DebugLoc dl, EVT VT, SDValue Op1) {
|
||||||
SDValue predReg = DAG->getRegister(0, MVT::i1);
|
SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
|
||||||
SDValue predOp = DAG->getTargetConstant(PTX::PRED_IGNORE, MVT::i1);
|
SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
|
||||||
SDValue ops[] = { Op1, predReg, predOp };
|
SDValue ops[] = { Op1, predReg, predOp };
|
||||||
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
|
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
|
||||||
}
|
}
|
||||||
@@ -160,8 +179,8 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
|||||||
MachineSDNode *PTXInstrInfo::
|
MachineSDNode *PTXInstrInfo::
|
||||||
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
||||||
DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
|
DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
|
||||||
SDValue predReg = DAG->getRegister(0, MVT::i1);
|
SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
|
||||||
SDValue predOp = DAG->getTargetConstant(PTX::PRED_IGNORE, MVT::i1);
|
SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
|
||||||
SDValue ops[] = { Op1, Op2, predReg, predOp };
|
SDValue ops[] = { Op1, Op2, predReg, predOp };
|
||||||
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
|
return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
|
||||||
}
|
}
|
||||||
@@ -169,6 +188,6 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
|
|||||||
void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
|
void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
|
||||||
if (MI->findFirstPredOperandIdx() == -1) {
|
if (MI->findFirstPredOperandIdx() == -1) {
|
||||||
MI->addOperand(MachineOperand::CreateReg(0, /*IsDef=*/false));
|
MI->addOperand(MachineOperand::CreateReg(0, /*IsDef=*/false));
|
||||||
MI->addOperand(MachineOperand::CreateImm(PTX::PRED_IGNORE));
|
MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,6 +269,18 @@ multiclass INT3ntnc<string opcstr, SDNode opnode> {
|
|||||||
[(set RRegu32:$d, (opnode imm:$a, RRegu32:$b))]>;
|
[(set RRegu32:$d, (opnode imm:$a, RRegu32:$b))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
multiclass PTX_SETP<RegisterClass RC, string regclsname, Operand immcls,
|
||||||
|
CondCode cmp, string cmpstr> {
|
||||||
|
def rr
|
||||||
|
: InstPTX<(outs Preds:$d), (ins RC:$a, RC:$b),
|
||||||
|
!strconcat("setp.", cmpstr, ".", regclsname, "\t$d, $a, $b"),
|
||||||
|
[(set Preds:$d, (setcc RC:$a, RC:$b, cmp))]>;
|
||||||
|
def ri
|
||||||
|
: InstPTX<(outs Preds:$d), (ins RC:$a, immcls:$b),
|
||||||
|
!strconcat("setp.", cmpstr, ".", regclsname, "\t$d, $a, $b"),
|
||||||
|
[(set Preds:$d, (setcc RC:$a, imm:$b, cmp))]>;
|
||||||
|
}
|
||||||
|
|
||||||
multiclass PTX_LD<string opstr, string typestr, RegisterClass RC, PatFrag pat_load> {
|
multiclass PTX_LD<string opstr, string typestr, RegisterClass RC, PatFrag pat_load> {
|
||||||
def rr32 : InstPTX<(outs RC:$d),
|
def rr32 : InstPTX<(outs RC:$d),
|
||||||
(ins MEMri32:$a),
|
(ins MEMri32:$a),
|
||||||
@@ -343,6 +355,11 @@ multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> {
|
|||||||
// Instructions
|
// Instructions
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
///===- Integer Arithmetic Instructions -----------------------------------===//
|
||||||
|
|
||||||
|
defm ADD : INT3<"add", add>;
|
||||||
|
defm SUB : INT3<"sub", sub>;
|
||||||
|
|
||||||
///===- Floating-Point Arithmetic Instructions ----------------------------===//
|
///===- Floating-Point Arithmetic Instructions ----------------------------===//
|
||||||
|
|
||||||
// Standard Binary Operations
|
// Standard Binary Operations
|
||||||
@@ -397,12 +414,14 @@ def FDIVri64SM10 : InstPTX<(outs RRegf64:$d),
|
|||||||
// TODO: Allow the rounding mode to be selectable through llc.
|
// TODO: Allow the rounding mode to be selectable through llc.
|
||||||
defm FMAD : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>;
|
defm FMAD : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>;
|
||||||
|
|
||||||
|
///===- Comparison and Selection Instructions -----------------------------===//
|
||||||
|
|
||||||
|
defm SETPEQu32 : PTX_SETP<RRegu32, "u32", i32imm, SETEQ, "eq">;
|
||||||
///===- Integer Arithmetic Instructions -----------------------------------===//
|
defm SETPNEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETNE, "ne">;
|
||||||
|
defm SETPLTu32 : PTX_SETP<RRegu32, "u32", i32imm, SETULT, "lt">;
|
||||||
defm ADD : INT3<"add", add>;
|
defm SETPLEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETULE, "le">;
|
||||||
defm SUB : INT3<"sub", sub>;
|
defm SETPGTu32 : PTX_SETP<RRegu32, "u32", i32imm, SETUGT, "gt">;
|
||||||
|
defm SETPGEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETUGE, "ge">;
|
||||||
|
|
||||||
///===- Logic and Shift Instructions --------------------------------------===//
|
///===- Logic and Shift Instructions --------------------------------------===//
|
||||||
|
|
||||||
@@ -475,6 +494,10 @@ defm STs : PTX_ST_ALL<"st.shared", store_shared>;
|
|||||||
// defm LDp : PTX_LD_ALL<"ld.param", load_parameter>;
|
// defm LDp : PTX_LD_ALL<"ld.param", load_parameter>;
|
||||||
// TODO: Do something with st.param if/when it is needed.
|
// TODO: Do something with st.param if/when it is needed.
|
||||||
|
|
||||||
|
def CVT_u32_pred
|
||||||
|
: InstPTX<(outs RRegu32:$d), (ins Preds:$a), "cvt.u32.pred\t$d, $a",
|
||||||
|
[(set RRegu32:$d, (zext Preds:$a))]>;
|
||||||
|
|
||||||
///===- Control Flow Instructions -----------------------------------------===//
|
///===- Control Flow Instructions -----------------------------------------===//
|
||||||
|
|
||||||
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
|
let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
|
||||||
|
|||||||
109
test/CodeGen/PTX/setp.ll
Normal file
109
test/CodeGen/PTX/setp.ll
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
; RUN: llc < %s -march=ptx | FileCheck %s
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_eq_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.eq.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp eq i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_ne_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.ne.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ne i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_lt_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.lt.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ult i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_le_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.le.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ule i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_gt_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.gt.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ugt i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_ge_u32_rr(i32 %x, i32 %y) {
|
||||||
|
; CHECK: setp.ge.u32 p0, r1, r2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp uge i32 %x, %y
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_eq_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.eq.u32 p0, r1, 1;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp eq i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_ne_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.ne.u32 p0, r1, 1;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ne i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_lt_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.eq.u32 p0, r1, 0;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ult i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_le_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.lt.u32 p0, r1, 2;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ule i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_gt_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.gt.u32 p0, r1, 1;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp ugt i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
|
|
||||||
|
define ptx_device i32 @test_setp_ge_u32_ri(i32 %x) {
|
||||||
|
; CHECK: setp.ne.u32 p0, r1, 0;
|
||||||
|
; CHECK-NEXT: cvt.u32.pred r0, p0;
|
||||||
|
; CHECK-NEXT: ret;
|
||||||
|
%p = icmp uge i32 %x, 1
|
||||||
|
%z = zext i1 %p to i32
|
||||||
|
ret i32 %z
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user