[llvm] [RISCV][P-ext] Custom lower v8i8 mulh* on RV64. NFC (PR #218160)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 22 13:24:10 PDT 2026
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/218160
Assisted-by: Claude
>From 5ced921c30be23e75b62fcff65e37b4b3570e028 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 21 Aug 2026 23:26:23 -0700
Subject: [PATCH] [RISCV][P-ext] Custom lower v8i8 mulh* on RV64. NFC
Assisted-by: Claude
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 44 ++++++++++++++++++++-
llvm/lib/Target/RISCV/RISCVInstrInfoP.td | 33 ++++++++++------
2 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 9406b697882d7..0fdadff79b5e3 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -724,7 +724,10 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::INSERT_SUBVECTOR, {MVT::v4i16, MVT::v8i8},
Custom);
} else {
- setOperationAction({ISD::MUL, ISD::MULHS, ISD::MULHU}, P64VecVTs, Legal);
+ setOperationAction(ISD::MUL, P64VecVTs, Legal);
+ setOperationAction({ISD::MULHS, ISD::MULHU}, {MVT::v2i32, MVT::v4i16},
+ Legal);
+ setOperationAction({ISD::MULHS, ISD::MULHU}, MVT::v8i8, Custom);
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG,
{MVT::v4i16, MVT::v2i32}, Legal);
setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, {MVT::v4i16, MVT::v2i32},
@@ -9439,6 +9442,22 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
}
return DAG.getNode(ISD::TRUNCATE, DL, VT, Res);
}
+ // Lower v8i8 MULHS/MULHU on RV64 via a pair of widening byte multiplies
+ // (picking out the even/odd result lanes) recombined with PPAIRO.
+ if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8 &&
+ Opc != ISD::MUL) {
+ SDLoc DL(Op);
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ unsigned LoOpc =
+ Opc == ISD::MULHU ? RISCVISD::PMULU_H_B00 : RISCVISD::PMUL_H_B00;
+ unsigned HiOpc =
+ Opc == ISD::MULHU ? RISCVISD::PMULU_H_B11 : RISCVISD::PMUL_H_B11;
+ SDValue Lo = DAG.getNode(LoOpc, DL, MVT::v4i16, LHS, RHS);
+ SDValue Hi = DAG.getNode(HiOpc, DL, MVT::v4i16, LHS, RHS);
+ return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
+ DAG.getBitcast(VT, Hi));
+ }
return lowerToScalableOp(Op, DAG);
}
case ISD::ANY_EXTEND_VECTOR_INREG: {
@@ -17737,7 +17756,8 @@ static SDValue combineAddMulh(SDNode *N, SelectionDAG &DAG,
bool IsPExtPackedDoubleType =
VT.isSimple() && Subtarget.isPExtPackedDoubleType(VT.getSimpleVT());
if (!TLI.isOperationLegal(ISD::MULHS, VT) && !IsPExtPackedDoubleType &&
- !(Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::v4i8))
+ !(Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::v4i8) &&
+ !(Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8))
return SDValue();
using namespace SDPatternMatch;
@@ -17780,6 +17800,16 @@ static SDValue combineAddMulh(SDNode *N, SelectionDAG &DAG,
if (Subtarget.hasStdExtP() && !Subtarget.is64Bit() && VT == MVT::v4i8)
return MakePWMulSU(X, Mulh.getOperand(1));
+ // We don't have a v8i8 MULHSU instruction on RV64 either; build it from a
+ // pair of widening byte multiplies recombined with PPAIRO.
+ if (Subtarget.hasStdExtP() && Subtarget.is64Bit() && VT == MVT::v8i8) {
+ SDValue C = Mulh.getOperand(1);
+ SDValue Lo = DAG.getNode(RISCVISD::PMULSU_H_B00, DL, MVT::v4i16, X, C);
+ SDValue Hi = DAG.getNode(RISCVISD::PMULSU_H_B11, DL, MVT::v4i16, X, C);
+ return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
+ DAG.getBitcast(VT, Hi));
+ }
+
return DAG.getNode(RISCVISD::MULHSU, DL, VT, X, Mulh.getOperand(1));
}
@@ -18174,6 +18204,16 @@ static SDValue combinePExtTruncate(SDNode *N, SelectionDAG &DAG,
SDValue Hi = DAG.getNode(Opc, DL, MVT::i32, AHi, BHi);
return DAG.getNode(ISD::BUILD_VECTOR, DL, VT, Lo, Hi);
}
+
+ // On RV64, v8i8 MULHSU is built from a pair of widening byte multiplies
+ // (picking out the even/odd result lanes) recombined with PPAIRO.
+ if (Subtarget.is64Bit() && VT == MVT::v8i8 && Opc == RISCVISD::MULHSU) {
+ SDLoc DL(N);
+ SDValue Lo = DAG.getNode(RISCVISD::PMULSU_H_B00, DL, MVT::v4i16, A, B);
+ SDValue Hi = DAG.getNode(RISCVISD::PMULSU_H_B11, DL, MVT::v4i16, A, B);
+ return DAG.getNode(RISCVISD::PPAIRO, DL, VT, DAG.getBitcast(VT, Lo),
+ DAG.getBitcast(VT, Hi));
+ }
break;
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
index ac893d83cf3ac..ceece53cb51bc 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoP.td
@@ -1871,6 +1871,16 @@ def riscv_pmulsu_h_b00
: RVSDNode<"PMULSU_H_B00", SDT_RISCVPackedWideningMulByHalves>;
def riscv_pmulsu_w_h00
: RVSDNode<"PMULSU_W_H00", SDT_RISCVPackedWideningMulByHalves>;
+def riscv_pmul_h_b00
+ : RVSDNode<"PMUL_H_B00", SDT_RISCVPackedWideningMulByHalves>;
+def riscv_pmul_h_b11
+ : RVSDNode<"PMUL_H_B11", SDT_RISCVPackedWideningMulByHalves>;
+def riscv_pmulu_h_b00
+ : RVSDNode<"PMULU_H_B00", SDT_RISCVPackedWideningMulByHalves>;
+def riscv_pmulu_h_b11
+ : RVSDNode<"PMULU_H_B11", SDT_RISCVPackedWideningMulByHalves>;
+def riscv_pmulsu_h_b11
+ : RVSDNode<"PMULSU_H_B11", SDT_RISCVPackedWideningMulByHalves>;
def SDT_RISCVWideningShiftLeft : SDTypeProfile<2, 2, [SDTCisVT<0, i32>,
SDTCisSameAs<0, 1>,
@@ -2878,17 +2888,18 @@ let append Predicates = [IsRV64] in {
def : Pat<(v2i32 (riscv_pmulsu_w_h00 (v4i16 GPR:$rs1), (v4i16 GPR:$rs2))),
(PMULSU_W_H00 GPR:$rs1, GPR:$rs2)>;
- // 8-bit multiply high patterns
- // FIXME custom lower
- def : Pat<(v8i8 (mulhs GPR:$rs1, GPR:$rs2)),
- (PPAIRO_B (PMUL_H_B00 GPR:$rs1, GPR:$rs2),
- (PMUL_H_B11 GPR:$rs1, GPR:$rs2))>;
- def : Pat<(v8i8 (mulhu GPR:$rs1, GPR:$rs2)),
- (PPAIRO_B (PMULU_H_B00 GPR:$rs1, GPR:$rs2),
- (PMULU_H_B11 GPR:$rs1, GPR:$rs2))>;
- def : Pat<(v8i8 (riscv_mulhsu GPR:$rs1, GPR:$rs2)),
- (PPAIRO_B (PMULSU_H_B00 GPR:$rs1, GPR:$rs2),
- (PMULSU_H_B11 GPR:$rs1, GPR:$rs2))>;
+ // 8-bit multiply high patterns. The mulhs/mulhu/mulhsu themselves are
+ // custom-lowered to riscv_pmul(u|su)_h_b00/b11 + riscv_ppairo.
+ def : Pat<(v4i16 (riscv_pmul_h_b00 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (PMUL_H_B00 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_pmul_h_b11 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (PMUL_H_B11 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_pmulu_h_b00 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (PMULU_H_B00 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_pmulu_h_b11 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (PMULU_H_B11 GPR:$rs1, GPR:$rs2)>;
+ def : Pat<(v4i16 (riscv_pmulsu_h_b11 (v8i8 GPR:$rs1), (v8i8 GPR:$rs2))),
+ (PMULSU_H_B11 GPR:$rs1, GPR:$rs2)>;
// 32-bit logical shift left/right patterns
def : PatGprImm<riscv_pshl, PSLLI_W, uimm5, v2i32>;
More information about the llvm-commits
mailing list