From 6325a17d8137bf22df8556d51f8f57f6d8a7a63f Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Fri, 14 Nov 2025 07:08:53 +0100 Subject: [PATCH 1/3] [RISCV][test] Add tests for (mul (shr exact X, C1), C2) foldings --- llvm/test/CodeGen/RISCV/rv64zba.ll | 79 ++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index 4ab4ff84dac57..cbce79a142ded 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -5016,3 +5016,82 @@ define ptr @shl_add_knownbits(ptr %p, i64 %i) { %r = getelementptr i8, ptr %p, i64 %shr ret ptr %r } + +define i64 @exactashr1mul6(i64 %a) { +; RV64I-LABEL: exactashr1mul6: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a1, a0, 1 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: exactashr1mul6: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: srli a0, a0, 1 +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 1 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: exactashr1mul6: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: srli a0, a0, 1 +; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a0 +; RV64XANDESPERF-NEXT: slli a0, a0, 1 +; RV64XANDESPERF-NEXT: ret + %c = ashr exact i64 %a, 1 + %d = mul i64 %c, 6 + ret i64 %d +} + +define i64 @exactlshr3mul22(i64 %a) { +; RV64I-LABEL: exactlshr3mul22: +; RV64I: # %bb.0: +; RV64I-NEXT: srli a0, a0, 3 +; RV64I-NEXT: li a1, 22 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: exactlshr3mul22: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: srli a0, a0, 3 +; RV64ZBA-NEXT: sh2add a1, a0, a0 +; RV64ZBA-NEXT: sh1add a0, a1, a0 +; RV64ZBA-NEXT: slli a0, a0, 1 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: exactlshr3mul22: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: srli a0, a0, 3 +; RV64XANDESPERF-NEXT: nds.lea.w a1, a0, a0 +; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a1 +; RV64XANDESPERF-NEXT: slli a0, a0, 1 +; RV64XANDESPERF-NEXT: ret + %c = lshr exact i64 %a, 3 + %d = mul i64 %c, 22 + ret i64 %d +} + +define i64 @exactashr1mul36(i64 %a) { +; RV64I-LABEL: exactashr1mul36: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a1, a0, 1 +; RV64I-NEXT: slli a0, a0, 4 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: exactashr1mul36: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: srli a0, a0, 1 +; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 2 +; RV64ZBA-NEXT: ret +; +; RV64XANDESPERF-LABEL: exactashr1mul36: +; RV64XANDESPERF: # %bb.0: +; RV64XANDESPERF-NEXT: srli a0, a0, 1 +; RV64XANDESPERF-NEXT: nds.lea.d a0, a0, a0 +; RV64XANDESPERF-NEXT: slli a0, a0, 2 +; RV64XANDESPERF-NEXT: ret + %c = ashr exact i64 %a, 1 + %d = mul i64 %c, 36 + ret i64 %d +} From d8aafb46129754ece36ca8e92a9c453cecdfaeb9 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Fri, 14 Nov 2025 07:09:16 +0100 Subject: [PATCH 2/3] [RISCV] Fold Zba-expanded (mul (shr exact X, C1), C2) --- llvm/include/llvm/CodeGen/SDPatternMatch.h | 5 +++++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 7 +++++-- llvm/test/CodeGen/RISCV/rv64zba.ll | 16 ++++------------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SDPatternMatch.h b/llvm/include/llvm/CodeGen/SDPatternMatch.h index 511cb56f73dcb..557dbf8c7ca39 100644 --- a/llvm/include/llvm/CodeGen/SDPatternMatch.h +++ b/llvm/include/llvm/CodeGen/SDPatternMatch.h @@ -903,6 +903,11 @@ template inline BinaryOpc_match m_Srl(const LHS &L, const RHS &R) { return BinaryOpc_match(ISD::SRL, L, R); } +template +inline auto m_ExactSr(const LHS &L, const RHS &R) { + return m_AnyOf(BinaryOpc_match(ISD::SRA, L, R, SDNodeFlags::Exact), + BinaryOpc_match(ISD::SRL, L, R, SDNodeFlags::Exact)); +} template inline BinaryOpc_match m_Rotl(const LHS &L, const RHS &R) { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 38cce26e44af4..1971837a38aa7 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16829,10 +16829,13 @@ static SDValue getShlAddShlAdd(SDNode *N, SelectionDAG &DAG, unsigned ShX, SDLoc DL(N); EVT VT = N->getValueType(0); SDValue X = N->getOperand(0); - // Put the shift first if we can fold a zext into the shift forming a slli.uw. + // Put the shift first if we can fold: + // a. a zext into the shift forming a slli.uw + // b. an exact shift right forming one shorter shift or no shift at all using namespace SDPatternMatch; if (Shift != 0 && - sd_match(X, m_And(m_Value(), m_SpecificInt(UINT64_C(0xffffffff))))) { + sd_match(X, m_AnyOf(m_And(m_Value(), m_SpecificInt(UINT64_C(0xffffffff))), + m_ExactSr(m_Value(), m_ConstInt())))) { X = DAG.getNode(ISD::SHL, DL, VT, X, DAG.getConstant(Shift, DL, VT)); Shift = 0; } diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index cbce79a142ded..fb26b8b16a290 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -5026,16 +5026,12 @@ define i64 @exactashr1mul6(i64 %a) { ; ; RV64ZBA-LABEL: exactashr1mul6: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: srli a0, a0, 1 ; RV64ZBA-NEXT: sh1add a0, a0, a0 -; RV64ZBA-NEXT: slli a0, a0, 1 ; RV64ZBA-NEXT: ret ; ; RV64XANDESPERF-LABEL: exactashr1mul6: ; RV64XANDESPERF: # %bb.0: -; RV64XANDESPERF-NEXT: srli a0, a0, 1 ; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a0 -; RV64XANDESPERF-NEXT: slli a0, a0, 1 ; RV64XANDESPERF-NEXT: ret %c = ashr exact i64 %a, 1 %d = mul i64 %c, 6 @@ -5052,18 +5048,16 @@ define i64 @exactlshr3mul22(i64 %a) { ; ; RV64ZBA-LABEL: exactlshr3mul22: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: srli a0, a0, 3 +; RV64ZBA-NEXT: srli a0, a0, 2 ; RV64ZBA-NEXT: sh2add a1, a0, a0 ; RV64ZBA-NEXT: sh1add a0, a1, a0 -; RV64ZBA-NEXT: slli a0, a0, 1 ; RV64ZBA-NEXT: ret ; ; RV64XANDESPERF-LABEL: exactlshr3mul22: ; RV64XANDESPERF: # %bb.0: -; RV64XANDESPERF-NEXT: srli a0, a0, 3 +; RV64XANDESPERF-NEXT: srli a0, a0, 2 ; RV64XANDESPERF-NEXT: nds.lea.w a1, a0, a0 ; RV64XANDESPERF-NEXT: nds.lea.h a0, a0, a1 -; RV64XANDESPERF-NEXT: slli a0, a0, 1 ; RV64XANDESPERF-NEXT: ret %c = lshr exact i64 %a, 3 %d = mul i64 %c, 22 @@ -5080,16 +5074,14 @@ define i64 @exactashr1mul36(i64 %a) { ; ; RV64ZBA-LABEL: exactashr1mul36: ; RV64ZBA: # %bb.0: -; RV64ZBA-NEXT: srli a0, a0, 1 +; RV64ZBA-NEXT: slli a0, a0, 1 ; RV64ZBA-NEXT: sh3add a0, a0, a0 -; RV64ZBA-NEXT: slli a0, a0, 2 ; RV64ZBA-NEXT: ret ; ; RV64XANDESPERF-LABEL: exactashr1mul36: ; RV64XANDESPERF: # %bb.0: -; RV64XANDESPERF-NEXT: srli a0, a0, 1 +; RV64XANDESPERF-NEXT: slli a0, a0, 1 ; RV64XANDESPERF-NEXT: nds.lea.d a0, a0, a0 -; RV64XANDESPERF-NEXT: slli a0, a0, 2 ; RV64XANDESPERF-NEXT: ret %c = ashr exact i64 %a, 1 %d = mul i64 %c, 36 From 0e58c5bc9a2d5ffef00e33aeab6b4d9694773453 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Fri, 14 Nov 2025 07:24:00 +0100 Subject: [PATCH 3/3] [RISCV][NFC] Refactor with the new m_ExactSr --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 1971837a38aa7..675f3557a01c8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -16802,9 +16802,7 @@ static SDValue expandMulToAddOrSubOfShl(SDNode *N, SelectionDAG &DAG, // because X is exact (Y >> M + 2). uint64_t ShAmt = Log2_64(MulAmtLowBit) + 2; using namespace SDPatternMatch; - return sd_match(X, m_AnyOf(m_Sra(m_Value(), m_SpecificInt(ShAmt)), - m_Srl(m_Value(), m_SpecificInt(ShAmt)))) && - X->getFlags().hasExact(); + return sd_match(X, m_ExactSr(m_Value(), m_SpecificInt(ShAmt))); }; if (isPowerOf2_64(MulAmt - MulAmtLowBit) && !(CanSub && PreferSub())) { Op = ISD::ADD;