diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 98b613d9cc856..da329a8047a42 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -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(); + if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt)) + return SDValue(); + uint64_t MulAmtLowBit = MulAmt & (-MulAmt); ISD::NodeType Op; uint64_t ShiftAmt1; @@ -23700,6 +23706,10 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, auto *ConstNode = cast(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 (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 +}