[llvm] [RISCV] Move Xqci Select-likes to use riscv_selectcc (PR #153147)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 14 19:53:40 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-risc-v

Author: Sam Elliott (lenary)

<details>
<summary>Changes</summary>

The original patterns for the Xqci select-like instructions used `select`, and marked that ISD node as legal. This is not the usual way that `select` is dealt with in the RISC-V backend.

Usually on RISC-V, we expand `select` to `riscv_select_cc` which holds references to the operands of the comparison and the possible values depending on the comparison. In retrospect, this is a much better fit for our instructions, as most of them correspond to specific condition codes, rather than more generic `select` with a truthy/falsey value.

This PR moves the Xqci select-like patterns to use `riscv_select_cc` nodes. This applies to the Xqcicm, Xqcics and Xqcicli instruction patterns.

In order to match the existing codegen, minor additions had to be made to `translateSetCCForBranch` to ensure that comparisons against specific immediate values are left in a form that can be matched more closely by the instructions. This prevents having to insert additional `li` instructions and use the register forms.

There are a few slight regressions:
- There are sometimes more `mv` instructions than entirely necessary. I believe these would not be seen with larger examples where the register allocator has more leeway.
- In some tests where just one of the three extensions is enabled, codegen falls back to using a branch over a move. With all three extensions enabled (the configuration we most care about), these are not seen.
- The generated patterns are very similar to each other - they have similar complexity (7 or 8) and there are still overlaps. Sometimes the choice between two instructions can be affected by the order of the patterns in the tablegen file.

---

Patch is 128.95 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/153147.diff


11 Files Affected:

- (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (-3) 
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+17-2) 
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+82-68) 
- (modified) llvm/test/CodeGen/RISCV/select-bare.ll (+14) 
- (modified) llvm/test/CodeGen/RISCV/select-cc.ll (+76) 
- (modified) llvm/test/CodeGen/RISCV/select-cond.ll (+353-110) 
- (modified) llvm/test/CodeGen/RISCV/select-const.ll (+138) 
- (modified) llvm/test/CodeGen/RISCV/select.ll (+418) 
- (modified) llvm/test/CodeGen/RISCV/xqcicli.ll (+183-3) 
- (modified) llvm/test/CodeGen/RISCV/xqcicm.ll (+217-26) 
- (modified) llvm/test/CodeGen/RISCV/xqcics.ll (+123) 


``````````diff
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index a7329d201f880..0f8956e524c1b 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -1488,9 +1488,6 @@ def HasVendorXqcics
 def NoVendorXqcics
     : Predicate<"!Subtarget->hasVendorXqcics()">;
 
-def HasVendorXqcicsOrXqcicm
-    : Predicate<"Subtarget->hasVendorXqcics() || Subtarget->hasVendorXqcicm()">;
-
 def FeatureVendorXqcicsr
     : RISCVExperimentalExtension<0, 4, "Qualcomm uC CSR Extension">;
 def HasVendorXqcicsr
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 57ca687df5f6c..0e0193326d94a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -436,8 +436,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::ABS, MVT::i32, Custom);
   }
 
-  if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov() &&
-      !Subtarget.hasVendorXqcicm() && !Subtarget.hasVendorXqcics())
+  if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
 
   if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
@@ -2505,6 +2504,14 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
         CC = ISD::SETGE;
         return;
       }
+      if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
+          C != INT64_MAX && isInt<5>(C + 1)) {
+        // We have a conditional move instruction for SETGE but not SETGT.
+        // Convert X > C to X >= C + 1, if (C + 1) is a 5-bit signed immediate.
+        RHS = DAG.getSignedConstant(C + 1, DL, RHS.getValueType());
+        CC = ISD::SETGE;
+        return;
+      }
       if (Subtarget.hasVendorXqcibi() && C != INT64_MAX && isInt<16>(C + 1)) {
         // We have a branch immediate instruction for SETGE but not SETGT.
         // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit signed immediate.
@@ -2523,6 +2530,14 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
       }
       break;
     case ISD::SETUGT:
