[llvm] [RISCV] Add ISel patterns for Xqcia instructions (PR #136548)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 21 02:00:03 PDT 2025


https://github.com/hchandel updated https://github.com/llvm/llvm-project/pull/136548

>From 850bdc72403aa2efa2700a30516e2ccc848ee95c Mon Sep 17 00:00:00 2001
From: Harsh Chandel <quic_hchandel at quicinc.com>
Date: Mon, 21 Apr 2025 12:22:35 +0530
Subject: [PATCH 1/3] [RISCV] Add ISel patterns for Xqcia instructions This
 patch adds instruction selection patterns for generating the integer
 arithmetic instructions.

Change-Id: I544fe4b35403f51d4e2860aca5bae9f7a353167f
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |   8 ++
 llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td |  13 ++
 llvm/test/CodeGen/RISCV/xqcia.ll            | 128 ++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/xqcia.ll

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 98fba9e86e88a..45320d28b9253 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -421,6 +421,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SELECT, XLenVT, Legal);
   else if (!Subtarget.hasVendorXTHeadCondMov())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
+  if (Subtarget.hasVendorXqcia()){
+    setOperationAction(ISD::UADDSAT, MVT::i32, Legal);
+    setOperationAction(ISD::SADDSAT, MVT::i32, Legal);
+    setOperationAction(ISD::USUBSAT, MVT::i32, Legal);
+    setOperationAction(ISD::SSUBSAT, MVT::i32, Legal);
+    setOperationAction(ISD::SSHLSAT, MVT::i32, Legal);
+    setOperationAction(ISD::USHLSAT, MVT::i32, Legal);
+  }
 
   static const unsigned FPLegalNodeTypes[] = {
       ISD::FMINNUM,       ISD::FMAXNUM,        ISD::FMINIMUMNUM,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index bb0818b001d38..741c4ce8f5d1e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1247,6 +1247,10 @@ class PatGprNoX0Simm32NoSimm26<SDPatternOperator OpNode, RVInst48 Inst>
     : Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), simm32_nosimm26:$imm)),
           (Inst GPRNoX0:$rs1, simm32_nosimm26:$imm)>;
 
+class PatGprNoX0GprNoX0<SDPatternOperator OpNode, RVInstR Inst>
+    : Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2))),
+          (Inst GPRNoX0:$rs1, GPRNoX0:$rs2)>;
+
 class QC48LdPat<PatFrag LoadOp, RVInst48 Inst>
     : Pat<(i32 (LoadOp (AddLike (i32 GPR:$rs1), simm26_nosimm12:$imm26))),
           (Inst GPR:$rs1, simm26_nosimm12:$imm26)>;
@@ -1308,5 +1312,14 @@ let Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1 in {
   def : QCScaledStPat<store, QC_SRW>;
 } // Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1
 
+let Predicates = [HasVendorXqcia, IsRV32] in {
+def : PatGprNoX0GprNoX0<saddsat, QC_ADDSAT>;
+def : PatGprNoX0GprNoX0<uaddsat, QC_ADDUSAT>;
+def : PatGprNoX0GprNoX0<ssubsat, QC_SUBSAT>;
+def : PatGprNoX0GprNoX0<usubsat, QC_SUBUSAT>;
+def : PatGprNoX0GprNoX0<ushlsat, QC_SHLUSAT>;
+def : PatGprNoX0GprNoX0<sshlsat, QC_SHLSAT>;
+} // Predicates = [HasVendorXqcia, IsRV32]
+
 let Predicates = [HasVendorXqciint, IsRV32] in
 def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;
