Skip to content

Conversation

@arsenm
Copy link
Contributor

@arsenm arsenm commented Dec 30, 2025

The fmul visitor handles this case as copysign and fneg.

Copy link
Contributor Author

arsenm commented Dec 30, 2025

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@llvmbot
Copy link
Member

llvmbot commented Dec 30, 2025

@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-support

Author: Matt Arsenault (arsenm)

Changes

The fmul visitor handles this case as copysign and fneg.


Full diff: https://github.com/llvm/llvm-project/pull/174023.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp (+18-2)
  • (modified) llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll (+4-2)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 9799ddacd7bd2..0b5854f169440 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -2356,8 +2356,6 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
     }
 
     // TODO: Apply knowledge of no-infinity returns to sources.
-
-    // TODO: Known -0, turn into copysign(y, fneg(x)) like visitFMul.
     if (KnownLHS.isKnownNeverInfOrNaN() &&
         KnownRHS.isKnownAlways(fcPosZero | fcNan)) {
       // => copysign(+0, lhs)
@@ -2376,6 +2374,24 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Value *V,
       return Copysign;
     }
 
+    if (KnownLHS.isKnownNeverInfOrNaN() &&
+        KnownRHS.isKnownAlways(fcNegZero | fcNan)) {
+      // => copysign(0, fneg(lhs))
+      // Note: Dropping canonicalize
+      Value *Copysign = Builder.CreateCopySign(Y, Builder.CreateFNegFMF(X, I));
+      Copysign->takeName(I);
+      return Copysign;
+    }
+
+    if (KnownLHS.isKnownAlways(fcNegZero | fcNan) &&
+        KnownRHS.isKnownNeverInfOrNaN()) {
+      // => copysign(+0, fneg(rhs))
+      // Note: Dropping canonicalize
+      Value *Copysign = Builder.CreateCopySign(X, Builder.CreateFNegFMF(Y, I));
+      Copysign->takeName(I);
+      return Copysign;
+    }
+
     Type *EltTy = VTy->getScalarType();
     DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics());
 
diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
index 7d0b8ebae20cc..cb83fdc3e7a6b 100644
--- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
+++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fmul.ll
@@ -941,7 +941,8 @@ define nofpclass(ninf) float @ret_ninf__fmul_nnan_unknown__zero(float %unknown)
 define nofpclass(snan) float @known__nzero_or_nan__fmul__not_inf_or_nan(float nofpclass(inf sub norm pzero) %nzero.or.nan, float nofpclass(inf nan) %not.inf.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float @known__nzero_or_nan__fmul__not_inf_or_nan(
 ; CHECK-SAME: float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]], float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul contract float [[NZERO_OR_NAN]], [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg contract float [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float [[NZERO_OR_NAN]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul contract float %nzero.or.nan, %not.inf.or.nan
@@ -952,7 +953,8 @@ define nofpclass(snan) float @known__nzero_or_nan__fmul__not_inf_or_nan(float no
 define nofpclass(snan) float @known__not_inf_or_nan__fmul__nzero_or_nan(float nofpclass(inf nan) %not.inf.or.nan, float nofpclass(inf sub norm pzero) %nzero.or.nan) {
 ; CHECK-LABEL: define nofpclass(snan) float @known__not_inf_or_nan__fmul__nzero_or_nan(
 ; CHECK-SAME: float nofpclass(nan inf) [[NOT_INF_OR_NAN:%.*]], float nofpclass(inf pzero sub norm) [[NZERO_OR_NAN:%.*]]) {
-; CHECK-NEXT:    [[MUL:%.*]] = fmul contract float [[NOT_INF_OR_NAN]], [[NZERO_OR_NAN]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg contract float [[NOT_INF_OR_NAN]]
+; CHECK-NEXT:    [[MUL:%.*]] = call float @llvm.copysign.f32(float [[NZERO_OR_NAN]], float [[TMP1]])
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %mul = fmul contract float %not.inf.or.nan, %nzero.or.nan

@arsenm arsenm marked this pull request as ready for review December 30, 2025 22:01
@arsenm arsenm force-pushed the users/arsenm/instcombine/simplify-demanded-fpclass-fmul-neg0-copysign branch from ff4c662 to b2471d5 Compare December 31, 2025 09:45
@arsenm arsenm force-pushed the users/arsenm/instcombine/simplify-demanded-fpclass-fmul branch from 171dd91 to f2f9302 Compare December 31, 2025 09:45
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

The fmul visitor handles this case as copysign and fneg.
@arsenm arsenm force-pushed the users/arsenm/instcombine/simplify-demanded-fpclass-fmul-neg0-copysign branch from b2471d5 to 45afbb3 Compare January 5, 2026 10:04
@arsenm arsenm force-pushed the users/arsenm/instcombine/simplify-demanded-fpclass-fmul branch from f2f9302 to ec17cc4 Compare January 5, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

floating-point Floating-point math llvm:analysis Includes value tracking, cost tables and constant folding llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:support llvm:transforms

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants