[clang] [llvm] [RISCV] Remove riscv_mulh_i32/riscv_mulhu_u32 intrinsics. (PR #227819)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 30 11:54:27 PDT 2026
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/227819
>From e3eb79f7ef62ca2a3bc815e4b774679d27db168a Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 30 Sep 2026 11:28:47 -0700
Subject: [PATCH 1/2] [RISCV] Remvoe riscv_mulh_i32/riscv_mulhu_u32 intrinsics.
These are redundant with the llvm.smulh/umulh intrinsics that were
recently added.
This changes codegen because smulh/umulh are currently generically
type legalized with extends+mul+srli instead of using pmulh(u).w.
This isn't always a regression. Sometimes we are able to prove the
inputs are already extended or we use mul(u).w00 and sometimes
we needed a sext.w after the pmulh(u).w.
---
clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 19 ++++++++++---------
clang/test/CodeGen/RISCV/rvp-intrinsics.c | 8 ++++----
.../riscv_packed_simd.c | 10 ++++++----
llvm/include/llvm/IR/IntrinsicsRISCV.td | 2 --
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 8 --------
llvm/test/CodeGen/RISCV/rvp-simd-32.ll | 10 ++++++----
6 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 869f71b9cdd1d..20ec751018685 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -1371,7 +1371,10 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
case RISCV::BI__builtin_riscv_pusati_u16x4:
case RISCV::BI__builtin_riscv_pusati_u32x2:
case RISCV::BI__builtin_riscv_psati_i16x4:
- case RISCV::BI__builtin_riscv_psati_i32x2: {
+ case RISCV::BI__builtin_riscv_psati_i32x2:
+ // Scalar Multiply High
+ case RISCV::BI__builtin_riscv_mulh_i32:
+ case RISCV::BI__builtin_riscv_mulhu_u32: {
switch (BuiltinID) {
default:
llvm_unreachable("unexpected builtin ID");
@@ -1622,6 +1625,12 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
case RISCV::BI__builtin_riscv_pusati_u32x2:
ID = Intrinsic::riscv_pusati;
break;
+ case RISCV::BI__builtin_riscv_mulh_i32:
+ ID = Intrinsic::smulh;
+ break;
+ case RISCV::BI__builtin_riscv_mulhu_u32:
+ ID = Intrinsic::umulh;
+ break;
}
IntrinsicTypes = {ResultType};
@@ -1629,24 +1638,16 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
}
// Scalar Multiply High
- case RISCV::BI__builtin_riscv_mulh_i32:
case RISCV::BI__builtin_riscv_mulhr_i32:
- case RISCV::BI__builtin_riscv_mulhu_u32:
case RISCV::BI__builtin_riscv_mulhru_u32:
case RISCV::BI__builtin_riscv_mulhsu_i32:
case RISCV::BI__builtin_riscv_mulhrsu_i32: {
switch (BuiltinID) {
default:
llvm_unreachable("unexpected builtin ID");
- case RISCV::BI__builtin_riscv_mulh_i32:
- ID = Intrinsic::riscv_mulh_i32;
- break;
case RISCV::BI__builtin_riscv_mulhr_i32:
ID = Intrinsic::riscv_mulhr_i32;
break;
- case RISCV::BI__builtin_riscv_mulhu_u32:
- ID = Intrinsic::riscv_mulhu_u32;
- break;
case RISCV::BI__builtin_riscv_mulhru_u32:
ID = Intrinsic::riscv_mulhru_u32;
break;
diff --git a/clang/test/CodeGen/RISCV/rvp-intrinsics.c b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
index b16415525a23a..f5a5863642331 100644
--- a/clang/test/CodeGen/RISCV/rvp-intrinsics.c
+++ b/clang/test/CodeGen/RISCV/rvp-intrinsics.c
@@ -137,13 +137,13 @@ uint64_t test_abs_u64(int64_t a) {
// RV32-LABEL: define dso_local i32 @test_mulh_i32(
// RV32-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
// RV32-NEXT: [[ENTRY:.*:]]
-// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mulh.i32(i32 [[A]], i32 [[B]])
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.smulh.i32(i32 [[A]], i32 [[B]])
// RV32-NEXT: ret i32 [[TMP0]]
//
// RV64-LABEL: define dso_local signext i32 @test_mulh_i32(
// RV64-SAME: i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
// RV64-NEXT: [[ENTRY:.*:]]
-// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mulh.i32(i32 [[A]], i32 [[B]])
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.smulh.i32(i32 [[A]], i32 [[B]])
// RV64-NEXT: ret i32 [[TMP0]]
//
int32_t test_mulh_i32(int32_t a, int32_t b) {
@@ -169,13 +169,13 @@ int32_t test_mulhr_i32(int32_t a, int32_t b) {
// RV32-LABEL: define dso_local i32 @test_mulhu_u32(
// RV32-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
// RV32-NEXT: [[ENTRY:.*:]]
-// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mulhu.u32(i32 [[A]], i32 [[B]])
+// RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.umulh.i32(i32 [[A]], i32 [[B]])
// RV32-NEXT: ret i32 [[TMP0]]
//
// RV64-LABEL: define dso_local signext i32 @test_mulhu_u32(
// RV64-SAME: i32 noundef signext [[A:%.*]], i32 noundef signext [[B:%.*]]) #[[ATTR0]] {
// RV64-NEXT: [[ENTRY:.*:]]
-// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mulhu.u32(i32 [[A]], i32 [[B]])
+// RV64-NEXT: [[TMP0:%.*]] = call i32 @llvm.umulh.i32(i32 [[A]], i32 [[B]])
// RV64-NEXT: ret i32 [[TMP0]]
//
uint32_t test_mulhu_u32(uint32_t a, uint32_t b) {
diff --git a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
index 54d7022dac80b..810ad22fa168d 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2916,9 +2916,10 @@ int32x2_t test_pmerge_mvmn_i32x2(int32x2_t rs2, int32x2_t rs1, uint32x2_t rd) {
}
// Scalar multiply high
-// CHECK-LABEL: test_mulh_i32:
+// CHECK-LABEL: test_mulh_i32:{{.*}}
// RV32: mulh
-// RV64: pmulh.w
+// RV64: mul
+// RV64-NEXT: srai
int32_t test_mulh_i32(int32_t rs1, int32_t rs2) {
return __riscv_mulh_i32(rs1, rs2);
}
@@ -2930,9 +2931,10 @@ int32_t test_mulhr_i32(int32_t rs1, int32_t rs2) {
return __riscv_mulhr_i32(rs1, rs2);
}
-// CHECK-LABEL: test_mulhu_u32:
+// CHECK-LABEL: test_mulhu_u32:{{.*}}
// RV32: mulhu
-// RV64: pmulhu.w
+// RV64: mulu.w00
+// RV64-NEXT: srai
uint32_t test_mulhu_u32(uint32_t rs1, uint32_t rs2) {
return __riscv_mulhu_u32(rs1, rs2);
}
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td
index 140a2397841d9..8cac40c2dc535 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCV.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td
@@ -2144,9 +2144,7 @@ class RVPBinaryIntrinsic
class RVPScalarMulHighIntrinsic
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrSpeculatable]>;
- def int_riscv_mulh_i32 : RVPScalarMulHighIntrinsic;
def int_riscv_mulhr_i32 : RVPScalarMulHighIntrinsic;
- def int_riscv_mulhu_u32 : RVPScalarMulHighIntrinsic;
def int_riscv_mulhru_u32 : RVPScalarMulHighIntrinsic;
def int_riscv_mulhsu_i32 : RVPScalarMulHighIntrinsic;
def int_riscv_mulhrsu_i32 : RVPScalarMulHighIntrinsic;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 3a650ca20f19e..bd994fc36a704 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -12323,12 +12323,8 @@ static unsigned getRVScalarMulHighOpcode(unsigned IntNo) {
switch (IntNo) {
default:
llvm_unreachable("Unexpected RISC-V scalar multiply high intrinsic");
- case Intrinsic::riscv_mulh_i32:
- return ISD::MULHS;
case Intrinsic::riscv_mulhr_i32:
return RISCVISD::MULHR;
- case Intrinsic::riscv_mulhu_u32:
- return ISD::MULHU;
case Intrinsic::riscv_mulhru_u32:
return RISCVISD::MULHRU;
case Intrinsic::riscv_mulhsu_i32:
@@ -13282,9 +13278,7 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
return DAG.getNode(Opc, DL, VT, Op.getOperand(1), Op.getOperand(2));
}
- case Intrinsic::riscv_mulh_i32:
case Intrinsic::riscv_mulhr_i32:
- case Intrinsic::riscv_mulhu_u32:
case Intrinsic::riscv_mulhru_u32:
case Intrinsic::riscv_mulhsu_i32:
case Intrinsic::riscv_mulhrsu_i32: {
@@ -17893,9 +17887,7 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
Results.push_back(DAG.getExtractSubvector(DL, VT, Res, 0));
return;
}
- case Intrinsic::riscv_mulh_i32:
case Intrinsic::riscv_mulhr_i32:
- case Intrinsic::riscv_mulhu_u32:
case Intrinsic::riscv_mulhru_u32:
case Intrinsic::riscv_mulhsu_i32:
case Intrinsic::riscv_mulhrsu_i32: {
diff --git a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
index 14afeb9c88302..2149266271707 100644
--- a/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
+++ b/llvm/test/CodeGen/RISCV/rvp-simd-32.ll
@@ -3932,9 +3932,10 @@ define i32 @test_mulh_i32(i32 %rs1, i32 %rs2) {
;
; RV64-LABEL: test_mulh_i32:
; RV64: # %bb.0:
-; RV64-NEXT: pmulh.w a0, a0, a1
+; RV64-NEXT: mul.w00 a0, a0, a1
+; RV64-NEXT: srli a0, a0, 32
; RV64-NEXT: ret
- %res = call i32 @llvm.riscv.mulh.i32(i32 %rs1, i32 %rs2)
+ %res = call i32 @llvm.smulh.i32(i32 %rs1, i32 %rs2)
ret i32 %res
}
@@ -3960,9 +3961,10 @@ define i32 @test_mulhu_u32(i32 %rs1, i32 %rs2) {
;
; RV64-LABEL: test_mulhu_u32:
; RV64: # %bb.0:
-; RV64-NEXT: pmulhu.w a0, a0, a1
+; RV64-NEXT: mulu.w00 a0, a0, a1
+; RV64-NEXT: srli a0, a0, 32
; RV64-NEXT: ret
- %res = call i32 @llvm.riscv.mulhu.u32(i32 %rs1, i32 %rs2)
+ %res = call i32 @llvm.umulh.i32(i32 %rs1, i32 %rs2)
ret i32 %res
}
>From bcfcc7f6a5a02f624d30e356047c2c4e22449d46 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Wed, 30 Sep 2026 11:54:04 -0700
Subject: [PATCH 2/2] fixup! make sure we are testing mnemonics and not
function names.
---
.../intrinsic-header-tests/riscv_packed_simd.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
index 810ad22fa168d..bfb76a4c11cd2 100644
--- a/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
+++ b/cross-project-tests/intrinsic-header-tests/riscv_packed_simd.c
@@ -2916,10 +2916,10 @@ int32x2_t test_pmerge_mvmn_i32x2(int32x2_t rs2, int32x2_t rs1, uint32x2_t rd) {
}
// Scalar multiply high
-// CHECK-LABEL: test_mulh_i32:{{.*}}
-// RV32: mulh
-// RV64: mul
-// RV64-NEXT: srai
+// CHECK-LABEL: test_mulh_i32:
+// RV32: mulh{{[[:space:]]}}
+// RV64: mul{{[[:space:]]}}
+// RV64-NEXT: srai{{[[:space:]]}}
int32_t test_mulh_i32(int32_t rs1, int32_t rs2) {
return __riscv_mulh_i32(rs1, rs2);
}
@@ -2931,10 +2931,10 @@ int32_t test_mulhr_i32(int32_t rs1, int32_t rs2) {
return __riscv_mulhr_i32(rs1, rs2);
}
-// CHECK-LABEL: test_mulhu_u32:{{.*}}
-// RV32: mulhu
-// RV64: mulu.w00
-// RV64-NEXT: srai
+// CHECK-LABEL: test_mulhu_u32:
+// RV32: mulhu{{[[:space:]]}}
+// RV64: mulu.w00{{[[:space:]]}}
+// RV64-NEXT: srai{{[[:space:]]}}
uint32_t test_mulhu_u32(uint32_t rs1, uint32_t rs2) {
return __riscv_mulhu_u32(rs1, rs2);
}
More information about the llvm-commits
mailing list