diff --git a/llvm/test/CodeGen/RISCV/xqcia.ll b/llvm/test/CodeGen/RISCV/xqcia.ll
new file mode 100644
index 0000000000000..6a353c358d037
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xqcia.ll
@@ -0,0 +1,128 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; Test that we are able to generate the Xqcia instructions
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32I
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefixes=RV32IXQCIA
+
+define i32 @addsat(i32 %a, i32 %b) {
+; RV32I-LABEL: addsat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    mv a2, a0
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    slt a2, a0, a2
+; RV32I-NEXT:    slti a1, a1, 0
+; RV32I-NEXT:    beq a1, a2, .LBB0_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    srai a0, a0, 31
+; RV32I-NEXT:    lui a1, 524288
+; RV32I-NEXT:    xor a0, a0, a1
+; RV32I-NEXT:  .LBB0_2:
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: addsat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.addsat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.sadd.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}
+
+define i32 @addusat(i32 %a, i32 %b) {
+; RV32I-LABEL: addusat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    add a1, a0, a1
+; RV32I-NEXT:    sltu a0, a1, a0
+; RV32I-NEXT:    neg a0, a0
+; RV32I-NEXT:    or a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: addusat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.addusat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.uadd.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}
+
+define i32 @subsat(i32 %a, i32 %b) {
+; RV32I-LABEL: subsat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    mv a2, a0
+; RV32I-NEXT:    sgtz a3, a1
+; RV32I-NEXT:    sub a0, a0, a1
+; RV32I-NEXT:    slt a1, a0, a2
+; RV32I-NEXT:    beq a3, a1, .LBB2_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    srai a0, a0, 31
+; RV32I-NEXT:    lui a1, 524288
+; RV32I-NEXT:    xor a0, a0, a1
+; RV32I-NEXT:  .LBB2_2:
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: subsat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.subsat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.ssub.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}
+
+define i32 @subusat(i32 %a, i32 %b) {
+; RV32I-LABEL: subusat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    sub a1, a0, a1
+; RV32I-NEXT:    sltu a0, a0, a1
+; RV32I-NEXT:    addi a0, a0, -1
+; RV32I-NEXT:    and a0, a0, a1
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: subusat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.subusat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.usub.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}
+
+define i32 @shlusat(i32 %a, i32 %b) {
+; RV32I-LABEL: shlusat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    sll a2, a0, a1
+; RV32I-NEXT:    srl a1, a2, a1
+; RV32I-NEXT:    xor a0, a0, a1
+; RV32I-NEXT:    seqz a0, a0
+; RV32I-NEXT:    addi a0, a0, -1
+; RV32I-NEXT:    or a0, a0, a2
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: shlusat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.shlusat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.ushl.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}
+
+define i32 @shlsat(i32 %a, i32 %b) {
+; RV32I-LABEL: shlsat:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    mv a2, a0
+; RV32I-NEXT:    sll a0, a0, a1
+; RV32I-NEXT:    sra a1, a0, a1
+; RV32I-NEXT:    beq a2, a1, .LBB5_2
+; RV32I-NEXT:  # %bb.1:
+; RV32I-NEXT:    srai a2, a2, 31
+; RV32I-NEXT:    lui a0, 524288
+; RV32I-NEXT:    addi a0, a0, -1
+; RV32I-NEXT:    xor a0, a2, a0
+; RV32I-NEXT:  .LBB5_2:
+; RV32I-NEXT:    ret
+;
+; RV32IXQCIA-LABEL: shlsat:
+; RV32IXQCIA:       # %bb.0:
+; RV32IXQCIA-NEXT:    qc.shlsat a0, a0, a1
+; RV32IXQCIA-NEXT:    ret
+ %addai = tail call i32 @llvm.sshl.sat.i32(i32 %a,i32 %b)
+ ret i32 %addai
+}

>From 5860e7f04238c6972bf6a183349e7180d1bf7ab5 Mon Sep 17 00:00:00 2001
From: Harsh Chandel <quic_hchandel at quicinc.com>
Date: Mon, 21 Apr 2025 14:15:21 +0530
Subject: [PATCH 2/3] fixup! Minor changes

