[llvm] [RISCV] Add ISel patterns for Xqciac QC.MULIADD instruction (PR #147661)
Sudharsan Veeravalli via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 10 08:29:21 PDT 2025
https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/147661
>From 8e748ac033539f8e9523c7c09398856444bbb1a8 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Wed, 9 Jul 2025 11:57:31 +0530
Subject: [PATCH 1/3] [RISCV] Add ISel patterns for Xqciac QC.MULIADD
instruction
Add basic isel patterns for the multiple accumulate QC.MULIADD instruction.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 11 ++
llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td | 5 +
llvm/test/CodeGen/RISCV/xqciac.ll | 177 ++++++++++++++++++++
3 files changed, 193 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/xqciac.ll
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 98b613d9cc856..f586ff609ca16 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15895,6 +15895,13 @@ static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG,
// X * (2^N +/- 2^M) -> (add/sub (shl X, C1), (shl X, C2))
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG,
uint64_t MulAmt) {
+ // Don't do this is if the Xqciac extension is enabled and the MulAmt is
+ // simm12.
+ const RISCVSubtarget &Subtarget =
+ DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
+ if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt))
+ return SDValue();
+
uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
ISD::NodeType Op;
uint64_t ShiftAmt1;
@@ -23700,6 +23707,10 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
auto *ConstNode = cast<ConstantSDNode>(C);
const APInt &Imm = ConstNode->getAPIntValue();
+ // Don't do this if the Xqciac extension is enabled and the Imm in simm12.
+ if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
+ return false;
+
// Break the MUL to a SLLI and an ADD/SUB.
if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
(1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
index b2bf09028bc40..3d0712baf6940 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
@@ -1332,6 +1332,11 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
(OpNode GPRNoX0:$lhs, InTyImm:$Constant,
(IntCCtoRISCVCC $cc), GPRNoX0:$truev, GPRNoX0:$falsev)>;
+let Predicates = [HasVendorXqciac, IsRV32] in {
+def : Pat<(XLenVT (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
+ (QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
+} // Predicates = [HasVendorXqciac, IsRV32]
+
/// Simple arithmetic operations
let Predicates = [HasVendorXqcilia, IsRV32] in {
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
new file mode 100644
index 0000000000000..2822d1a98afea
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -0,0 +1,177 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=riscv32 -mattr=+m -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32IM
+; RUN: llc -mtriple=riscv32 -mattr=+m,+experimental-xqciac -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32IMXQCIAC
+; RUN: llc -mtriple=riscv32 -mattr=+m,+experimental-xqciac,+zba -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32IZBAMXQCIAC
+
+define dso_local i32 @mul(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: mul:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a0, a1, 5
+; RV32IM-NEXT: add a0, a0, a1
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: mul:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: li a0, 33
+; RV32IMXQCIAC-NEXT: mul a0, a1, a0
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: mul:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: li a0, 33
+; RV32IZBAMXQCIAC-NEXT: mul a0, a1, a0
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 33
+ ret i32 %mul
+}
+
+define dso_local i32 @muliadd(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: muliadd:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: li a2, 165
+; RV32IM-NEXT: mul a1, a1, a2
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: muliadd:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 165
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: muliadd:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 165
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 165
+ %add = add nsw i32 %mul, %a
+ ret i32 %add
+}
+
+define dso_local i32 @muliadd_neg(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: muliadd_neg:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: li a2, -165
+; RV32IM-NEXT: mul a1, a1, a2
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: muliadd_neg:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, -165
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: muliadd_neg:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, -165
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, -165
+ %add = add nsw i32 %mul, %a
+ ret i32 %add
+}
+
+define dso_local i32 @pow2immplus1(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: pow2immplus1:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a2, a1, 5
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: add a0, a2, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: pow2immplus1:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 33
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: pow2immplus1:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 33
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 33
+ %add = add nsw i32 %mul, %a
+ ret i32 %add
+}
+
+define dso_local i32 @gtsimm12(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: gtsimm12:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: lui a2, 1
+; RV32IM-NEXT: addi a2, a2, 477
+; RV32IM-NEXT: mul a1, a1, a2
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: gtsimm12:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: lui a2, 1
+; RV32IMXQCIAC-NEXT: addi a2, a2, 477
+; RV32IMXQCIAC-NEXT: mul a1, a1, a2
+; RV32IMXQCIAC-NEXT: add a0, a0, a1
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: gtsimm12:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: lui a2, 1
+; RV32IZBAMXQCIAC-NEXT: addi a2, a2, 477
+; RV32IZBAMXQCIAC-NEXT: mul a1, a1, a2
+; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 4573
+ %add = add nsw i32 %mul, %a
+ 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
+; RV32IM-NEXT: slli a1, a1, 5
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: pow2:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: slli a1, a1, 5
+; RV32IMXQCIAC-NEXT: add a0, a0, a1
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: pow2:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 5
+; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 32
+ %add = add nsw i32 %mul, %a
+ ret i32 %add
+}
+
+define dso_local i32 @shxadd(i32 %a, i32 %b) local_unnamed_addr #0 {
+; RV32IM-LABEL: shxadd:
+; RV32IM: # %bb.0: # %entry
+; RV32IM-NEXT: slli a1, a1, 1
+; RV32IM-NEXT: add a0, a1, a0
+; RV32IM-NEXT: ret
+;
+; RV32IMXQCIAC-LABEL: shxadd:
+; RV32IMXQCIAC: # %bb.0: # %entry
+; RV32IMXQCIAC-NEXT: slli a1, a1, 1
+; RV32IMXQCIAC-NEXT: add a0, a0, a1
+; RV32IMXQCIAC-NEXT: ret
+;
+; RV32IZBAMXQCIAC-LABEL: shxadd:
+; RV32IZBAMXQCIAC: # %bb.0: # %entry
+; RV32IZBAMXQCIAC-NEXT: sh1add a0, a1, a0
+; RV32IZBAMXQCIAC-NEXT: ret
+entry:
+ %mul = mul nsw i32 %b, 2
+ %add = add nsw i32 %mul, %a
+ ret i32 %add
+}
>From 0201aea0adcfc0d8c44b46a0c582497b6d9b07e3 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Wed, 9 Jul 2025 15:49:49 +0530
Subject: [PATCH 2/3] getSubtarget
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f586ff609ca16..da329a8047a42 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15897,8 +15897,7 @@ static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG,
uint64_t MulAmt) {
// Don't do this is if the Xqciac extension is enabled and the MulAmt is
// simm12.
- const RISCVSubtarget &Subtarget =
- DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
+ auto &Subtarget = DAG.getSubtarget<RISCVSubtarget>();
if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt))
return SDValue();
>From bf0aca9748717ff551fe5d50e6195c0b91829b15 Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Thu, 10 Jul 2025 06:40:48 +0530
Subject: [PATCH 3/3] Pass subtarget from caller
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index da329a8047a42..8a4e8f967cfcf 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -15894,10 +15894,8 @@ static SDValue expandMulToNAFSequence(SDNode *N, SelectionDAG &DAG,
// X * (2^N +/- 2^M) -> (add/sub (shl X, C1), (shl X, C2))
static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG,
- uint64_t MulAmt) {
- // Don't do this is if the Xqciac extension is enabled and the MulAmt is
- // simm12.
- auto &Subtarget = DAG.getSubtarget<RISCVSubtarget>();
+ uint64_t MulAmt,
+ const RISCVSubtarget &Subtarget) {
if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt))
return SDValue();
@@ -16085,7 +16083,7 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG,
}
}
- if (SDValue V = expandMulToAddOrSubOfShl(N, DAG, MulAmt))
+ if (SDValue V = expandMulToAddOrSubOfShl(N, DAG, MulAmt, Subtarget))
return V;
if (!Subtarget.hasStdExtZmmul())
More information about the llvm-commits
mailing list