Skip to content

[RISCV] Add ISel patterns for Xqciac QC.MULIADD instruction #147661

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15895,6 +15895,12 @@ 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>();
if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt))
return SDValue();

uint64_t MulAmtLowBit = MulAmt & (-MulAmt);
ISD::NodeType Op;
uint64_t ShiftAmt1;
Expand Down Expand Up @@ -23700,6 +23706,10 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
auto *ConstNode = cast<ConstantSDNode>(C);
const APInt &Imm = ConstNode->getAPIntValue();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe I can do this is DAG-DAG to combine them back into muliadd so that we expand mul here when there is not accumulate. Or I can leave this here since expandMulToAddOrSubOfShl will run later and try to do the same thing.

Probably as a follow-up.

// 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())
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
177 changes: 177 additions & 0 deletions llvm/test/CodeGen/RISCV/xqciac.ll
Original file line number Diff line number Diff line change
@@ -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
}