+      if ((Subtarget.hasVendorXqcicm() || Subtarget.hasVendorXqcicli()) &&
+          C != INT64_MAX && isUInt<5>(C + 1)) {
+        // We have a conditional move instruction for SETUGE but not SETUGT.
+        // Convert X > C to X >= C + 1, if (C + 1) is a 5-bit signed immediate.
+        RHS = DAG.getConstant(C + 1, DL, RHS.getValueType());
+        CC = ISD::SETUGE;
+        return;
+      }
       if (Subtarget.hasVendorXqcibi() && C != INT64_MAX && isUInt<16>(C + 1)) {
         // We have a branch immediate instruction for SETUGE but not SETUGT.
         // Convert X > C to X >= C + 1, if (C + 1) is a 16-bit unsigned
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 2c64b0c220fba..f3f98ae333028 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1334,51 +1334,51 @@ class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
           (Inst GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt)>;
 
 class QCIMVCCPat<CondCode Cond, QCIMVCC Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2), Cond)), (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2), Cond, (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd))),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, GPRNoX0:$rs3)>;
 
 class QCIMVCCIPat<CondCode Cond, QCIMVCCI Inst, DAGOperand InTyImm>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rs1), InTyImm:$imm, Cond)), (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), InTyImm:$imm, Cond, (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd))),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, InTyImm:$imm, GPRNoX0:$rs3)>;
 
 class QCISELECTCCIPat<CondCode Cond, QCISELECTCCI Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), simm5:$imm, Cond)), (i32 GPRNoX0:$rs2), (i32 GPRNoX0:$rs3)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), simm5:$imm, Cond, (i32 GPRNoX0:$rs2), (i32 GPRNoX0:$rs3))),
           (Inst GPRNoX0:$rd, simm5:$imm, GPRNoX0:$rs2, GPRNoX0:$rs3)>;
 
 class QCISELECTICCIPat<CondCode Cond, QCISELECTICCI Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), simm5:$imm, Cond)), (i32 GPRNoX0:$rs2), simm5:$simm2),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), simm5:$imm, Cond, (i32 GPRNoX0:$rs2), simm5:$simm2)),
           (Inst GPRNoX0:$rd, simm5:$imm, GPRNoX0:$rs2, simm5:$simm2)>;
 
 class QCISELECTICCIPatInv<CondCode Cond, QCISELECTICCI Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), simm5:$imm, Cond)), simm5:$simm2, (i32 GPRNoX0:$rs2)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), simm5:$imm, Cond, simm5:$simm2, (i32 GPRNoX0:$rs2))),
           (Inst GPRNoX0:$rd, simm5:$imm, GPRNoX0:$rs2, simm5:$simm2)>;
 
 class QCISELECTICCPat<CondCode Cond, QCISELECTICC Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond)), (i32 GPRNoX0:$rs2), simm5:$simm2),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond, (i32 GPRNoX0:$rs2), simm5:$simm2)),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm2)>;
 
 class QCISELECTICCPatInv<CondCode Cond, QCISELECTICC Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond)), simm5:$simm2, (i32 GPRNoX0:$rs2)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond, simm5:$simm2, (i32 GPRNoX0:$rs2))),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm2)>;
 
 class QCISELECTIICCPat<CondCode Cond, QCISELECTIICC Inst>
-    : Pat<(select (i32 (setcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond)), simm5:$simm1, simm5:$simm2),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs1), Cond, simm5:$simm1, simm5:$simm2)),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, simm5:$simm1, simm5:$simm2)>;
 
 class QCILICCPat<CondCode Cond, QCILICC Inst>
-    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), (XLenVT GPRNoX0:$rs2), Cond)), simm5:$simm, (XLenVT GPRNoX0:$rd)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2), Cond, simm5:$simm, (i32 GPRNoX0:$rd))),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm)>;
 
 class QCILICCPatInv<CondCode Cond, QCILICC Inst>
-    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), (XLenVT GPRNoX0:$rs2), Cond)), (XLenVT GPRNoX0:$rd), simm5:$simm),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2), Cond, (i32 GPRNoX0:$rd), simm5:$simm)),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, simm5:$simm)>;
 
 class QCILICCIPat<CondCode Cond, QCILICC Inst, DAGOperand InTyImm>
-    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), InTyImm:$imm, Cond)), simm5:$simm, (XLenVT GPRNoX0:$rd)),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), InTyImm:$imm, Cond, simm5:$simm, (i32 GPRNoX0:$rd))),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, InTyImm:$imm, simm5:$simm)>;
 
 class QCILICCIPatInv<CondCode Cond, QCILICC Inst, DAGOperand InTyImm>
-    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), InTyImm:$imm, Cond)), (XLenVT GPRNoX0:$rd), simm5:$simm),
+    : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), InTyImm:$imm, Cond, (i32 GPRNoX0:$rd), simm5:$simm)),
           (Inst GPRNoX0:$rd, GPRNoX0:$rs1, InTyImm:$imm, simm5:$simm)>;
 
 // Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
@@ -1525,79 +1525,93 @@ let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
 
 let Predicates = [HasVendorXqcicm, IsRV32] in {
-def : Pat<(select (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rd),(i32 GPRNoX0:$rs3)),
-          (QC_MVEQI GPRNoX0:$rd, GPRNoX0:$rs1, (i32 0), GPRNoX0:$rs3)>;
-
-def : QCIMVCCPat <SETEQ,  QC_MVEQ>;
-def : QCIMVCCPat <SETNE,  QC_MVNE>;
-def : QCIMVCCPat <SETLT,  QC_MVLT>;
-def : QCIMVCCPat <SETULT, QC_MVLTU>;
-
-def : QCIMVCCIPat <SETLT,  QC_MVLTI, simm5>;
-def : QCIMVCCIPat <SETULT, QC_MVLTUI, uimm5>;
+def : QCIMVCCPat<SETEQ,  QC_MVEQ>;
+def : QCIMVCCPat<SETNE,  QC_MVNE>;
+def : QCIMVCCPat<SETLT,  QC_MVLT>;
+def : QCIMVCCPat<SETULT, QC_MVLTU>;
+def : QCIMVCCPat<SETGE,  QC_MVGE>;
+def : QCIMVCCPat<SETUGE, QC_MVGEU>;
+
+def : QCIMVCCIPat<SETLT,  QC_MVLTI,  simm5>;
+def : QCIMVCCIPat<SETULT, QC_MVLTUI, uimm5>;
+def : QCIMVCCIPat<SETGE,  QC_MVGEI,  simm5>;
+def : QCIMVCCIPat<SETUGE, QC_MVGEUI, uimm5>;
 }
 
 // Prioritize Xqcics over these patterns.
 let Predicates = [HasVendorXqcicm, NoVendorXqcics, IsRV32] in {
-def : QCIMVCCIPat <SETEQ,  QC_MVEQI, simm5>;
-def : QCIMVCCIPat <SETNE,  QC_MVNEI, simm5>;
+// (SELECT X, Y, Z) is canonicalised to `(riscv_selectcc x, 0, NE, y, z)`.
+// This exists to prioritise over the `Select_GPR_Using_CC_GPR` pattern.
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), (i32 0), SETNE, (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd))),
+          (QC_MVNEI GPRNoX0:$rd, GPRNoX0:$rs1, 0, GPRNoX0:$rs3)>;
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rs1), (i32 0), SETEQ, (i32 GPRNoX0:$rs3), (i32 GPRNoX0:$rd))),
+          (QC_MVEQI GPRNoX0:$rd, GPRNoX0:$rs1, 0, GPRNoX0:$rs3)>;
+
+def : QCIMVCCIPat<SETEQ,  QC_MVEQI, simm5>;
+def : QCIMVCCIPat<SETNE,  QC_MVNEI, simm5>;
 }
 
