From 966cb03095ea1f0839394a8af1fc6d83ebe55e09 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 10 Dec 2025 18:10:57 +0100 Subject: [PATCH] IR: Stop requiring nsz to reassociate fmul nsz can only change the behavior of the sign bit. The sign bit for fmul can be implemented as xor, which is associative. DAGCombiner already reassociates the multiply by 2 constants without nsz. Fixes #64967 --- llvm/lib/IR/Instruction.cpp | 1 + .../InstCombine/2006-10-26-VectorReassoc.ll | 6 ++---- llvm/test/Transforms/InstCombine/fdiv.ll | 3 +-- .../InstCombine/issue64967-reassoc-fmul.ll | 18 ++++++------------ 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 33ca46ca1c2c6..b95c1466871bc 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -1271,6 +1271,7 @@ bool Instruction::isAssociative() const { switch (Opcode) { case FMul: + return cast(this)->hasAllowReassoc(); case FAdd: return cast(this)->hasAllowReassoc() && cast(this)->hasNoSignedZeros(); diff --git a/llvm/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll b/llvm/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll index fb860a5e7bdf3..6509797e0d3dc 100644 --- a/llvm/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll +++ b/llvm/test/Transforms/InstCombine/2006-10-26-VectorReassoc.ll @@ -35,12 +35,10 @@ define <4 x float> @test_fmul_reassoc_nsz(<4 x float> %V) { } ; (V * C1) * C2 => V * (C1 * C2) -; TODO: This doesn't require 'nsz'. It should fold to V * { 1.0, 4.0e+05, -9.0, 16.0 } define <4 x float> @test_fmul_reassoc(<4 x float> %V) { ; CHECK-LABEL: @test_fmul_reassoc( -; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc <4 x float> [[V:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = fmul reassoc <4 x float> [[TMP1]], -; CHECK-NEXT: ret <4 x float> [[TMP2]] +; CHECK: [[TMP1:%.*]] = fmul reassoc <4 x float> %V, +; CHECK-NEXT: ret <4 x float> [[TMP1]] %Y = fmul reassoc <4 x float> %V, < float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00 > %Z = fmul reassoc <4 x float> %Y, < float 1.000000e+00, float 2.000000e+05, float -3.000000e+00, float 4.000000e+00 > ret <4 x float> %Z diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll index 54b0bf8c50ac7..3465781e3af9d 100644 --- a/llvm/test/Transforms/InstCombine/fdiv.ll +++ b/llvm/test/Transforms/InstCombine/fdiv.ll @@ -525,8 +525,7 @@ define <2 x float> @div_constant_dividend2_reassoc_only(<2 x float> %x) { define <2 x float> @div_constant_dividend3(<2 x float> %x) { ; CHECK-LABEL: @div_constant_dividend3( -; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], -; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], +; CHECK-NEXT: [[T2:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], ; CHECK-NEXT: ret <2 x float> [[T2]] ; %t1 = fdiv <2 x float> , %x diff --git a/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll b/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll index 16f9cf2dd64c5..5d064234bf609 100644 --- a/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll +++ b/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll @@ -25,8 +25,7 @@ define float @fmul(float %x) { define float @fmul_reassoc(float %x) { ; CHECK-LABEL: define float @fmul_reassoc( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00 -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], 8.000000e+00 ; CHECK-NEXT: ret float [[FMUL1]] ; %fmul0 = fmul reassoc float %x, 2.0 @@ -37,8 +36,7 @@ define float @fmul_reassoc(float %x) { define <2 x float> @fmul_reassoc_v2(<2 x float> %x) { ; CHECK-LABEL: define <2 x float> @fmul_reassoc_v2( ; CHECK-SAME: <2 x float> [[X:%.*]]) { -; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc <2 x float> [[X]], splat (float 2.000000e+00) -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc <2 x float> [[FMUL0]], splat (float 4.000000e+00) +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc <2 x float> [[X]], splat (float 8.000000e+00) ; CHECK-NEXT: ret <2 x float> [[FMUL1]] ; %fmul0 = fmul reassoc <2 x float> %x, splat (float 2.0) @@ -54,8 +52,7 @@ define <2 x float> @fmul_reassoc_v2(<2 x float> %x) { define float @fmul_reassoc_negative_0(float %x) { ; CHECK-LABEL: define float @fmul_reassoc_negative_0( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00 -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -4.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -8.000000e+00 ; CHECK-NEXT: ret float [[FMUL1]] ; %fmul0 = fmul reassoc float %x, 2.0 @@ -71,8 +68,7 @@ define float @fmul_reassoc_negative_0(float %x) { define float @fmul_reassoc_negative_1(float %x) { ; CHECK-LABEL: define float @fmul_reassoc_negative_1( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -2.000000e+00 -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -8.000000e+00 ; CHECK-NEXT: ret float [[FMUL1]] ; %fmul0 = fmul reassoc float %x, -2.0 @@ -95,8 +91,7 @@ define float @fmul_reassoc_nsz(float %x) { define float @fmul_reassoc_posk_neg0(float %x) { ; CHECK-LABEL: define float @fmul_reassoc_posk_neg0( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 4.000000e+00 -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -0.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[X]], -0.000000e+00 ; CHECK-NEXT: ret float [[FMUL1]] ; %fmul0 = fmul reassoc float %x, 4.0 @@ -108,8 +103,7 @@ define float @fmul_reassoc_neg0_posk(float %x) { ; CHECK-LABEL: define float @fmul_reassoc_neg0_posk( ; CHECK-SAME: float [[X:%.*]]) { ; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -0.000000e+00 -; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 -; CHECK-NEXT: ret float [[FMUL1]] +; CHECK-NEXT: ret float [[FMUL0]] ; %fmul0 = fmul reassoc float %x, -0.0 %fmul1 = fmul reassoc float %fmul0, 4.0