https://github.com/arsenm created 
https://github.com/llvm/llvm-project/pull/171726

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

>From a7f8f32873ca08051df973e82099e38aa2f2ae39 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
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<FPMathOperator>(this)->hasAllowReassoc();
   case FAdd:
     return cast<FPMathOperator>(this)->hasAllowReassoc() &&
            cast<FPMathOperator>(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:%.*]], <float 
1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00>
-; CHECK-NEXT:     [[TMP2:%.*]] = fmul reassoc <4 x float> [[TMP1]], <float 
1.000000e+00, float 2.000000e+05, float -3.000000e+00, float 4.000000e+00>
-; CHECK-NEXT:     ret <4 x float> [[TMP2]]
+; CHECK: [[TMP1:%.*]] = fmul reassoc <4 x float> %V, <float 1.000000e+00, 
float 4.000000e+05, float -9.000000e+00, float 1.600000e+01>
+; 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:%.*]], 
<float 1.500000e+01, float -7.000000e+00>
-; CHECK-NEXT:    [[T2:%.*]] = fmul reassoc arcp <2 x float> [[TMP1]], <float 
0x3FD5555560000000, float 0x3FC24924A0000000>
+; CHECK-NEXT:    [[T2:%.*]] = fmul reassoc arcp <2 x float> [[X:%.*]], <float 
5.000000e+00, float -1.000000e+00>
 ; CHECK-NEXT:    ret <2 x float> [[T2]]
 ;
   %t1 = fdiv <2 x float> <float 3.0e0, float 7.0e0>, %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

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to