-let Predicates = [HasVendorXqcicli, HasVendorXqcicsOrXqcicm, IsRV32] in {
-def : QCILICCPat <SETEQ,  QC_LIEQ>;
-def : QCILICCPat <SETNE,  QC_LINE>;
-def : QCILICCPat <SETLT,  QC_LILT>;
-def : QCILICCPat <SETGE,  QC_LIGE>;
-def : QCILICCPat <SETULT, QC_LILTU>;
-def : QCILICCPat <SETUGE, QC_LIGEU>;
-
-def : QCILICCIPat <SETEQ,  QC_LIEQI, simm5>;
-def : QCILICCIPat <SETNE,  QC_LINEI, simm5>;
-def : QCILICCIPat <SETLT,  QC_LILTI, simm5>;
-def : QCILICCIPat <SETGE,  QC_LIGEI, simm5>;
-def : QCILICCIPat <SETULT, QC_LILTUI, uimm5>;
-def : QCILICCIPat <SETUGE, QC_LIGEUI, uimm5>;
-
-def : QCILICCPatInv <SETNE,  QC_LIEQ>;
-def : QCILICCPatInv <SETEQ,  QC_LINE>;
-def : QCILICCPatInv <SETGE,  QC_LILT>;
-def : QCILICCPatInv <SETLT,  QC_LIGE>;
-def : QCILICCPatInv <SETUGE, QC_LILTU>;
-def : QCILICCPatInv <SETULT, QC_LIGEU>;
-
-def : QCILICCIPatInv <SETNE,  QC_LIEQI, simm5>;
-def : QCILICCIPatInv <SETEQ,  QC_LINEI, simm5>;
-def : QCILICCIPatInv <SETGE,  QC_LILTI, simm5>;
-def : QCILICCIPatInv <SETLT,  QC_LIGEI, simm5>;
-def : QCILICCIPatInv <SETUGE, QC_LILTUI, uimm5>;
-def : QCILICCIPatInv <SETULT, QC_LIGEUI, uimm5>;
-}
+let Predicates = [HasVendorXqcicli, IsRV32] in {
+def : QCILICCPat<SETEQ,  QC_LIEQ>;
+def : QCILICCPat<SETNE,  QC_LINE>;
+def : QCILICCPat<SETLT,  QC_LILT>;
+def : QCILICCPat<SETGE,  QC_LIGE>;
+def : QCILICCPat<SETULT, QC_LILTU>;
+def : QCILICCPat<SETUGE, QC_LIGEU>;
+
+def : QCILICCIPat<SETEQ,  QC_LIEQI, simm5>;
+def : QCILICCIPat<SETNE,  QC_LINEI, simm5>;
+def : QCILICCIPat<SETLT,  QC_LILTI, simm5>;
+def : QCILICCIPat<SETGE,  QC_LIGEI, simm5>;
+def : QCILICCIPat<SETULT, QC_LILTUI, uimm5>;
+def : QCILICCIPat<SETUGE, QC_LIGEUI, uimm5>;
+
+def : QCILICCPatInv<SETNE,  QC_LIEQ>;
+def : QCILICCPatInv<SETEQ,  QC_LINE>;
+def : QCILICCPatInv<SETGE,  QC_LILT>;
+def : QCILICCPatInv<SETLT,  QC_LIGE>;
+def : QCILICCPatInv<SETUGE, QC_LILTU>;
+def : QCILICCPatInv<SETULT, QC_LIGEU>;
+
+def : QCILICCIPatInv<SETNE,  QC_LIEQI, simm5>;
+def : QCILICCIPatInv<SETEQ,  QC_LINEI, simm5>;
+def : QCILICCIPatInv<SETGE,  QC_LILTI, simm5>;
+def : QCILICCIPatInv<SETLT,  QC_LIGEI, simm5>;
+def : QCILICCIPatInv<SETUGE, QC_LILTUI, uimm5>;
+def : QCILICCIPatInv<SETULT, QC_LIGEUI, uimm5>;
+} // Predicates = [HasVendorXqcicli, IsRV32]
 
 let Predicates = [HasVendorXqcics, IsRV32] in {
-def : Pat<(select (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs2),(i32 GPRNoX0:$rs3)),
+// (SELECT X, Y, Z) is canonicalised to `(riscv_selectcc x, 0, NE, y, z)`.
+// These exist to prioritise over the `Select_GPR_Using_CC_GPR` pattern.
+
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 0), SETNE, (i32 GPRNoX0:$rs2), (i32 GPRNoX0:$rs3))),
           (QC_SELECTNEI GPRNoX0:$rd, (i32 0), GPRNoX0:$rs2, GPRNoX0:$rs3)>;
