[llvm] [RISCV] Add ISel patterns for Xqciac QC_SHLADD instruction (PR #148256)
Sudharsan Veeravalli via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 12 00:18:18 PDT 2025
https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/148256
>From 2df6343497ea6330daec787e8b94eae7178dd98a Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Fri, 11 Jul 2025 21:29:19 +0530
Subject: [PATCH 1/3] [RISCV] Add ISel patterns for Xqciac QC_SHLADD
instruction
Add a couple of patterns to generate the Xqciac QC_SHLADD shift left accumulate instruction.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 12 +-
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 +
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 6 +
llvm/test/CodeGen/RISCV/xqciac.ll | 178 +++++++++++++++++++-
4 files changed, 191 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 456f3aedbf034..35658a2632540 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15025,10 +15025,13 @@ static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG,
// Optimize (add (shl x, c0), (shl y, c1)) ->
// (SLLI (SH*ADD x, y), c0), if c1-c0 equals to [1|2|3].
+// or
+// (SLLI (QC.SHLADD x, y, c1 - c0), c0), if 4 <= (c1-c0) <=31.
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
- // Perform this optimization only in the zba/xandesperf extension.
- if (!Subtarget.hasStdExtZba() && !Subtarget.hasVendorXAndesPerf())
+ // Perform this optimization only in the zba/xandesperf/xqciac extension.
+ if (!Subtarget.hasStdExtZba() && !Subtarget.hasVendorXAndesPerf() &&
+ !Subtarget.hasVendorXqciac())
return SDValue();
// Skip for vector types and larger types.
@@ -15056,7 +15059,10 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
// Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
int64_t Bits = std::min(C0, C1);
int64_t Diff = std::abs(C0 - C1);
- if (Diff != 1 && Diff != 2 && Diff != 3)
+ if (Diff != 1 && Diff != 2 && Diff != 3 && !Subtarget.hasVendorXqciac())
+ return SDValue();
+
+ if (!Diff || Diff > 31)
return SDValue();
// Build nodes.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 2723229859a55..c7019a65ec30c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -2823,6 +2823,9 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
case RISCVOp::OPERAND_UIMM5_NONZERO:
Ok = isUInt<5>(Imm) && (Imm != 0);
break;
+ case RISCVOp::OPERAND_UIMM5_GT3:
+ Ok = isUInt<5>(Imm) && (Imm > 3);
+ break;
case RISCVOp::OPERAND_UIMM5_PLUS1:
Ok = (isUInt<5>(Imm) && (Imm != 0)) || (Imm == 32);
break;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 9e3eb1c03fb37..6ca8d2737bd5f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1359,6 +1359,12 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
let Predicates = [HasVendorXqciac, IsRV32] in {
def : Pat<(XLenVT (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
+foreach i = 4-31 in {
+ def : Pat<(XLenVT (add_like_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)),
+ (QC_SHLADD GPR:$rs1, GPR:$rs2, i)>;
+ def : Pat<(XLenVT (riscv_shl_add GPR:$rs1, (XLenVT i), GPR:$rs2)),
+ (QC_SHLADD GPR:$rs1, GPR:$rs2, i)>;
+}
} // Predicates = [HasVendorXqciac, IsRV32]
/// Simple arithmetic operations
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index 4cee0910608f3..807c4ef48a3a3 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -222,7 +222,6 @@ entry:
ret i32 %add
}
-; NOTE: This will become qc.shladd once support is added
define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
; RV32IM-LABEL: pow2:
; RV32IM: # %bb.0: # %entry
@@ -232,14 +231,12 @@ define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
;
; RV32IMXQCIAC-LABEL: pow2:
; RV32IMXQCIAC: # %bb.0: # %entry
-; RV32IMXQCIAC-NEXT: slli a1, a1, 5
-; RV32IMXQCIAC-NEXT: add a0, a0, a1
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: pow2:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
-; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 5
-; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
; RV32IZBAMXQCIAC-NEXT: ret
entry:
%mul = mul nsw i32 %b, 32
@@ -269,3 +266,174 @@ entry:
%add = add nsw i32 %mul, %a
ret i32 %add
}
+
+define dso_local i32 @shladd(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladd:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a1, a1, 31
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladd:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladd:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shl = shl nsw i32 %b, 31
+ %add = add nsw i32 %shl, %a
+ ret i32 %add
+}
+
+define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladd64:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: srli a4, a2, 1
+; RV32IM-NEXT: slli a3, a3, 31
+; RV32IM-NEXT: slli a2, a2, 31
+; RV32IM-NEXT: or a3, a3, a4
+; RV32IM-NEXT: add a0, a2, a0
+; RV32IM-NEXT: sltu a2, a0, a2
+; RV32IM-NEXT: add a1, a3, a1
+; RV32IM-NEXT: add a1, a1, a2
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladd64:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: srli a4, a2, 1
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31
+; RV32IMXQCIAC-NEXT: slli a2, a2, 31
+; RV32IMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31
+; RV32IMXQCIAC-NEXT: sltu a2, a0, a2
+; RV32IMXQCIAC-NEXT: add a1, a1, a3
+; RV32IMXQCIAC-NEXT: add a1, a1, a2
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladd64:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: srli a4, a2, 1
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31
+; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 31
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31
+; RV32IZBAMXQCIAC-NEXT: sltu a2, a0, a2
+; RV32IZBAMXQCIAC-NEXT: add a1, a1, a3
+; RV32IZBAMXQCIAC-NEXT: add a1, a1, a2
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shl = shl nsw i64 %b, 31
+ %add = add nsw i64 %shl, %a
+ ret i64 %add
+}
+
+define dso_local i32 @shladd_ordisjoint(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladd_ordisjoint:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a1, a1, 22
+; RV32IM-NEXT: or a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladd_ordisjoint:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladd_ordisjoint:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shl = shl nsw i32 %b, 22
+ %or = or disjoint i32 %shl, %a
+ ret i32 %or
+}
+
+define dso_local i32 @shladdc1c2(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladdc1c2:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a0, a0, 31
+; RV32IM-NEXT: slli a1, a1, 26
+; RV32IM-NEXT: add a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladdc1c2:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
+; RV32IMXQCIAC-NEXT: slli a0, a0, 26
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladdc1c2:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
+; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 26
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shlc1 = shl nsw i32 %a, 31
+ %shlc2 = shl nsw i32 %b, 26
+ %add = add nsw i32 %shlc1, %shlc2
+ ret i32 %add
+}
+
+define dso_local i64 @shladdc1c264(i64 %a, i64 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladdc1c264:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a1, a0, 23
+; RV32IM-NEXT: srli a0, a2, 12
+; RV32IM-NEXT: slli a3, a3, 20
+; RV32IM-NEXT: or a3, a3, a0
+; RV32IM-NEXT: slli a0, a2, 20
+; RV32IM-NEXT: add a1, a1, a3
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladdc1c264:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: srli a1, a2, 12
+; RV32IMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20
+; RV32IMXQCIAC-NEXT: slli a2, a2, 20
+; RV32IMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23
+; RV32IMXQCIAC-NEXT: mv a0, a2
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladdc1c264:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: srli a1, a2, 12
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20
+; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 20
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23
+; RV32IZBAMXQCIAC-NEXT: mv a0, a2
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shlc1 = shl nsw i64 %a, 55
+ %shlc2 = shl nsw i64 %b, 20
+ %add = add nsw i64 %shlc1, %shlc2
+ ret i64 %add
+}
+
+define dso_local i32 @shladdc1equalc2(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shladdc1equalc2:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a0, a0, 12
+; RV32IM-NEXT: slli a1, a1, 12
+; RV32IM-NEXT: add a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shladdc1equalc2:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: slli a1, a1, 12
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shladdc1equalc2:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 12
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shlc1 = shl nsw i32 %a, 12
+ %shlc2 = shl nsw i32 %b, 12
+ %add = add nsw i32 %shlc1, %shlc2
+ ret i32 %add
+}
>From 36c06fb2357b01c0bbafe26ea283443d052b306c Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Sat, 12 Jul 2025 08:46:30 +0530
Subject: [PATCH 2/3] Fix tests
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +-
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 4 +--
llvm/test/CodeGen/RISCV/xqciac.ll | 36 ++++++++++-----------
3 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 35658a2632540..a38723f2b2e17 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15062,7 +15062,7 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
if (Diff != 1 && Diff != 2 && Diff != 3 && !Subtarget.hasVendorXqciac())
return SDValue();
- if (!Diff || Diff > 31)
+ if (Diff == 0 || Diff > 31)
return SDValue();
// Build nodes.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index 6ca8d2737bd5f..bfd55e9e57be1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1361,9 +1361,9 @@ def : Pat<(XLenVT (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
foreach i = 4-31 in {
def : Pat<(XLenVT (add_like_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)),
- (QC_SHLADD GPR:$rs1, GPR:$rs2, i)>;
+ (QC_SHLADD GPR:$rs2, GPR:$rs1, i)>;
def : Pat<(XLenVT (riscv_shl_add GPR:$rs1, (XLenVT i), GPR:$rs2)),
- (QC_SHLADD GPR:$rs1, GPR:$rs2, i)>;
+ (QC_SHLADD GPR:$rs2, GPR:$rs1, i)>;
}
} // Predicates = [HasVendorXqciac, IsRV32]
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index 807c4ef48a3a3..9a946f0455437 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -231,12 +231,12 @@ define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
;
; RV32IMXQCIAC-LABEL: pow2:
; RV32IMXQCIAC: # %bb.0: # %entry
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: pow2:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
; RV32IZBAMXQCIAC-NEXT: ret
entry:
%mul = mul nsw i32 %b, 32
@@ -276,12 +276,12 @@ define dso_local i32 @shladd(i32 %a, i32 %b) local_unnamed_addr #0 {
;
; RV32IMXQCIAC-LABEL: shladd:
; RV32IMXQCIAC: # %bb.0: # %entry
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: shladd:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 31
; RV32IZBAMXQCIAC-NEXT: ret
entry:
%shl = shl nsw i32 %b, 31
@@ -305,9 +305,9 @@ define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 {
; RV32IMXQCIAC-LABEL: shladd64:
; RV32IMXQCIAC: # %bb.0: # %entry
; RV32IMXQCIAC-NEXT: srli a4, a2, 1
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31
; RV32IMXQCIAC-NEXT: slli a2, a2, 31
-; RV32IMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31
+; RV32IMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31
; RV32IMXQCIAC-NEXT: sltu a2, a0, a2
; RV32IMXQCIAC-NEXT: add a1, a1, a3
; RV32IMXQCIAC-NEXT: add a1, a1, a2
@@ -316,9 +316,9 @@ define dso_local i64 @shladd64(i64 %a, i64 %b) local_unnamed_addr #0 {
; RV32IZBAMXQCIAC-LABEL: shladd64:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
; RV32IZBAMXQCIAC-NEXT: srli a4, a2, 1
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a2, a0, 31
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a2, 31
; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 31
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a3, a4, 31
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a3, a4, a3, 31
; RV32IZBAMXQCIAC-NEXT: sltu a2, a0, a2
; RV32IZBAMXQCIAC-NEXT: add a1, a1, a3
; RV32IZBAMXQCIAC-NEXT: add a1, a1, a2
@@ -338,12 +338,12 @@ define dso_local i32 @shladd_ordisjoint(i32 %a, i32 %b) local_unnamed_addr #0 {
;
; RV32IMXQCIAC-LABEL: shladd_ordisjoint:
; RV32IMXQCIAC: # %bb.0: # %entry
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: shladd_ordisjoint:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 22
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 22
; RV32IZBAMXQCIAC-NEXT: ret
entry:
%shl = shl nsw i32 %b, 22
@@ -361,13 +361,13 @@ define dso_local i32 @shladdc1c2(i32 %a, i32 %b) local_unnamed_addr #0 {
;
; RV32IMXQCIAC-LABEL: shladdc1c2:
; RV32IMXQCIAC: # %bb.0: # %entry
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
; RV32IMXQCIAC-NEXT: slli a0, a0, 26
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: shladdc1c2:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 5
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 5
; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 26
; RV32IZBAMXQCIAC-NEXT: ret
entry:
@@ -391,18 +391,18 @@ define dso_local i64 @shladdc1c264(i64 %a, i64 %b) local_unnamed_addr #0 {
; RV32IMXQCIAC-LABEL: shladdc1c264:
; RV32IMXQCIAC: # %bb.0: # %entry
; RV32IMXQCIAC-NEXT: srli a1, a2, 12
-; RV32IMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20
+; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20
; RV32IMXQCIAC-NEXT: slli a2, a2, 20
-; RV32IMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23
+; RV32IMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23
; RV32IMXQCIAC-NEXT: mv a0, a2
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: shladdc1c264:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
; RV32IZBAMXQCIAC-NEXT: srli a1, a2, 12
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a3, a1, 20
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a3, 20
; RV32IZBAMXQCIAC-NEXT: slli a2, a2, 20
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a0, a1, 23
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a1, a1, a0, 23
; RV32IZBAMXQCIAC-NEXT: mv a0, a2
; RV32IZBAMXQCIAC-NEXT: ret
entry:
@@ -423,13 +423,13 @@ define dso_local i32 @shladdc1equalc2(i32 %a, i32 %b) local_unnamed_addr #0 {
; RV32IMXQCIAC-LABEL: shladdc1equalc2:
; RV32IMXQCIAC: # %bb.0: # %entry
; RV32IMXQCIAC-NEXT: slli a1, a1, 12
-; RV32IMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12
; RV32IMXQCIAC-NEXT: ret
;
; RV32IZBAMXQCIAC-LABEL: shladdc1equalc2:
; RV32IZBAMXQCIAC: # %bb.0: # %entry
; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 12
-; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a1, 12
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a1, a0, 12
; RV32IZBAMXQCIAC-NEXT: ret
entry:
%shlc1 = shl nsw i32 %a, 12
>From 9b222ff4b28ed57d3f6f8a4f3d4d1e604dca3106 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Sat, 12 Jul 2025 12:42:21 +0530
Subject: [PATCH 3/3] Fix pattern add test
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 17 ++++++++++----
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 10 ++++----
llvm/test/CodeGen/RISCV/xqciac.ll | 26 +++++++++++++++++++++
3 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index a38723f2b2e17..e74f35ac4c0e8 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15029,9 +15029,11 @@ static SDValue combineBinOpToReduce(SDNode *N, SelectionDAG &DAG,
// (SLLI (QC.SHLADD x, y, c1 - c0), c0), if 4 <= (c1-c0) <=31.
static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
+ const bool HasStdExtZba = Subtarget.hasStdExtZba();
+ const bool HasVendorXAndesPerf = Subtarget.hasVendorXAndesPerf();
+ const bool HasVendorXqciac = Subtarget.hasVendorXqciac();
// Perform this optimization only in the zba/xandesperf/xqciac extension.
- if (!Subtarget.hasStdExtZba() && !Subtarget.hasVendorXAndesPerf() &&
- !Subtarget.hasVendorXqciac())
+ if (!HasStdExtZba && !HasVendorXAndesPerf && !HasVendorXqciac)
return SDValue();
// Skip for vector types and larger types.
@@ -15056,17 +15058,22 @@ static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
if (C0 <= 0 || C1 <= 0)
return SDValue();
- // Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
- int64_t Bits = std::min(C0, C1);
int64_t Diff = std::abs(C0 - C1);
- if (Diff != 1 && Diff != 2 && Diff != 3 && !Subtarget.hasVendorXqciac())
+ bool IsShXaddDiff = Diff == 1 || Diff == 2 || Diff == 3;
+ bool HasShXadd = HasStdExtZba || HasVendorXAndesPerf;
+
+ // Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
+ if ((!IsShXaddDiff && HasShXadd && !HasVendorXqciac) ||
+ (IsShXaddDiff && !HasShXadd && HasVendorXqciac))
return SDValue();
+ // Skip if QC_SHLADD is not applicable.
if (Diff == 0 || Diff > 31)
return SDValue();
// Build nodes.
SDLoc DL(N);
+ int64_t Bits = std::min(C0, C1);
SDValue NS = (C0 < C1) ? N0->getOperand(0) : N1->getOperand(0);
SDValue NL = (C0 > C1) ? N0->getOperand(0) : N1->getOperand(0);
SDValue SHADD = DAG.getNode(RISCVISD::SHL_ADD, DL, VT, NL,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index bfd55e9e57be1..84475e1d8961b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1359,12 +1359,10 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
let Predicates = [HasVendorXqciac, IsRV32] in {
def : Pat<(XLenVT (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
-foreach i = 4-31 in {
- def : Pat<(XLenVT (add_like_non_imm12 (shl GPR:$rs1, (XLenVT i)), GPR:$rs2)),
- (QC_SHLADD GPR:$rs2, GPR:$rs1, i)>;
- def : Pat<(XLenVT (riscv_shl_add GPR:$rs1, (XLenVT i), GPR:$rs2)),
- (QC_SHLADD GPR:$rs2, GPR:$rs1, i)>;
-}
+def : Pat<(i32 (add_like_non_imm12 (shl GPRNoX0:$rs1, uimm5gt3:$imm), GPRNoX0:$rs2)),
+ (QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>;
+def : Pat<(i32 (riscv_shl_add GPRNoX0:$rs1, uimm5gt3:$imm, GPRNoX0:$rs2)),
+ (QC_SHLADD GPRNoX0:$rs2, GPRNoX0:$rs1, uimm5gt3:$imm)>;
} // Predicates = [HasVendorXqciac, IsRV32]
/// Simple arithmetic operations
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index 9a946f0455437..a3b4e7829a51d 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -377,6 +377,32 @@ entry:
ret i32 %add
}
+define dso_local i32 @shxaddc1c2(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shxaddc1c2:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a0, a0, 31
+; RV32IM-NEXT: slli a1, a1, 28
+; RV32IM-NEXT: add a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shxaddc1c2:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: slli a1, a1, 28
+; RV32IMXQCIAC-NEXT: qc.shladd a0, a1, a0, 31
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shxaddc1c2:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: sh3add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT: slli a0, a0, 28
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %shlc1 = shl nsw i32 %a, 31
+ %shlc2 = shl nsw i32 %b, 28
+ %add = add nsw i32 %shlc1, %shlc2
+ ret i32 %add
+}
+
define dso_local i64 @shladdc1c264(i64 %a, i64 %b) local_unnamed_addr #0 {
; RV32IM-LABEL: shladdc1c264:
; RV32IM: # %bb.0: # %entry
More information about the llvm-commits
mailing list