Skip to content

[RISCV] Add ISel patterns for Qualcomm uC Xqcicm extension #145643

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 27, 2025

Conversation

hchandel
Copy link
Contributor

Add codegen patterns for the conditional move instructions in this extension

Change-Id: I85ca9b02f88b34c3745a28aebc73d6da80928207
@llvmbot
Copy link
Member

llvmbot commented Jun 25, 2025

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

Author: quic_hchandel (hchandel)

Changes

Add codegen patterns for the conditional move instructions in this extension


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

4 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+2-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td (+22)
  • (modified) llvm/test/CodeGen/RISCV/select-cond.ll (+204)
  • (added) llvm/test/CodeGen/RISCV/xqcicm.ll (+679)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 712f6154732a2..bb26306d19a20 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -436,7 +436,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::ABS, MVT::i32, Custom);
   }
 
-  if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov())
+  if (!Subtarget.useCCMovInsn() && !Subtarget.hasVendorXTHeadCondMov() &&
+      !Subtarget.hasVendorXqcicm())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
 
   if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index ccd20859c24e6..a306e7e9fc542 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1335,6 +1335,14 @@ class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
     : Pat<(StoreOp (i32 GPR:$rd), (AddShl (i32 GPRMem:$rs1), (i32 GPRNoX0:$rs2), uimm3:$shamt)),
           (Inst GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt)>;
 
+class QCIMVCCPat<CondCode Cond, QCIMVCC Inst>
+    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), (XLenVT GPRNoX0:$rs2), Cond)), (XLenVT GPRNoX0:$rs3), (XLenVT GPRNoX0:$rd)),
+          (Inst GPRNoX0:$rd, GPRNoX0:$rs1, GPRNoX0:$rs2, GPRNoX0:$rs3)>;
+
+class QCIMVCCIPat<CondCode Cond, QCIMVCCI Inst>
+    : Pat<(select (XLenVT (setcc (XLenVT GPRNoX0:$rs1), simm5:$imm, Cond)), (XLenVT GPRNoX0:$rs3), (XLenVT GPRNoX0:$rd)),
+          (Inst GPRNoX0:$rd, GPRNoX0:$rs1, simm5:$imm, GPRNoX0:$rs3)>;
+
 // Match `riscv_brcc` and lower to the appropriate XQCIBI branch instruction.
 class BcciPat<CondCode Cond, QCIBranchInst_rii Inst, DAGOperand InTyImm>
     : Pat<(riscv_brcc (XLenVT GPRNoX0:$rs1), InTyImm:$rs2, Cond, bb:$imm12),
@@ -1469,6 +1477,20 @@ def: Pat<(i32 (ctlz (not (i32 GPR:$rs1)))), (QC_CLO GPR:$rs1)>;
 let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
 
+let Predicates = [HasVendorXqcicm, IsRV32] in {
+def : Pat<(select (XLenVT GPRNoX0:$cond), (XLenVT GPRNoX0:$a),(XLenVT GPRNoX0:$b)),
+          (QC_MVEQI GPRNoX0:$a, GPRNoX0:$cond, (XLenVT 0), GPRNoX0:$b)>;
+
+def : QCIMVCCPat <SETEQ,  QC_MVEQ>;
+def : QCIMVCCPat <SETNE,  QC_MVNE>;
+def : QCIMVCCPat <SETLT,  QC_MVLT>;
+def : QCIMVCCPat <SETULT, QC_MVLTU>;
+
+def : QCIMVCCIPat <SETEQ,  QC_MVEQI>;
+def : QCIMVCCIPat <SETNE,  QC_MVNEI>;
+def : QCIMVCCIPat <SETLT,  QC_MVLTI>;
+def : QCIMVCCIPat <SETULT, QC_MVLTUI>;
+}
 
 //===----------------------------------------------------------------------===/i
 // Compress Instruction tablegen backend.
diff --git a/llvm/test/CodeGen/RISCV/select-cond.ll b/llvm/test/CodeGen/RISCV/select-cond.ll
index a5f4677f73f13..d9f9ad379ee95 100644
--- a/llvm/test/CodeGen/RISCV/select-cond.ll
+++ b/llvm/test/CodeGen/RISCV/select-cond.ll
@@ -3,6 +3,8 @@
 ; RUN:   | FileCheck %s --check-prefixes=RV32
 ; RUN: llc -mtriple=riscv32 -mattr=+xtheadcondmov -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefixes=RV32-THEAD
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32-XQCICM
 ; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefixes=RV64
 ; RUN: llc -mtriple=riscv64 -mattr=+xmipscmov -verify-machineinstrs < %s \