-def : Pat<(select (i32 GPRNoX0:$rd), (i32 GPRNoX0:$rs2), simm5:$simm2),
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 0), SETEQ, (i32 GPRNoX0:$rs2), (i32 GPRNoX0:$rs3))),
+          (QC_SELECTEQI GPRNoX0:$rd, (i32 0), GPRNoX0:$rs2, GPRNoX0:$rs3)>;
+
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 0), SETNE, (i32 GPRNoX0:$rs2), simm5:$simm2)),
           (QC_SELECTINEI GPRNoX0:$rd, (i32 0), GPRNoX0:$rs2, simm5:$simm2)>;
-def : Pat<(select (i32 GPRNoX0:$rd), simm5:$simm2,(i32 GPRNoX0:$rs2)),
+def : Pat<(i32 (riscv_selectcc (i32 GPRNoX0:$rd), (i32 0), SETNE, simm5:$simm2, (i32 GPRNoX0:$rs2))),
           (QC_SELECTIEQI GPRNoX0:$rd, (i32 0), GPRNoX0:$rs2, simm5:$simm2)>;
 
-def : QCISELECTCCIPat <SETEQ,  QC_SELECTEQI>;
-def : QCISELECTCCIPat <SETNE,  QC_SELECTNEI>;
+def : QCISELECTCCIPat<SETEQ,  QC_SELECTEQI>;
+def : QCISELECTCCIPat<SETNE,  QC_SELECTNEI>;
 
-def : QCISELECTICCIPat <SETEQ,  QC_SELECTIEQI>;
-def : QCISELECTICCIPat <SETNE,  QC_SELECTINEI>;
+def : QCISELECTICCIPat<SETEQ,  QC_SELECTIEQI>;
+def : QCISELECTICCIPat<SETNE,  QC_SELECTINEI>;
 
-def : QCISELECTICCIPatInv <SETEQ,  QC_SELECTINEI>;
-def : QCISELECTICCIPatInv <SETNE,  QC_SELECTIEQI>;
+def : QCISELECTICCIPatInv<SETEQ,  QC_SELECTINEI>;
+def : QCISELECTICCIPatInv<SETNE,  QC_SELECTIEQI>;
 
-def : QCISELECTICCPat <SETEQ,  QC_SELECTIEQ>;
-def : QCISELECTICCPat <SETNE,  QC_SELECTINE>;
+def : QCISELECTICCPat<SETEQ,  QC_SELECTIEQ>;
+def : QCISELECTICCPat<SETNE,  QC_SELECTINE>;
 
-def : QCISELECTICCPatInv <SETEQ,  QC_SELECTINE>;
-def : QCISELECTICCPatInv <SETNE,  QC_SELECTIEQ>;
+def : QCISELECTICCPatInv<SETEQ,  QC_SELECTINE>;
+def : QCISELECTICCPatInv<SETNE,  QC_SELECTIEQ>;
 
