[llvm] [DAG] SimplifyMultipleUseDemandedBits - fold (mul X, 1) -> X (PR #197677)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 14 06:24:56 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Simon Pilgrim (RKSimon)
<details>
<summary>Changes</summary>
Use DemandedElts + KnownBits to match hidden identity patterns - helps especially with reduction patterns padded by legalisation
Once #<!-- -->197455 has landed, I'm intending to convert this (plus SMIN/SMAX/UMIN/UMAX and the existing ISD::ADD case) to use isIdentityElement directly.
---
Full diff: https://github.com/llvm/llvm-project/pull/197677.diff
5 Files Affected:
- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+10)
- (modified) llvm/test/CodeGen/AArch64/aarch64-mulv.ll (+3-6)
- (modified) llvm/test/CodeGen/AMDGPU/vector-reduce-mul.ll (+14-23)
- (modified) llvm/test/CodeGen/X86/dpbusd_const.ll (+2-2)
- (modified) llvm/test/CodeGen/X86/srem-vector-lkk.ll (+13-13)
``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index ce1493200b9b1..7e43794ef224b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -831,6 +831,16 @@ SDValue TargetLowering::SimplifyMultipleUseDemandedBits(
return Op.getOperand(1);
break;
}
+ case ISD::MUL: {
+ RHSKnown = DAG.computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
+ if (RHSKnown.isConstant() && RHSKnown.getConstant().isOne())
+ return Op.getOperand(0);
+
+ LHSKnown = DAG.computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
+ if (LHSKnown.isConstant() && LHSKnown.getConstant().isOne())
+ return Op.getOperand(1);
+ break;
+ }
case ISD::SHL: {
// If we are only demanding sign bits then we can use the shift source
// directly.
diff --git a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
index f8d7cca916159..0740472c5e7ee 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-mulv.ll
@@ -390,12 +390,9 @@ entry:
define i32 @mulv_v3i32(<3 x i32> %a) {
; CHECK-LABEL: mulv_v3i32:
; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov v1.16b, v0.16b
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: mov v1.s[3], w8
-; CHECK-NEXT: mov d1, v1.d[1]
-; CHECK-NEXT: mul v0.2s, v0.2s, v1.2s
-; CHECK-NEXT: mul v0.2s, v0.2s, v0.s[1]
+; CHECK-NEXT: mov d1, v0.d[1]
+; CHECK-NEXT: mul v1.2s, v0.2s, v1.2s
+; CHECK-NEXT: mul v0.2s, v1.2s, v0.s[1]
; CHECK-NEXT: fmov w0, s0
; CHECK-NEXT: ret
entry:
diff --git a/llvm/test/CodeGen/AMDGPU/vector-reduce-mul.ll b/llvm/test/CodeGen/AMDGPU/vector-reduce-mul.ll
index 1d495f5a7f01c..13457b1e2f254 100644
--- a/llvm/test/CodeGen/AMDGPU/vector-reduce-mul.ll
+++ b/llvm/test/CodeGen/AMDGPU/vector-reduce-mul.ll
@@ -1099,11 +1099,9 @@ define i16 @test_vector_reduce_mul_v3i16(<3 x i16> %v) {
; GFX9-SDAG-LABEL: test_vector_reduce_mul_v3i16:
; GFX9-SDAG: ; %bb.0: ; %entry
; GFX9-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-SDAG-NEXT: v_mov_b32_e32 v2, 0x5040100
-; GFX9-SDAG-NEXT: v_perm_b32 v1, 1, v1, v2
-; GFX9-SDAG-NEXT: v_pk_mul_lo_u16 v0, v0, v1
+; GFX9-SDAG-NEXT: v_pk_mul_lo_u16 v1, v0, v1
; GFX9-SDAG-NEXT: s_nop 0
-; GFX9-SDAG-NEXT: v_mul_lo_u16_sdwa v0, v0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:WORD_1
+; GFX9-SDAG-NEXT: v_mul_lo_u16_sdwa v0, v1, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:WORD_1
; GFX9-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX9-GISEL-LABEL: test_vector_reduce_mul_v3i16:
@@ -1116,10 +1114,9 @@ define i16 @test_vector_reduce_mul_v3i16(<3 x i16> %v) {
; GFX10-SDAG-LABEL: test_vector_reduce_mul_v3i16:
; GFX10-SDAG: ; %bb.0: ; %entry
; GFX10-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX10-SDAG-NEXT: v_perm_b32 v1, 1, v1, 0x5040100
+; GFX10-SDAG-NEXT: v_lshrrev_b32_e32 v2, 16, v0
; GFX10-SDAG-NEXT: v_pk_mul_lo_u16 v0, v0, v1
-; GFX10-SDAG-NEXT: v_lshrrev_b32_e32 v1, 16, v0
-; GFX10-SDAG-NEXT: v_mul_lo_u16 v0, v0, v1
+; GFX10-SDAG-NEXT: v_mul_lo_u16 v0, v0, v2
; GFX10-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX10-GISEL-LABEL: test_vector_reduce_mul_v3i16:
@@ -1133,21 +1130,18 @@ define i16 @test_vector_reduce_mul_v3i16(<3 x i16> %v) {
; GFX11-SDAG-TRUE16-LABEL: test_vector_reduce_mul_v3i16:
; GFX11-SDAG-TRUE16: ; %bb.0: ; %entry
; GFX11-SDAG-TRUE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-SDAG-TRUE16-NEXT: v_mov_b16_e32 v1.h, 1
-; GFX11-SDAG-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX11-SDAG-TRUE16-NEXT: v_pk_mul_lo_u16 v0, v0, v1
-; GFX11-SDAG-TRUE16-NEXT: v_mul_lo_u16 v0.l, v0.l, v0.h
+; GFX11-SDAG-TRUE16-NEXT: v_pk_mul_lo_u16 v1, v0, v1
+; GFX11-SDAG-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX11-SDAG-TRUE16-NEXT: v_mul_lo_u16 v0.l, v1.l, v0.h
; GFX11-SDAG-TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11-SDAG-FAKE16-LABEL: test_vector_reduce_mul_v3i16:
; GFX11-SDAG-FAKE16: ; %bb.0: ; %entry
; GFX11-SDAG-FAKE16-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-SDAG-FAKE16-NEXT: v_perm_b32 v1, 1, v1, 0x5040100
-; GFX11-SDAG-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX11-SDAG-FAKE16-NEXT: v_lshrrev_b32_e32 v2, 16, v0
; GFX11-SDAG-FAKE16-NEXT: v_pk_mul_lo_u16 v0, v0, v1
-; GFX11-SDAG-FAKE16-NEXT: v_lshrrev_b32_e32 v1, 16, v0
; GFX11-SDAG-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11-SDAG-FAKE16-NEXT: v_mul_lo_u16 v0, v0, v1
+; GFX11-SDAG-FAKE16-NEXT: v_mul_lo_u16 v0, v0, v2
; GFX11-SDAG-FAKE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX11-GISEL-LABEL: test_vector_reduce_mul_v3i16:
@@ -1166,10 +1160,9 @@ define i16 @test_vector_reduce_mul_v3i16(<3 x i16> %v) {
; GFX12-SDAG-TRUE16-NEXT: s_wait_samplecnt 0x0
; GFX12-SDAG-TRUE16-NEXT: s_wait_bvhcnt 0x0
; GFX12-SDAG-TRUE16-NEXT: s_wait_kmcnt 0x0
-; GFX12-SDAG-TRUE16-NEXT: v_mov_b16_e32 v1.h, 1
-; GFX12-SDAG-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-SDAG-TRUE16-NEXT: v_pk_mul_lo_u16 v0, v0, v1
-; GFX12-SDAG-TRUE16-NEXT: v_mul_lo_u16 v0.l, v0.l, v0.h
+; GFX12-SDAG-TRUE16-NEXT: v_pk_mul_lo_u16 v1, v0, v1
+; GFX12-SDAG-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX12-SDAG-TRUE16-NEXT: v_mul_lo_u16 v0.l, v1.l, v0.h
; GFX12-SDAG-TRUE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX12-SDAG-FAKE16-LABEL: test_vector_reduce_mul_v3i16:
@@ -1179,12 +1172,10 @@ define i16 @test_vector_reduce_mul_v3i16(<3 x i16> %v) {
; GFX12-SDAG-FAKE16-NEXT: s_wait_samplecnt 0x0
; GFX12-SDAG-FAKE16-NEXT: s_wait_bvhcnt 0x0
; GFX12-SDAG-FAKE16-NEXT: s_wait_kmcnt 0x0
-; GFX12-SDAG-FAKE16-NEXT: v_perm_b32 v1, 1, v1, 0x5040100
-; GFX12-SDAG-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX12-SDAG-FAKE16-NEXT: v_lshrrev_b32_e32 v2, 16, v0
; GFX12-SDAG-FAKE16-NEXT: v_pk_mul_lo_u16 v0, v0, v1
-; GFX12-SDAG-FAKE16-NEXT: v_lshrrev_b32_e32 v1, 16, v0
; GFX12-SDAG-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX12-SDAG-FAKE16-NEXT: v_mul_lo_u16 v0, v0, v1
+; GFX12-SDAG-FAKE16-NEXT: v_mul_lo_u16 v0, v0, v2
; GFX12-SDAG-FAKE16-NEXT: s_setpc_b64 s[30:31]
;
; GFX12-GISEL-LABEL: test_vector_reduce_mul_v3i16:
diff --git a/llvm/test/CodeGen/X86/dpbusd_const.ll b/llvm/test/CodeGen/X86/dpbusd_const.ll
index bb47df59eefad..1d6c3f7c5c6e8 100644
--- a/llvm/test/CodeGen/X86/dpbusd_const.ll
+++ b/llvm/test/CodeGen/X86/dpbusd_const.ll
@@ -8,8 +8,8 @@ define i32 @mul_4xi8_zc_exceed(<4 x i8> %a, i32 %c) {
; CHECK-LABEL: mul_4xi8_zc_exceed:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vpmovzxbd {{.*#+}} xmm0 = xmm0[0],zero,zero,zero,xmm0[1],zero,zero,zero,xmm0[2],zero,zero,zero,xmm0[3],zero,zero,zero
-; CHECK-NEXT: vpmaddwd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [0,0,1,0,2,0,128,0]
; CHECK-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
+; CHECK-NEXT: vpmaddwd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 # [2,128,2,128]
; CHECK-NEXT: vpaddd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,1,1]
; CHECK-NEXT: vpaddd %xmm0, %xmm1, %xmm0
@@ -180,8 +180,8 @@ define i32 @mul_4xi8_cs_exceed(<4 x i8> %a, i32 %c) {
; CHECK-LABEL: mul_4xi8_cs_exceed:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vpmovsxbd %xmm0, %xmm0
-; CHECK-NEXT: vpmaddwd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0 # [0,0,1,0,2,0,256,0]
; CHECK-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
+; CHECK-NEXT: vpmaddwd {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 # [2,256,2,256]
; CHECK-NEXT: vpaddd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,1,1]
; CHECK-NEXT: vpaddd %xmm0, %xmm1, %xmm0
diff --git a/llvm/test/CodeGen/X86/srem-vector-lkk.ll b/llvm/test/CodeGen/X86/srem-vector-lkk.ll
index f9de4e18857c9..678515c3e572e 100644
--- a/llvm/test/CodeGen/X86/srem-vector-lkk.ll
+++ b/llvm/test/CodeGen/X86/srem-vector-lkk.ll
@@ -355,13 +355,13 @@ define <4 x i16> @dont_fold_urem_i16_smax(<4 x i16> %x) {
; SSE4-NEXT: movq {{.*#+}} xmm2 = [0,32767,45591,12375,0,0,0,0]
; SSE4-NEXT: pmulhw %xmm0, %xmm2
; SSE4-NEXT: paddw %xmm1, %xmm2
-; SSE4-NEXT: movdqa %xmm2, %xmm3
-; SSE4-NEXT: psrlw $15, %xmm3
-; SSE4-NEXT: pxor %xmm4, %xmm4
-; SSE4-NEXT: pblendw {{.*#+}} xmm4 = xmm4[0],xmm3[1,2,3],xmm4[4,5,6,7]
+; SSE4-NEXT: movdqa %xmm2, %xmm1
+; SSE4-NEXT: psrlw $15, %xmm1
+; SSE4-NEXT: pxor %xmm3, %xmm3
+; SSE4-NEXT: pblendw {{.*#+}} xmm3 = xmm3[0],xmm1[1,2,3],xmm3[4,5,6,7]
; SSE4-NEXT: pmulhw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 # [u,4,4096,64,u,u,u,u]
-; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm1[0],xmm2[1,2,3,4,5,6,7]
-; SSE4-NEXT: paddw %xmm4, %xmm2
+; SSE4-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0],xmm2[1,2,3,4,5,6,7]
+; SSE4-NEXT: paddw %xmm3, %xmm2
; SSE4-NEXT: pmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2 # [1,32768,23,5423,u,u,u,u]
; SSE4-NEXT: psubw %xmm2, %xmm0
; SSE4-NEXT: retq
@@ -370,13 +370,13 @@ define <4 x i16> @dont_fold_urem_i16_smax(<4 x i16> %x) {
; AVX1OR2: # %bb.0:
; AVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1 # [1,65535,1,0,u,u,u,u]
; AVX1OR2-NEXT: vpmulhw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm2 # [0,32767,45591,12375,u,u,u,u]
-; AVX1OR2-NEXT: vpaddw %xmm1, %xmm2, %xmm2
-; AVX1OR2-NEXT: vpsrlw $15, %xmm2, %xmm3
-; AVX1OR2-NEXT: vpxor %xmm4, %xmm4, %xmm4
-; AVX1OR2-NEXT: vpblendw {{.*#+}} xmm3 = xmm4[0],xmm3[1,2,3],xmm4[4,5,6,7]
-; AVX1OR2-NEXT: vpmulhw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2, %xmm2 # [u,4,4096,64,u,u,u,u]
-; AVX1OR2-NEXT: vpblendw {{.*#+}} xmm1 = xmm1[0],xmm2[1,2,3,4,5,6,7]
-; AVX1OR2-NEXT: vpaddw %xmm3, %xmm1, %xmm1
+; AVX1OR2-NEXT: vpaddw %xmm1, %xmm2, %xmm1
+; AVX1OR2-NEXT: vpsrlw $15, %xmm1, %xmm2
+; AVX1OR2-NEXT: vpxor %xmm3, %xmm3, %xmm3
+; AVX1OR2-NEXT: vpblendw {{.*#+}} xmm2 = xmm3[0],xmm2[1,2,3],xmm3[4,5,6,7]
+; AVX1OR2-NEXT: vpmulhw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 # [u,4,4096,64,u,u,u,u]
+; AVX1OR2-NEXT: vpblendw {{.*#+}} xmm1 = xmm0[0],xmm1[1,2,3,4,5,6,7]
+; AVX1OR2-NEXT: vpaddw %xmm2, %xmm1, %xmm1
; AVX1OR2-NEXT: vpmullw {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1 # [1,32768,23,5423,u,u,u,u]
; AVX1OR2-NEXT: vpsubw %xmm1, %xmm0, %xmm0
; AVX1OR2-NEXT: retq
``````````
</details>
https://github.com/llvm/llvm-project/pull/197677
More information about the llvm-commits
mailing list