ptx: add set.p instruction and related changes to predicate execution
authorChe-Liang Chiou <clchiou@gmail.com>
Mon, 14 Mar 2011 11:26:01 +0000 (11:26 +0000)
committerChe-Liang Chiou <clchiou@gmail.com>
Mon, 14 Mar 2011 11:26:01 +0000 (11:26 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127577 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PTX/PTX.h
lib/Target/PTX/PTXAsmPrinter.cpp
lib/Target/PTX/PTXInstrInfo.cpp
lib/Target/PTX/PTXInstrInfo.td
test/CodeGen/PTX/setp.ll [new file with mode: 0644]

index 657279106e04aca62616cfca970489e8d2f2790d..49045cdc01edeeb51c05760791e9f55779c21a52 100644 (file)
@@ -31,7 +31,7 @@ namespace llvm {
     };
 
     enum Predicate {
-      PRED_IGNORE = 0,
+      PRED_NORMAL = 0,
       PRED_NEGATE = 1
     };
   } // namespace PTX
index 8b5ed4501fbdf34bb109afc49a4c8e127a3f5af7..087d4f98c4869f8d518f44b09b1f397fa310d7a5 100644 (file)
@@ -410,7 +410,7 @@ printPredicateOperand(const MachineInstr *MI, raw_ostream &O) {
 
   DEBUG(dbgs() << "predicate: (" << reg << ", " << predOp << ")\n");
 
-  if (reg && predOp != PTX::PRED_IGNORE) {
+  if (reg != PTX::NoRegister) {
     O << '@';
     if (predOp == PTX::PRED_NEGATE)
       O << '!';
index 8c2145d26c7126e8eee8b4cffb88b45b30f8636e..0aebc820521989fff32f71d27fe84d1c05fc26e3 100644 (file)
@@ -100,10 +100,7 @@ bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
 
 bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
   int i = MI->findFirstPredOperandIdx();
-  if (i == -1)
-    llvm_unreachable("missing predicate operand");
-  return MI->getOperand(i).getReg() ||
-         MI->getOperand(i+1).getImm() != PTX::PRED_IGNORE;
+  return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
 }
 
 bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
@@ -143,7 +140,29 @@ DefinesPredicate(MachineInstr *MI,
   // If the specified instruction defines any predicate or condition code
   // register(s) used for predication, returns true as well as the definition
   // predicate(s) by reference.
-  return false;
+
+  switch (MI->getOpcode()) {
+  default:
+    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
@@ -151,8 +170,8 @@ DefinesPredicate(MachineInstr *MI,
 MachineSDNode *PTXInstrInfo::
 GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
                   DebugLoc dl, EVT VT, SDValue Op1) {
-  SDValue predReg = DAG->getRegister(0, MVT::i1);
-  SDValue predOp = DAG->getTargetConstant(PTX::PRED_IGNORE, MVT::i1);
+  SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
+  SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
   SDValue ops[] = { Op1, predReg, predOp };
   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
 }
@@ -160,8 +179,8 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
 MachineSDNode *PTXInstrInfo::
 GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
                   DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
-  SDValue predReg = DAG->getRegister(0, MVT::i1);
-  SDValue predOp = DAG->getTargetConstant(PTX::PRED_IGNORE, MVT::i1);
+  SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
+  SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
   SDValue ops[] = { Op1, Op2, predReg, predOp };
   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
 }
@@ -169,6 +188,6 @@ GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
 void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
   if (MI->findFirstPredOperandIdx() == -1) {
     MI->addOperand(MachineOperand::CreateReg(0, /*IsDef=*/false));
-    MI->addOperand(MachineOperand::CreateImm(PTX::PRED_IGNORE));
+    MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
   }
 }
index 065799430c0e0248a506ba4768e4282d6aea4108..a5f82f1bf380c883082e9b8ecf8a6fb6d7932fbf 100644 (file)
@@ -269,6 +269,18 @@ multiclass INT3ntnc<string opcstr, SDNode opnode> {
                    [(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> {
   def rr32 : InstPTX<(outs RC:$d),
                      (ins MEMri32:$a),
@@ -343,6 +355,11 @@ multiclass PTX_ST_ALL<string opstr, PatFrag pat_store> {
 // Instructions
 //===----------------------------------------------------------------------===//
 
+///===- Integer Arithmetic Instructions -----------------------------------===//
+
+defm ADD : INT3<"add", add>;
+defm SUB : INT3<"sub", sub>;
+
 ///===- Floating-Point Arithmetic Instructions ----------------------------===//
 
 // Standard Binary Operations
@@ -397,12 +414,14 @@ def FDIVri64SM10 : InstPTX<(outs RRegf64:$d),
 // TODO: Allow the rounding mode to be selectable through llc.
 defm FMAD : PTX_FLOAT_4OP<"mad.rn", fmul, fadd>;
 
+///===- Comparison and Selection Instructions -----------------------------===//
 
-
-///===- Integer Arithmetic Instructions -----------------------------------===//
-
-defm ADD : INT3<"add", add>;
-defm SUB : INT3<"sub", sub>;
+defm SETPEQu32 : PTX_SETP<RRegu32, "u32", i32imm, SETEQ,  "eq">;
+defm SETPNEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETNE,  "ne">;
+defm SETPLTu32 : PTX_SETP<RRegu32, "u32", i32imm, SETULT, "lt">;
+defm SETPLEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETULE, "le">;
+defm SETPGTu32 : PTX_SETP<RRegu32, "u32", i32imm, SETUGT, "gt">;
+defm SETPGEu32 : PTX_SETP<RRegu32, "u32", i32imm, SETUGE, "ge">;
 
 ///===- 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>;
 // 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 -----------------------------------------===//
 
 let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
diff --git a/test/CodeGen/PTX/setp.ll b/test/CodeGen/PTX/setp.ll
new file mode 100644 (file)
index 0000000..7f8b996
--- /dev/null
@@ -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
+}