@@ -26,6 +28,13 @@ define signext i32 @select_i32_trunc(i32 signext %cond, i32 signext %x, i32 sign
 ; RV32-THEAD-NEXT:    mv a0, a1
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_trunc:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    andi a0, a0, 1
+; RV32-XQCICM-NEXT:    qc.mveqi a1, a0, 0, a2
+; RV32-XQCICM-NEXT:    mv a0, a1
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_trunc:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    andi a3, a0, 1
@@ -64,6 +73,13 @@ define signext i32 @select_i32_param(i1 signext %cond, i32 signext %x, i32 signe
 ; RV32-THEAD-NEXT:    mv a0, a1
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_param:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    andi a0, a0, 1
+; RV32-XQCICM-NEXT:    qc.mveqi a1, a0, 0, a2
+; RV32-XQCICM-NEXT:    mv a0, a1
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_param:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    andi a3, a0, 1
@@ -100,6 +116,12 @@ define signext i32 @select_i32_eq(i32 signext %a, i32 signext %b, i32 signext %x
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_eq:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mveq a3, a0, a1, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_eq:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    beq a0, a1, .LBB2_2
@@ -136,6 +158,12 @@ define signext i32 @select_i32_ne(i32 signext %a, i32 signext %b, i32 signext %x
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_ne:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvne a3, a0, a1, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_ne:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bne a0, a1, .LBB3_2
@@ -172,6 +200,12 @@ define signext i32 @select_i32_ugt(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_ugt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvltu a3, a1, a0, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_ugt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bltu a1, a0, .LBB4_2
@@ -208,6 +242,12 @@ define signext i32 @select_i32_uge(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_uge:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvltu a2, a0, a1, a3
+; RV32-XQCICM-NEXT:    mv a0, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_uge:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bgeu a0, a1, .LBB5_2
@@ -244,6 +284,12 @@ define signext i32 @select_i32_ult(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_ult:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvltu a3, a0, a1, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_ult:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bltu a0, a1, .LBB6_2
@@ -280,6 +326,12 @@ define signext i32 @select_i32_ule(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_ule:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvltu a2, a1, a0, a3
+; RV32-XQCICM-NEXT:    mv a0, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_ule:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bgeu a1, a0, .LBB7_2
@@ -316,6 +368,12 @@ define signext i32 @select_i32_sgt(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_sgt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvlt a3, a1, a0, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_sgt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    blt a1, a0, .LBB8_2
@@ -352,6 +410,12 @@ define signext i32 @select_i32_sge(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_sge:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvlt a2, a0, a1, a3
+; RV32-XQCICM-NEXT:    mv a0, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_sge:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bge a0, a1, .LBB9_2
@@ -388,6 +452,12 @@ define signext i32 @select_i32_slt(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_slt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvlt a3, a0, a1, a2
+; RV32-XQCICM-NEXT:    mv a0, a3
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_slt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    blt a0, a1, .LBB10_2
@@ -424,6 +494,12 @@ define signext i32 @select_i32_sle(i32 signext %a, i32 signext %b, i32 signext %
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i32_sle:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    qc.mvlt a2, a1, a0, a3
+; RV32-XQCICM-NEXT:    mv a0, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i32_sle:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bge a1, a0, .LBB11_2
@@ -465,6 +541,15 @@ define i64 @select_i64_trunc(i64 %cond, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a0, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_trunc:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    mv a1, a3
+; RV32-XQCICM-NEXT:    andi a0, a0, 1
+; RV32-XQCICM-NEXT:    qc.mveqi a2, a0, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a1, a0, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_trunc:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    andi a3, a0, 1
@@ -507,6 +592,15 @@ define i64 @select_i64_param(i1 %cond, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a2
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_param:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    andi a0, a0, 1
+; RV32-XQCICM-NEXT:    qc.mveqi a1, a0, 0, a3
+; RV32-XQCICM-NEXT:    qc.mveqi a2, a0, 0, a4
+; RV32-XQCICM-NEXT:    mv a0, a1
+; RV32-XQCICM-NEXT:    mv a1, a2
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_param:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    andi a3, a0, 1
@@ -552,6 +646,17 @@ define i64 @select_i64_eq(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_eq:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    xor a1, a1, a3
+; RV32-XQCICM-NEXT:    xor a0, a0, a2
+; RV32-XQCICM-NEXT:    or a0, a0, a1
+; RV32-XQCICM-NEXT:    qc.mveqi a6, a0, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a7, a0, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_eq:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    beq a0, a1, .LBB14_2
@@ -597,6 +702,17 @@ define i64 @select_i64_ne(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_ne:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    xor a1, a1, a3
+; RV32-XQCICM-NEXT:    xor a0, a0, a2
+; RV32-XQCICM-NEXT:    or a0, a0, a1
+; RV32-XQCICM-NEXT:    qc.mvnei a6, a0, 0, a4
+; RV32-XQCICM-NEXT:    qc.mvnei a7, a0, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_ne:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bne a0, a1, .LBB15_2
@@ -647,6 +763,17 @@ define i64 @select_i64_ugt(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_ugt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a2, a0
+; RV32-XQCICM-NEXT:    sltu a2, a3, a1
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a4, a2, 0, a6
+; RV32-XQCICM-NEXT:    qc.mveqi a5, a2, 0, a7
+; RV32-XQCICM-NEXT:    mv a0, a4
+; RV32-XQCICM-NEXT:    mv a1, a5
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_ugt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bltu a1, a0, .LBB16_2
@@ -697,6 +824,17 @@ define i64 @select_i64_uge(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_uge:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a0, a2
+; RV32-XQCICM-NEXT:    sltu a2, a1, a3
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a6, a2, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a7, a2, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_uge:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bgeu a0, a1, .LBB17_2
@@ -747,6 +885,17 @@ define i64 @select_i64_ult(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_ult:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a0, a2
+; RV32-XQCICM-NEXT:    sltu a2, a1, a3
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a4, a2, 0, a6
+; RV32-XQCICM-NEXT:    qc.mveqi a5, a2, 0, a7
+; RV32-XQCICM-NEXT:    mv a0, a4
+; RV32-XQCICM-NEXT:    mv a1, a5
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_ult:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bltu a0, a1, .LBB18_2
@@ -797,6 +946,17 @@ define i64 @select_i64_ule(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_ule:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a2, a0
+; RV32-XQCICM-NEXT:    sltu a2, a3, a1
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a6, a2, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a7, a2, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_ule:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bgeu a1, a0, .LBB19_2
@@ -847,6 +1007,17 @@ define i64 @select_i64_sgt(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_sgt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a2, a0
+; RV32-XQCICM-NEXT:    slt a2, a3, a1
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a4, a2, 0, a6
+; RV32-XQCICM-NEXT:    qc.mveqi a5, a2, 0, a7
+; RV32-XQCICM-NEXT:    mv a0, a4
+; RV32-XQCICM-NEXT:    mv a1, a5
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_sgt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    blt a1, a0, .LBB20_2
@@ -897,6 +1068,17 @@ define i64 @select_i64_sge(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_sge:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a0, a2
+; RV32-XQCICM-NEXT:    slt a2, a1, a3
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a6, a2, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a7, a2, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_sge:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bge a0, a1, .LBB21_2
@@ -947,6 +1129,17 @@ define i64 @select_i64_slt(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_slt:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a0, a2
+; RV32-XQCICM-NEXT:    slt a2, a1, a3
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a4, a2, 0, a6
+; RV32-XQCICM-NEXT:    qc.mveqi a5, a2, 0, a7
+; RV32-XQCICM-NEXT:    mv a0, a4
+; RV32-XQCICM-NEXT:    mv a1, a5
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_slt:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    blt a0, a1, .LBB22_2
@@ -997,6 +1190,17 @@ define i64 @select_i64_sle(i64 %a, i64 %b, i64 %x, i64 %y) nounwind {
 ; RV32-THEAD-NEXT:    mv a1, a5
 ; RV32-THEAD-NEXT:    ret
 ;
+; RV32-XQCICM-LABEL: select_i64_sle:
+; RV32-XQCICM:       # %bb.0:
+; RV32-XQCICM-NEXT:    sltu a0, a2, a0
+; RV32-XQCICM-NEXT:    slt a2, a3, a1
+; RV32-XQCICM-NEXT:    qc.mveq a2, a1, a3, a0
+; RV32-XQCICM-NEXT:    qc.mveqi a6, a2, 0, a4
+; RV32-XQCICM-NEXT:    qc.mveqi a7, a2, 0, a5
+; RV32-XQCICM-NEXT:    mv a0, a6
+; RV32-XQCICM-NEXT:    mv a1, a7
+; RV32-XQCICM-NEXT:    ret
+;
 ; RV64-LABEL: select_i64_sle:
 ; RV64:       # %bb.0:
 ; RV64-NEXT:    bge a1, a0, .LBB23_2
diff --git a/llvm/test/CodeGen/RISCV/xqcicm.ll b/llvm/test/CodeGen/RISCV/xqcicm.ll
new file mode 100644
index 0000000000000..4adb3dce265d1
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xqcicm.ll
@@ -0,0 +1,679 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test that we are able to generate the Xqcicm instructions
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32I
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcicm -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32IXQCICM
+
+define i32 @select_example(i32 %cond, i32 %x, i32 %y) {
+; RV32I-LABEL: select_example:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    andi a3, a0, 1
+; RV32I-NEXT:    mv a0, a1
+; RV32I-NEXT:    bnez a3, .LBB0_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:  .LBB0_2: # %entry
+; RV32I-NEXT:    ret
+;
+; RV32IXQCICM-LABEL: select_example:
+; RV32IXQCICM:       # %bb.0: # %entry
+; RV32IXQCICM-NEXT:    andi a0, a0, 1
+; RV32IXQCICM-NEXT:    qc.mveqi a1, a0, 0, a2
+; RV32IXQCICM-NEXT:    mv a0, a1
+; RV32IXQCICM-NEXT:    ret
+entry:
+  %cond_trunc = trunc i32 %cond to i1
+  %sel = select i1 %cond_trunc, i32 %x, i32 %y
+  ret i32 %sel
+}
+
+define i32 @select_cc_example_eq(i32 %a, i32 %b, i32 %x, i32 %y) {
+; RV32I-LABEL: select_cc_example_eq:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    li a1, 11
+; RV32I-NEXT:    beq a0, a1, .LBB1_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a2, a3
+; RV32I-NEXT:  .LBB1_2: # %entry
+; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:    ret
+;
+; RV32IXQCICM-LABEL: select_cc_example_eq:
+; RV32IXQCICM:       # %bb.0: # %entry
+; RV32IXQCICM-NEXT:    qc.mveqi a3, a0, 11, a2
+; RV32IXQCICM-NEXT:    mv a0, a3
+; RV32IXQCICM-NEXT:    ret
+entry:
+  %cmp = icmp eq i32 %a, 11
+  %sel = select i1 %cmp, i32 %x, i32 %y
+  ret i32 %sel
+}
+
+define i32 @select_cc_example_eq1(i32 %a, i32 %b, i32 %x, i32 %y) {
+; RV32I-LABEL: select_cc_example_eq1:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    li a1, 11
+; RV32I-NEXT:    beq a0, a1, .LBB2_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a2, a3
+; RV32I-NEXT:  .LBB2_2: # %entry
+; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:    ret
+;
+; RV32IXQCICM-LABEL: select_cc_example_eq1:
+; RV32IXQCICM:       # %bb.0: # %entry
+; RV32IXQCICM-NEXT:    qc.mveqi a3, a0, 11, a2
+; RV32IXQCICM-NEXT:    mv a0, a3
+; RV32IXQCICM-NEXT:    ret
+entry:
+  %cmp = icmp eq i32 11, %a
+  %sel = select i1 %cmp, i32 %x, i32 %y
+  ret i32 %sel
+}
+
+define i32 @select_cc_example_ne(i32 %a, i32 %b, i32 %x, i32 %y) {
+; RV32I-LABEL: select_cc_example_ne:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    li a1, 11
+; RV32I-NEXT:    bne a0, a1, .LBB3_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a2, a3
+; RV32I-NEXT:  .LBB3_2: # %entry
+; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:    ret
+;
+; RV32IXQCICM-LABEL: select_cc_example_ne:
+; RV32IXQCICM:       # %bb.0: # %entry
+; RV32IXQCICM-NEXT:    qc.mvnei a3, a0, 11, a2
+; RV32IXQCICM-NEXT:    mv a0, a3
+; RV32IXQCICM-NEXT:    ret
+entry:
+  %cmp = icmp ne i32 %a, 11
+  %sel = select i1 %cmp, i32 %x, i32 %y
+  ret i32 %sel
+}
+
+define i32 @select_cc_example_ne1(i32 %a, i32 %b, i32 %x, i32 %y) {
+; RV32I-LABEL: select_cc_example_ne1:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    li a1, 11
+; RV32I-NEXT:    bne a0, a1, .LBB4_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a2, a3
+; RV32I-NEXT:  .LBB4_2: # %entry
+; RV32I-NEXT:    mv a0, a2
+; RV32I-NEXT:    ret
+;
+; RV32IXQCICM-LABEL: select_cc_example_ne1:
+; RV32IXQCICM:       # %bb.0: # %entry
+; RV32IXQCICM-NEXT:    qc.mvnei a3, a0, 11, a2
+; RV32IXQCICM-NEXT:    mv a0, a3
+; RV32IXQCICM-NEXT:    ret
+entry:
+  %cmp = icmp ne i32 11, %a
+  %sel = select i1 %cmp, i32 %x, i32 %y
+  ret i32 %sel
+}
+
+define i32 @select_cc_example_slt(i32 %a, i32 %b, i32 %x, i32 %y) {
+; RV32I-LABEL: select_cc_example_slt:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    li a1, 11
+; RV32I-NEXT:    blt a0, a1, .LBB5_2
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    mv a2, a3
+; RV32I-NEXT:  .LBB5_2: # %entry
+; RV32I-NEXT:    mv a0...
[truncated]

@topperc
Copy link
Collaborator

topperc commented Jun 26, 2025

Will you be adding commuting support for the rd/rs3 sources? That should avoid some copies if rs3 is a better match for the destination register.

Change-Id: I3f8b9ef7f6a0b2ccc098743086412f1b39eb6639
@hchandel
Copy link
Contributor Author

hchandel commented Jun 27, 2025

Will you be adding commuting support for the rd/rs3 sources? That should avoid some copies if rs3 is a better match for the destination register.

I will do that in a follow-up PR.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@svs-quic svs-quic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@hchandel hchandel merged commit 950d281 into llvm:main Jun 27, 2025
7 checks passed
@hchandel hchandel deleted the XQCICM branch June 27, 2025 06:56
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jun 27, 2025

LLVM Buildbot has detected a new failure on builder lldb-x86_64-debian running on lldb-x86_64-debian while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/162/builds/25482

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-shell :: Process/Windows/process_load.cpp (3048 of 3059)
UNSUPPORTED: lldb-shell :: SymbolFile/PDB/type-quals.test (3049 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/no_threadState.test (3050 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/interactive_crashlog_invalid_target.test (3051 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/breakpoint_oneline_callback.test (3052 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/convenience_variables.test (3053 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Python/Crashlog/interactive_crashlog_arm64_register.test (3054 of 3059)
UNSUPPORTED: lldb-shell :: ScriptInterpreter/Lua/independent_state.test (3055 of 3059)
PASS: lldb-api :: terminal/TestEditlineCompletions.py (3056 of 3059)
UNRESOLVED: lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py (3057 of 3059)
******************** TEST 'lldb-api :: tools/lldb-dap/launch/TestDAP_launch.py' FAILED ********************
Script:
--
/usr/bin/python3 /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./lib --env LLVM_INCLUDE_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/include --env LLVM_TOOLS_DIR=/home/worker/2.0.1/lldb-x86_64-debian/build/./bin --arch x86_64 --build-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex --lldb-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/worker/2.0.1/lldb-x86_64-debian/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/lldb --compiler /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/clang --dsymutil /home/worker/2.0.1/lldb-x86_64-debian/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./bin --lldb-obj-root /home/worker/2.0.1/lldb-x86_64-debian/build/tools/lldb --lldb-libs-dir /home/worker/2.0.1/lldb-x86_64-debian/build/./lib --cmake-build-type Release -t /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch -p TestDAP_launch.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision 950d281eb2d42e53c05537965f714249a8e5084a)
  clang revision 950d281eb2d42e53c05537965f714249a8e5084a
  llvm revision 950d281eb2d42e53c05537965f714249a8e5084a
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
Change dir to: /home/worker/2.0.1/lldb-x86_64-debian/llvm-project/lldb/test/API/tools/lldb-dap/launch
runCmd: settings clear --all

output: 

runCmd: settings set symbols.enable-external-lookup false

output: 

runCmd: settings set target.inherit-tcc true

output: 

runCmd: settings set target.disable-aslr false

output: 

runCmd: settings set target.detach-on-error false

output: 

runCmd: settings set target.auto-apply-fixits false

rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
Add codegen patterns for the conditional move instructions in this
extension
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants