https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/174024

>From 93190f3c2217edf8cad2f2415a6f336652b54855 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Tue, 30 Dec 2025 21:04:37 +0100
Subject: [PATCH] InstCombine: Consider not-inf/nan context when simplifying
 fmul

Consider if the result can be nan, or if the inputs cannot
be infinity from the flag when trying to simplify fmul into
copysign.
---
 .../InstCombineSimplifyDemanded.cpp           | 18 +++++++----
 .../simplify-demanded-fpclass-fmul.ll         | 30 +++++++++++--------
 2 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 9e5be55fb909a..6252ad484b85d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2171,12 +2171,18 @@ Value 
*InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
       KnownRHS.knownNot(fcNan);
     }
 
+    if (FMF.noInfs()) {
+      // Flag implies inputs cannot be infinity.
+      KnownLHS.knownNot(fcInf);
+      KnownRHS.knownNot(fcInf);
+    }
+
+    bool NonNanResult = (DemandedMask & fcNan) == fcNone;
+
     // With no-nans/no-infs:
     // X * 0.0 --> copysign(0.0, X)
     // X * -0.0 --> copysign(0.0, -X)
-
-    // TODO: Apply knowledge of no-infinity returns to sources.
-    if (KnownLHS.isKnownNeverInfOrNaN() &&
+    if ((NonNanResult || KnownLHS.isKnownNeverInfOrNaN()) &&
         KnownRHS.isKnownAlways(fcPosZero | fcNan)) {
       // => copysign(+0, lhs)
       // Note: Dropping canonicalize
@@ -2186,7 +2192,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value 
*V,
     }
 
     if (KnownLHS.isKnownAlways(fcPosZero | fcNan) &&
-        KnownRHS.isKnownNeverInfOrNaN()) {
+        (NonNanResult || KnownRHS.isKnownNeverInfOrNaN())) {
       // => copysign(+0, rhs)
       // Note: Dropping canonicalize
       Value *Copysign = Builder.CreateCopySign(X, Y, FMF);
@@ -2194,7 +2200,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value 
*V,
       return Copysign;
     }
 
-    if (KnownLHS.isKnownNeverInfOrNaN() &&
+    if ((NonNanResult || KnownLHS.isKnownNeverInfOrNaN()) &&
         KnownRHS.isKnownAlways(fcNegZero | fcNan)) {
       // => copysign(0, fneg(lhs))
       // Note: Dropping canonicalize
@@ -2205,7 +2211,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value 
*V,
     }
 
     if (KnownLHS.isKnownAlways(fcNegZero | fcNan) &&
-        KnownRHS.isKnownNeverInfOrNaN()) {
+        (NonNanResult || KnownRHS.isKnownNeverInfOrNaN())) {
       // => copysign(+0, fneg(rhs))
       // Note: Dropping canonicalize
       Value *Copysign =
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll 
b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
index eb5dfed45187d..468ff8b771918 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
@@ -690,7 +690,7 @@ define nofpclass(nan) float 
@ret_no_nan_result__known_negative_non0__fmul__known
 define nofpclass(inf nan) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf 
sub norm nzero) %pzero.or.nan, float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
[[UNKNOWN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[UNKNOWN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %unknown
@@ -701,7 +701,7 @@ define nofpclass(inf nan) float 
@ret_noinf_nonan__known_pzero_or_nan__fmul__not_
 define nofpclass(inf nan) float 
@ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan(float nofpclass(inf 
sub norm nzero) %pzero.or.nan, float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan inf) float 
@ret_noinf_nonan__not_inf_or_nan__fmul__known_pzero_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
[[UNKNOWN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[UNKNOWN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %pzero.or.nan, %unknown
@@ -950,7 +950,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_pzero__unknown(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_pzero__unknown(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
+; CHECK-NEXT:    [[FMUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[UNKNOWN]])
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %pzero = call float @returns_pzero()
@@ -962,7 +962,7 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_unknown__pzero(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__pzero(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[PZERO:%.*]] = call float @returns_pzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], 0.000000e+00
+; CHECK-NEXT:    [[FMUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[UNKNOWN]])
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %pzero = call float @returns_pzero()
@@ -974,7 +974,8 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_nzero__unknown(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_nzero__unknown(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[UNKNOWN]]
+; CHECK-NEXT:    [[FMUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %nzero = call float @returns_nzero()
@@ -986,7 +987,8 @@ define nofpclass(nan) float 
@ret_no_nan__fmul_unknown__nzero(float %unknown) {
 ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nan__fmul_unknown__nzero(
 ; CHECK-SAME: float [[UNKNOWN:%.*]]) {
 ; CHECK-NEXT:    [[NZERO:%.*]] = call float @returns_nzero()
-; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[UNKNOWN]], -0.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[UNKNOWN]]
+; CHECK-NEXT:    [[FMUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[FMUL]]
 ;
   %nzero = call float @returns_nzero()
@@ -1112,7 +1114,8 @@ define nofpclass(inf) float 
@ret_noinf__not_inf_or_nan__fmul__nzero_or_nan(float
 define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm 
pzero) %nzero.or.nan, float nofpclass(nan) %not.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float 
nofpclass(nan) [[NOT_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %nzero.or.nan, %not.nan
@@ -1123,7 +1126,8 @@ define nofpclass(nan) float 
@ret_nonan__nzero_or_nan__fmul__not_inf_or_nan(float
 define nofpclass(nan) float 
@ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(float nofpclass(nan) %not.nan, 
float nofpclass(inf sub norm pzero) %nzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(nan) float 
@ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(inf pzero 
sub norm) [[NZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[NOT_NAN]], -0.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float 
0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul float %not.nan, %nzero.or.nan
@@ -1134,7 +1138,8 @@ define nofpclass(nan) float 
@ret_nonan__not_inf_or_nan__fmul__nzero_or_nan(float
 define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_ninf__not_inf_or_nan(float nofpclass(inf sub norm 
pzero) %nzero.or.nan, float nofpclass(nan) %not.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_ninf__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float 
nofpclass(nan) [[NOT_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[NZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg ninf float [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call ninf float @llvm.copysign.f32(float 
[[NZERO_OR_NAN]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul ninf float %nzero.or.nan, %not.nan
@@ -1145,7 +1150,8 @@ define nofpclass(snan) float 
@ret__nzero_or_nan__fmul_ninf__not_inf_or_nan(float
 define nofpclass(snan) float 
@ret_not_inf_or_nan__fmul_ninf__nzero_or_nan(float nofpclass(nan) %not.nan, 
float nofpclass(inf sub norm pzero) %nzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@ret_not_inf_or_nan__fmul_ninf__nzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(inf pzero 
sub norm) [[NZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[NOT_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg ninf float [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call ninf float @llvm.copysign.f32(float 
[[NZERO_OR_NAN]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul ninf float %not.nan, %nzero.or.nan
@@ -1268,7 +1274,7 @@ define nofpclass(inf) float 
@ret_noinf__not_inf_or_nan__fmul__pzero_or_nan(float
 define nofpclass(snan) float 
@ret__pzero_or_nan__fmul_ninf__not_inf_or_nan(float nofpclass(inf sub norm 
nzero) %pzero.or.nan, float nofpclass(nan) %not.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@ret__pzero_or_nan__fmul_ninf__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf nzero sub norm) [[PZERO_OR_NAN:%.*]], float 
nofpclass(nan) [[NOT_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[PZERO_OR_NAN]], [[NOT_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call ninf float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul ninf float %pzero.or.nan, %not.nan
@@ -1279,7 +1285,7 @@ define nofpclass(snan) float 
@ret__pzero_or_nan__fmul_ninf__not_inf_or_nan(float
 define nofpclass(snan) float 
@ret_not_inf_or_nan__fmul_ninf__pzero_or_nan(float nofpclass(nan) %not.nan, 
float nofpclass(inf sub norm nzero) %pzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float 
@ret_not_inf_or_nan__fmul_ninf__pzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan) [[NOT_NAN:%.*]], float nofpclass(inf nzero 
sub norm) [[PZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul ninf float [[NOT_NAN]], [[PZERO_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call ninf float @llvm.copysign.f32(float 
[[PZERO_OR_NAN]], float [[NOT_NAN]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul ninf float %not.nan, %pzero.or.nan

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

Reply via email to