-def : QCISELECTIICCPat <SETEQ,  QC_SELECTIIEQ>;
-def : QCISELECTIICCPat <SETNE,  QC_SELECTIINE>;
+def : QCISELECTIICCPat<SETEQ,  QC_SELECTIIEQ>;
+def : QCISELECTIICCPat<SETNE,  QC_SELECTIINE>;
 } // Predicates = [HasVendorXqcics, IsRV32]
 
 let Predicates = [HasVendorXqcilsm, IsRV32] in {
diff --git a/llvm/test/CodeGen/RISCV/select-bare.ll b/llvm/test/CodeGen/RISCV/select-bare.ll
index fc8eaa480b116..e6b742375df57 100644
--- a/llvm/test/CodeGen/RISCV/select-bare.ll
+++ b/llvm/test/CodeGen/RISCV/select-bare.ll
@@ -3,6 +3,8 @@
 ; RUN:   | FileCheck %s -check-prefix=RV32I
 ; RUN: llc -mtriple=riscv64 -mattr=+xmipscmov -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I-CCMOV %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm,+experimental-xqcics,+experimental-xqcicli -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32IXQCI
 
 define i32 @bare_select(i1 %a, i32 %b, i32 %c) nounwind {
 ; RV32I-LABEL: bare_select:
@@ -20,6 +22,12 @@ define i32 @bare_select(i1 %a, i32 %b, i32 %c) nounwind {
 ; RV64I-CCMOV-NEXT:    andi a0, a0, 1
 ; RV64I-CCMOV-NEXT:    mips.ccmov a0, a0, a1, a2
 ; RV64I-CCMOV-NEXT:    ret
+;
+; RV32IXQCI-LABEL: bare_select:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    andi a0, a0, 1
+; RV32IXQCI-NEXT:    qc.selectnei a0, 0, a1, a2
+; RV32IXQCI-NEXT:    ret
   %1 = select i1 %a, i32 %b, i32 %c
   ret i32 %1
 }
@@ -40,6 +48,12 @@ define float @bare_select_float(i1 %a, float %b, float %c) nounwind {
 ; RV64I-CCMOV-NEXT:    andi a0, a0, 1
 ; RV64I-CCMOV-NEXT:    mips.ccmov a0, a0, a1, a2
 ; RV64I-CCMOV-NEXT:    ret
+;
+; RV32IXQCI-LABEL: bare_select_float:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    andi a0, a0, 1
+; RV32IXQCI-NEXT:    qc.selectnei a0, 0, a1, a2
+; RV32IXQCI-NEXT:    ret
   %1 = select i1 %a, float %b, float %c
   ret float %1
 }
diff --git a/llvm/test/CodeGen/RISCV/select-cc.ll b/llvm/test/CodeGen/RISCV/select-cc.ll
index ec1f8aeddcaaf..02b562c130657 100644
--- a/llvm/test/CodeGen/RISCV/select-cc.ll
+++ b/llvm/test/CodeGen/RISCV/select-cc.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=riscv32 -disable-block-placement -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV32I %s
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm,+experimental-xqcics,+experimental-xqcicli -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32IXQCI
 ; RUN: llc -mtriple=riscv64 -disable-block-placement -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefixes=RV64I %s
 ; RUN: llc -mtriple=riscv64 -mattr=+xmipscmov -verify-machineinstrs < %s \
@@ -83,6 +85,44 @@ define signext i32 @foo(i32 signext %a, ptr %b) nounwind {
 ; RV32I-NEXT:  .LBB0_28:
 ; RV32I-NEXT:    ret
 ;
+; RV32IXQCI-LABEL: foo:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    lw a5, 0(a1)
+; RV32IXQCI-NEXT:    lw a2, 0(a1)
+; RV32IXQCI-NEXT:    lw a4, 0(a1)
+; RV32IXQCI-NEXT:    lw t5, 0(a1)
+; RV32IXQCI-NEXT:    lw t4, 0(a1)
+; RV32IXQCI-NEXT:    lw t2, 0(a1)
+; RV32IXQCI-NEXT:    lw t1, 0(a1)
+; RV32IXQCI-NEXT:    lw t0, 0(a1)
+; RV32IXQCI-NEXT:    lw a7, 0(a1)
+; RV32IXQCI-NEXT:    lw a6, 0(a1)
+; RV32IXQCI-NEXT:    lw t3, 0(a1)
+; RV32IXQCI-NEXT:    lw a3, 0(a1)
+; RV32IXQCI-NEXT:    bltz t3, .LBB0_2
+; RV32IXQCI-NEXT:  # %bb.1:
+; RV32IXQCI-NEXT:    li t6, 0
+; RV32IXQCI-NEXT:    qc.mveq a5, a0, a5, a0
+; RV32IXQCI-NEXT:    qc.mvne a2, a5, a2, a5
+; RV32IXQCI-NEXT:    qc.mvltu a4, a4, a2, a2
+; RV32IXQCI-NEXT:    qc.mvgeu t5, a4, t5, a4
+; RV32IXQCI-NEXT:    qc.mvltu t4, t5, t4, t5
+; RV32IXQCI-NEXT:    qc.mvgeu t2, t2, t4, t4
+; RV32IXQCI-NEXT:    qc.mvlt t1, t1, t2, t2
+; RV32IXQCI-NEXT:    qc.mvge t0, t1, t0, t1
+; RV32IXQCI-NEXT:    qc.mvlt a7, t0, a7, t0
+; RV32IXQCI-NEXT:    qc.mvge a6, a6, a7, a7
+; RV32IXQCI-NEXT:    mv a3, t3
+; RV32IXQCI-NEXT:    qc.mvge a3, t6, t3, a6
+; RV32IXQCI-NEXT:  .LBB0_2:
+; RV32IXQCI-NEXT:    lw a2, 0(a1)
+; RV32IXQCI-NEXT:    lw a0, 0(a1)
+; RV32IXQCI-NEXT:    li a1, 1024
+; RV32IXQCI-NEXT:    qc.mvlt a2, a1, a2, a3
+; RV32IXQCI-NEXT:    li a1, 2046
+; RV32IXQCI-NEXT:    qc.mvltu a0, a1, t3, a2
+; RV32IXQCI-NEXT:    ret
+;
 ; RV64I-LABEL: foo:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    lw a2, 0(a1)
@@ -291,6 +331,23 @@ define signext i16 @numsignbits(i16 signext %0, i16 signext %1, i16 signext %2,
 ; RV32I-NEXT:    addi sp, sp, 16
 ; RV32I-NEXT:    ret
 ;
+; RV32IXQCI-LABEL: numsignbits:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    qc.selecteqi a0, 0, a3, a2
+; RV32IXQCI-NEXT:    beqz a1, .LBB1_2
+; RV32IXQCI-NEXT:  # %bb.1:
+; RV32IXQCI-NEXT:    addi sp, sp, -16
+; RV32IXQCI-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32IXQCI-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
+; RV32IXQCI-NEXT:    mv s0, a0
+; RV32IXQCI-NEXT:    call bar
+; RV32IXQCI-NEXT:    mv a0, s0
+; RV32IXQCI-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32IXQCI-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
+; RV32IXQCI-NEXT:    addi sp, sp, 16
+; RV32IXQCI-NEXT:  .LBB1_2:
+; RV32IXQCI-NEXT:    ret
+;
 ; RV64I-LABEL: numsignbits:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    addi sp, sp, -16
@@ -355,6 +412,14 @@ define i32 @select_sge_int16min(i32 signext %x, i32 signext %y, i32 signext %z)
 ; RV32I-NEXT:    mv a0, a1
 ; RV32I-NEXT:    ret
 ;
+; RV32IXQCI-LABEL: select_sge_int16min:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    lui a3, 1048560
+; RV32IXQCI-NEXT:    addi a3, a3, -1
+; RV32IXQCI-NEXT:    qc.mvlt a2, a3, a0, a1
+; RV32IXQCI-NEXT:    mv a0, a2
+; RV32IXQCI-NEXT:    ret
+;
 ; RV64I-LABEL: select_sge_int16min:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    lui a3, 1048560
@@ -399,6 +464,17 @@ define i64 @select_sge_int32min(i64 %x, i64 %y, i64 %z) {
 ; RV32I-NEXT:    mv a1, a3
 ; RV32I-NEXT:    ret
 ;
+; RV32IXQCI-LABEL: select_sge_int32min:
+; RV32IXQCI:       # %bb.0:
+; RV32IXQCI-NEXT:    slti a6, a0, 0
+; RV32IXQCI-NEXT:    slti a0, a1, 0
+; RV32IXQCI-NEXT:    xori a0, a0, 1
+; RV32IXQCI-NEXT:    qc.selecteqi a1, -1, a6, a0
+; RV32IXQCI-NEXT:    mv a0, a1
+; RV32IXQCI-NEXT:    qc.selectnei a0, 0, a2, a4
+; RV32IXQCI-NEXT:    qc.selectnei a1, 0, a3, a5
+; RV32IXQCI-NEXT:    ret
+;
 ; RV64I-LABEL: select_sge_int32min:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    lui a3, 524288
diff --git a/llvm/test/CodeGen/RISCV/select-cond.ll b/llvm/test/CodeGen/RISCV/select-cond.ll
index 59f4d95f45acc..a2a0a4e9177f6 100644
--- a/llvm/test/CodeGen/RISCV/select-cond.ll
+++ b/llvm/test/CodeGen/RISCV/select-cond.ll
@@ -7,6 +7,8 @@
 ; RUN:   | FileCheck %s --check-prefixes=RV32-XQCICM
 ; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcics -verify-machineinstrs < %s \
 ; RUN:  ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/153147


More information about the llvm-commits mailing list