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

>From 69b33a58040c50108e41afe0ea487c488f759a52 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Wed, 31 Dec 2025 20:50:38 +0100
Subject: [PATCH 1/2] ValueTracking: Improve handling of fadd in
 computeKnownFPClass.

This already recognized that if both inputs are positive, the
result is positive. Extend this to the mirror situation with
negative inputs.

Also special case fadd x, x. Canonically, fmul x, 2 is fadd x, x.
We can tell the sign bit won't change, and 0 will propagate.
---
 llvm/lib/Analysis/ValueTracking.cpp          | 28 +++++++++--
 llvm/test/Transforms/Attributor/nofpclass.ll | 50 ++++++++++----------
 2 files changed, 49 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index cf7c6796f76c7..df435df311d0c 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5619,14 +5619,22 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
     computeKnownFPClass(Op->getOperand(1), DemandedElts, InterestedSrcs,
                         KnownRHS, Q, Depth + 1);
 
+    // Special case fadd x, x, which is the canonical form of fmul x, 2.
+    bool SameOperands = Op->getOperand(0) == Op->getOperand(1);
+    if (SameOperands)
+      KnownLHS = KnownRHS;
+
     if ((WantNaN && KnownRHS.isKnownNeverNaN()) ||
         (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) ||
         WantNegZero || Opc == Instruction::FSub) {
 
-      // RHS is canonically cheaper to compute. Skip inspecting the LHS if
-      // there's no point.
-      computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs,
-                          KnownLHS, Q, Depth + 1);
+      if (!SameOperands) {
+        // RHS is canonically cheaper to compute. Skip inspecting the LHS if
+        // there's no point.
+        computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs,
+                            KnownLHS, Q, Depth + 1);
+      }
+
       // Adding positive and negative infinity produces NaN.
       // TODO: Check sign of infinities.
       if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
@@ -5640,6 +5648,10 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
         if (KnownLHS.cannotBeOrderedLessThanZero() &&
             KnownRHS.cannotBeOrderedLessThanZero())
           Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
+        if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
+            KnownRHS.cannotBeOrderedGreaterThanZero())
+          Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);
+
         if (!F)
           break;
 
@@ -5647,6 +5659,14 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
             Op->getType()->getScalarType()->getFltSemantics();
         DenormalMode Mode = F->getDenormalMode(FltSem);
 
+        if (SameOperands) {
+          // Doubling 0 will give the same 0.
+          if (KnownRHS.isKnownNeverLogicalPosZero(Mode))
+            Known.knownNot(fcPosZero);
+          if (KnownRHS.isKnownNeverLogicalNegZero(Mode))
+            Known.knownNot(fcNegZero);
+        }
+
         // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
         if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
              KnownRHS.isKnownNeverLogicalNegZero(Mode)) &&
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll 
b/llvm/test/Transforms/Attributor/nofpclass.ll
index d6c6e8ad7db32..68206b2e6ff13 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -3043,7 +3043,7 @@ define float @fadd_double_no_inf(float noundef 
nofpclass(inf) %arg) {
 
 define float @fadd_double_no_zero(float noundef nofpclass(zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(nzero) float @fadd_double_no_zero
+; CHECK-LABEL: define noundef nofpclass(zero) float @fadd_double_no_zero
 ; CHECK-SAME: (float noundef nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3076,7 +3076,7 @@ define float @fadd_double_known_positive(float noundef 
nofpclass(ninf nnorm nsub
 
 define float @fadd_double_known_positive_non0(float noundef nofpclass(ninf 
nnorm nsub zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) float 
@fadd_double_known_positive_non0
+; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float 
@fadd_double_known_positive_non0
 ; CHECK-SAME: (float noundef nofpclass(ninf zero nsub nnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3087,7 +3087,7 @@ define float @fadd_double_known_positive_non0(float 
noundef nofpclass(ninf nnorm
 
 define float @fadd_double_known_negative_or_zero(float noundef nofpclass(pinf 
pnorm psub) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_known_negative_or_zero
+; CHECK-LABEL: define noundef nofpclass(pinf psub pnorm) float 
@fadd_double_known_negative_or_zero
 ; CHECK-SAME: (float noundef nofpclass(pinf psub pnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3098,7 +3098,7 @@ define float @fadd_double_known_negative_or_zero(float 
noundef nofpclass(pinf pn
 
 define float @fadd_double_known_negative(float noundef nofpclass(pinf pnorm 
psub pzero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_known_negative
+; CHECK-LABEL: define noundef nofpclass(pinf pzero psub pnorm) float 
@fadd_double_known_negative
 ; CHECK-SAME: (float noundef nofpclass(pinf pzero psub pnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3109,7 +3109,7 @@ define float @fadd_double_known_negative(float noundef 
nofpclass(pinf pnorm psub
 
 define float @fadd_double_known_negative_non0(float noundef nofpclass(pinf 
pnorm psub zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(nzero) float 
@fadd_double_known_negative_non0
+; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float 
@fadd_double_known_negative_non0
 ; CHECK-SAME: (float noundef nofpclass(pinf zero psub pnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3164,7 +3164,7 @@ define float @fadd_double_no_nnorm_nsub(float noundef 
nofpclass(nnorm nsub) %arg
 
 define float @fadd_double_no_nopsub_pzero(float noundef nofpclass(psub pzero) 
%arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_no_nopsub_pzero
+; CHECK-LABEL: define noundef nofpclass(pzero) float 
@fadd_double_no_nopsub_pzero
 ; CHECK-SAME: (float noundef nofpclass(pzero psub) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3186,7 +3186,7 @@ define float @fadd_double_no_nonsub_nzero(float noundef 
nofpclass(nsub nzero) %a
 
 define float @fadd_double_no_nopsub_pzero_daz(float noundef nofpclass(psub 
pzero) %arg) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_no_nopsub_pzero_daz
+; CHECK-LABEL: define noundef nofpclass(pzero) float 
@fadd_double_no_nopsub_pzero_daz
 ; CHECK-SAME: (float noundef nofpclass(pzero psub) [[ARG:%.*]]) #[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3197,7 +3197,7 @@ define float @fadd_double_no_nopsub_pzero_daz(float 
noundef nofpclass(psub pzero
 
 define float @fadd_double_no_nonsub_nzero_daz(float noundef nofpclass(nsub 
nzero) %arg) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_no_nonsub_nzero_daz
+; CHECK-LABEL: define noundef nofpclass(nzero) float 
@fadd_double_no_nonsub_nzero_daz
 ; CHECK-SAME: (float noundef nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3219,7 +3219,7 @@ define float @fadd_double_no_nopsub_pzero_dynamic(float 
noundef nofpclass(psub p
 
 define float @fadd_double_no_nonsub_nzero_dynamic(float noundef nofpclass(nsub 
nzero) %arg) #6 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_no_nonsub_nzero_dynamic
+; CHECK-LABEL: define noundef nofpclass(nzero) float 
@fadd_double_no_nonsub_nzero_dynamic
 ; CHECK-SAME: (float noundef nofpclass(nzero nsub) [[ARG:%.*]]) #[[ATTR17]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3230,7 +3230,7 @@ define float @fadd_double_no_nonsub_nzero_dynamic(float 
noundef nofpclass(nsub n
 
 define float @fadd_double_known_positive_nonsub_ieee(float noundef 
nofpclass(ninf nnorm sub zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(ninf nzero nsub nnorm) float 
@fadd_double_known_positive_nonsub_ieee
+; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float 
@fadd_double_known_positive_nonsub_ieee
 ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3241,7 +3241,7 @@ define float 
@fadd_double_known_positive_nonsub_ieee(float noundef nofpclass(nin
 
 define float @fadd_double_known_positive_nonsub_daz(float noundef 
nofpclass(ninf nnorm sub zero) %arg) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(ninf nsub nnorm) float 
@fadd_double_known_positive_nonsub_daz
+; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float 
@fadd_double_known_positive_nonsub_daz
 ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) 
#[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3252,7 +3252,7 @@ define float @fadd_double_known_positive_nonsub_daz(float 
noundef nofpclass(ninf
 
 define float @fadd_double_known_positive_nonsub_dynamic(float noundef 
nofpclass(ninf nnorm sub zero) %arg) #6 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(ninf nsub nnorm) float 
@fadd_double_known_positive_nonsub_dynamic
+; CHECK-LABEL: define noundef nofpclass(ninf zero nsub nnorm) float 
@fadd_double_known_positive_nonsub_dynamic
 ; CHECK-SAME: (float noundef nofpclass(ninf zero sub nnorm) [[ARG:%.*]]) 
#[[ATTR17]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3263,7 +3263,7 @@ define float 
@fadd_double_known_positive_nonsub_dynamic(float noundef nofpclass(
 
 define float @fadd_double_known_negative_nonsub_ieee(float noundef 
nofpclass(pinf pnorm sub zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef nofpclass(nzero) float 
@fadd_double_known_negative_nonsub_ieee
+; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float 
@fadd_double_known_negative_nonsub_ieee
 ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) 
#[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3274,7 +3274,7 @@ define float 
@fadd_double_known_negative_nonsub_ieee(float noundef nofpclass(pin
 
 define float @fadd_double_known_negative_nonsub_daz(float noundef 
nofpclass(pinf pnorm sub zero) %arg) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_known_negative_nonsub_daz
+; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float 
@fadd_double_known_negative_nonsub_daz
 ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) 
#[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3285,7 +3285,7 @@ define float @fadd_double_known_negative_nonsub_daz(float 
noundef nofpclass(pinf
 
 define float @fadd_double_known_negative_nonsub_dynamic(float noundef 
nofpclass(pinf pnorm sub zero) %arg) #6 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define noundef float @fadd_double_known_negative_nonsub_dynamic
+; CHECK-LABEL: define noundef nofpclass(pinf zero psub pnorm) float 
@fadd_double_known_negative_nonsub_dynamic
 ; CHECK-SAME: (float noundef nofpclass(pinf zero sub pnorm) [[ARG:%.*]]) 
#[[ATTR17]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3351,7 +3351,7 @@ define float @fadd_known_negative_rhs(float %arg0, float 
nofpclass(pinf psub pno
 
 define float @fadd_known_negative(float nofpclass(pinf psub pnorm) %arg0, 
float nofpclass(pinf psub pnorm) %arg1) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative
 ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3362,7 +3362,7 @@ define float @fadd_known_negative(float nofpclass(pinf 
psub pnorm) %arg0, float
 
 define float @fadd_known_negative_daz(float nofpclass(pinf psub pnorm) %arg0, 
float nofpclass(pinf psub pnorm) %arg1) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_daz
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float @fadd_known_negative_daz
 ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3373,7 +3373,7 @@ define float @fadd_known_negative_daz(float 
nofpclass(pinf psub pnorm) %arg0, fl
 
 define float @fadd_known_negative_pzero_lhs(float nofpclass(pinf psub pnorm 
pzero) %arg0, float nofpclass(pinf psub pnorm) %arg1) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero_lhs
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero_lhs
 ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3384,7 +3384,7 @@ define float @fadd_known_negative_pzero_lhs(float 
nofpclass(pinf psub pnorm pzer
 
 define float @fadd_known_negative_pzero_rhs(float nofpclass(pinf psub pnorm) 
%arg0, float nofpclass(pinf psub pnorm pzero) %arg1) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero_rhs
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero_rhs
 ; CHECK-SAME: (float nofpclass(pinf psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3395,7 +3395,7 @@ define float @fadd_known_negative_pzero_rhs(float 
nofpclass(pinf psub pnorm) %ar
 
 define float @fadd_known_negative_pzero(float nofpclass(pinf psub pnorm pzero) 
%arg0, float nofpclass(pinf psub pnorm pzero) %arg1) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero
 ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3406,7 +3406,7 @@ define float @fadd_known_negative_pzero(float 
nofpclass(pinf psub pnorm pzero) %
 
 define float @fadd_known_negative_pzero_ftz_daz(float nofpclass(pinf psub 
pnorm pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #0 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero_ftz_daz
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero_ftz_daz
 ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR10]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3417,7 +3417,7 @@ define float @fadd_known_negative_pzero_ftz_daz(float 
nofpclass(pinf psub pnorm
 
 define float @fadd_known_negative_pzero_ftz(float nofpclass(pinf psub pnorm 
pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #1 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero_ftz
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero_ftz
 ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR13]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3428,7 +3428,7 @@ define float @fadd_known_negative_pzero_ftz(float 
nofpclass(pinf psub pnorm pzer
 
 define float @fadd_known_negative_pzero_daz(float nofpclass(pinf psub pnorm 
pzero) %arg0, float nofpclass(pinf psub pnorm pzero) %arg1) #2 {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_known_negative_pzero_daz
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) float 
@fadd_known_negative_pzero_daz
 ; CHECK-SAME: (float nofpclass(pinf pzero psub pnorm) [[ARG0:%.*]], float 
nofpclass(pinf pzero psub pnorm) [[ARG1:%.*]]) #[[ATTR11]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3484,7 +3484,7 @@ define float @fadd_known_negative_normal_dapz(float 
nofpclass(pinf pnorm pzero)
 ; Cannot conclude this can't return +0 due to undef.
 define float @fadd_double_no_zero_maybe_undef(float nofpclass(zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define nofpclass(nzero) float @fadd_double_no_zero_maybe_undef
+; CHECK-LABEL: define nofpclass(zero) float @fadd_double_no_zero_maybe_undef
 ; CHECK-SAME: (float nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3506,7 +3506,7 @@ define float @fadd_double_no_nzero_maybe_undef(float 
nofpclass(nzero) %arg) {
 
 define float @fadd_double_no_pzero_maybe_undef(float nofpclass(pzero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define float @fadd_double_no_pzero_maybe_undef
+; CHECK-LABEL: define nofpclass(pzero) float @fadd_double_no_pzero_maybe_undef
 ; CHECK-SAME: (float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]

>From e63cc4a41a2f46143c9a71a48852440d13c39f65 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Fri, 2 Jan 2026 11:42:09 +0100
Subject: [PATCH 2/2] Check isGuaranteedNotToBeUndef

---
 llvm/lib/Analysis/ValueTracking.cpp          | 10 ++++++----
 llvm/test/Transforms/Attributor/nofpclass.ll |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index df435df311d0c..6ad04de63b93a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5620,15 +5620,17 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
                         KnownRHS, Q, Depth + 1);
 
     // Special case fadd x, x, which is the canonical form of fmul x, 2.
-    bool SameOperands = Op->getOperand(0) == Op->getOperand(1);
-    if (SameOperands)
+    bool SelfAdd = Op->getOperand(0) == Op->getOperand(1) &&
+                   isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI,
+                                            Q.DT, Depth + 1);
+    if (SelfAdd)
       KnownLHS = KnownRHS;
 
     if ((WantNaN && KnownRHS.isKnownNeverNaN()) ||
         (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) ||
         WantNegZero || Opc == Instruction::FSub) {
 
-      if (!SameOperands) {
+      if (!SelfAdd) {
         // RHS is canonically cheaper to compute. Skip inspecting the LHS if
         // there's no point.
         computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs,
@@ -5659,7 +5661,7 @@ void computeKnownFPClass(const Value *V, const APInt 
&DemandedElts,
             Op->getType()->getScalarType()->getFltSemantics();
         DenormalMode Mode = F->getDenormalMode(FltSem);
 
-        if (SameOperands) {
+        if (SelfAdd) {
           // Doubling 0 will give the same 0.
           if (KnownRHS.isKnownNeverLogicalPosZero(Mode))
             Known.knownNot(fcPosZero);
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll 
b/llvm/test/Transforms/Attributor/nofpclass.ll
index 68206b2e6ff13..f5f33547bd19f 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -3484,7 +3484,7 @@ define float @fadd_known_negative_normal_dapz(float 
nofpclass(pinf pnorm pzero)
 ; Cannot conclude this can't return +0 due to undef.
 define float @fadd_double_no_zero_maybe_undef(float nofpclass(zero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define nofpclass(zero) float @fadd_double_no_zero_maybe_undef
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_double_no_zero_maybe_undef
 ; CHECK-SAME: (float nofpclass(zero) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -3506,7 +3506,7 @@ define float @fadd_double_no_nzero_maybe_undef(float 
nofpclass(nzero) %arg) {
 
 define float @fadd_double_no_pzero_maybe_undef(float nofpclass(pzero) %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind 
willreturn memory(none)
-; CHECK-LABEL: define nofpclass(pzero) float @fadd_double_no_pzero_maybe_undef
+; CHECK-LABEL: define float @fadd_double_no_pzero_maybe_undef
 ; CHECK-SAME: (float nofpclass(pzero) [[ARG:%.*]]) #[[ATTR3]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]

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

Reply via email to