Change-Id: I240a028c2fc37f239faa62e1215cd89d79e89e42
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp |  1 +
 llvm/test/CodeGen/RISCV/xqcia.ll            | 24 ++++++++++-----------
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 45320d28b9253..d4ca9f48b7aef 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -421,6 +421,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::SELECT, XLenVT, Legal);
   else if (!Subtarget.hasVendorXTHeadCondMov())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
+
   if (Subtarget.hasVendorXqcia()){
     setOperationAction(ISD::UADDSAT, MVT::i32, Legal);
     setOperationAction(ISD::SADDSAT, MVT::i32, Legal);
diff --git a/llvm/test/CodeGen/RISCV/xqcia.ll b/llvm/test/CodeGen/RISCV/xqcia.ll
index 6a353c358d037..c75bb9daefcf2 100644
--- a/llvm/test/CodeGen/RISCV/xqcia.ll
+++ b/llvm/test/CodeGen/RISCV/xqcia.ll
@@ -24,8 +24,8 @@ define i32 @addsat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.addsat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.sadd.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %saddsat = tail call i32 @llvm.sadd.sat.i32(i32 %a,i32 %b)
+ ret i32 %saddsat
 }
 
 define i32 @addusat(i32 %a, i32 %b) {
@@ -41,8 +41,8 @@ define i32 @addusat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.addusat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.uadd.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %uaddsat = tail call i32 @llvm.uadd.sat.i32(i32 %a,i32 %b)
+ ret i32 %uaddsat
 }
 
 define i32 @subsat(i32 %a, i32 %b) {
@@ -64,8 +64,8 @@ define i32 @subsat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.subsat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.ssub.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %ssubsat = tail call i32 @llvm.ssub.sat.i32(i32 %a,i32 %b)
+ ret i32 %ssubsat
 }
 
 define i32 @subusat(i32 %a, i32 %b) {
@@ -81,8 +81,8 @@ define i32 @subusat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.subusat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.usub.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %usubsat = tail call i32 @llvm.usub.sat.i32(i32 %a,i32 %b)
+ ret i32 %usubsat
 }
 
 define i32 @shlusat(i32 %a, i32 %b) {
@@ -100,8 +100,8 @@ define i32 @shlusat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.shlusat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.ushl.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %ushlsat = tail call i32 @llvm.ushl.sat.i32(i32 %a,i32 %b)
+ ret i32 %ushlsat
 }
 
 define i32 @shlsat(i32 %a, i32 %b) {
@@ -123,6 +123,6 @@ define i32 @shlsat(i32 %a, i32 %b) {
 ; RV32IXQCIA:       # %bb.0:
 ; RV32IXQCIA-NEXT:    qc.shlsat a0, a0, a1
 ; RV32IXQCIA-NEXT:    ret
- %addai = tail call i32 @llvm.sshl.sat.i32(i32 %a,i32 %b)
- ret i32 %addai
+ %sshlsat = tail call i32 @llvm.sshl.sat.i32(i32 %a,i32 %b)
+ ret i32 %sshlsat
 }

>From 8284d625b99b94d017b0f2b963a831dfaf16842b Mon Sep 17 00:00:00 2001
From: Harsh Chandel <quic_hchandel at quicinc.com>
Date: Mon, 21 Apr 2025 14:29:28 +0530
Subject: [PATCH 3/3] fixup! clang format

Change-Id: Iebfd125316008441d23de14c4ceecdcfa0042a97
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index d4ca9f48b7aef..d7b78fecd0649 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -422,7 +422,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
   else if (!Subtarget.hasVendorXTHeadCondMov())
     setOperationAction(ISD::SELECT, XLenVT, Custom);
 
-  if (Subtarget.hasVendorXqcia()){
+  if (Subtarget.hasVendorXqcia()) {
     setOperationAction(ISD::UADDSAT, MVT::i32, Legal);
     setOperationAction(ISD::SADDSAT, MVT::i32, Legal);
     setOperationAction(ISD::USUBSAT, MVT::i32, Legal);



More information about the llvm-commits mailing list