[llvm] [ValueTracking] Improve nofpclass inference for nsz fadd (PR #186315)

Yunbo Ni via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 01:49:44 PDT 2026


https://github.com/cardigan1008 updated https://github.com/llvm/llvm-project/pull/186315

>From d99350053e15bd8be83c52fcb1049351aacf0779 Mon Sep 17 00:00:00 2001
From: cardigan1008 <ybni at cse.cuhk.edu.hk>
Date: Fri, 13 Mar 2026 12:49:21 +0800
Subject: [PATCH 1/4] [ValueTracking] Improve nofpclass inference for nsz fadd

---
 llvm/lib/Analysis/ValueTracking.cpp          |  7 +++++--
 llvm/test/Transforms/Attributor/nofpclass.ll | 11 +++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 0672dc889b640..eab514892fc1a 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5587,8 +5587,11 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           Op->getType()->getScalarType()->getFltSemantics();
       DenormalMode Mode =
           F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
-
-      if (Self && Opc == Instruction::FAdd) {
+      
+      const FPMathOperator *FPop = cast<FPMathOperator>(Op); 
+      bool HasNSZ = FPop->hasNoSignedZeros();
+      
+      if (!HasNSZ && Self && Opc == Instruction::FAdd) {
         Known = KnownFPClass::fadd_self(KnownLHS, Mode);
       } else {
         // RHS is canonically cheaper to compute. Skip inspecting the LHS if
diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll
index 507d0f3ff98f3..3946c9f88e41d 100644
--- a/llvm/test/Transforms/Attributor/nofpclass.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass.ll
@@ -3326,6 +3326,17 @@ define float @fadd_double_known_negative_nonsub_dynamic(float noundef nofpclass(
   ret float %add
 }
 
+define float @fadd_double_known_negative_zero_nsz(float noundef nofpclass(ninf pzero sub nnorm) %arg) {
+; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
+; CHECK-LABEL: define noundef nofpclass(ninf nsub nnorm) float @fadd_double_known_negative_zero_nsz
+; CHECK-SAME: (float noundef nofpclass(ninf pzero sub nnorm) [[ARG:%.*]]) #[[ATTR3]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd nsz float [[ARG]], [[ARG]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd nsz float %arg, %arg
+  ret float %add
+}
+
 define float @fsub_self(float noundef %arg) {
 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
 ; CHECK-LABEL: define noundef float @fsub_self

>From db4d943ca5ae1fbc757cad71bb43f3b6f6dbb011 Mon Sep 17 00:00:00 2001
From: cardigan1008 <ybni at cse.cuhk.edu.hk>
Date: Fri, 13 Mar 2026 12:50:10 +0800
Subject: [PATCH 2/4] [ValueTracking] Fix format issues

---
 llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eab514892fc1a..25a8a8166d3af 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5587,10 +5587,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
           Op->getType()->getScalarType()->getFltSemantics();
       DenormalMode Mode =
           F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
-      
-      const FPMathOperator *FPop = cast<FPMathOperator>(Op); 
+
+      const FPMathOperator *FPop = cast<FPMathOperator>(Op);
       bool HasNSZ = FPop->hasNoSignedZeros();
-      
+
       if (!HasNSZ && Self && Opc == Instruction::FAdd) {
         Known = KnownFPClass::fadd_self(KnownLHS, Mode);
       } else {

>From 5cf73a400c422bcfeefcca7f15e67a26c5580c37 Mon Sep 17 00:00:00 2001
From: cardigan1008 <ybni at cse.cuhk.edu.hk>
Date: Fri, 10 Apr 2026 16:48:55 +0800
Subject: [PATCH 3/4] [ValueTracking] Handle nsz more generically

---
 llvm/lib/Analysis/ValueTracking.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 25a8a8166d3af..edd96ac264614 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5588,10 +5588,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       DenormalMode Mode =
           F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
 
-      const FPMathOperator *FPop = cast<FPMathOperator>(Op);
-      bool HasNSZ = FPop->hasNoSignedZeros();
-
-      if (!HasNSZ && Self && Opc == Instruction::FAdd) {
+      if (Self && Opc == Instruction::FAdd) {
         Known = KnownFPClass::fadd_self(KnownLHS, Mode);
       } else {
         // RHS is canonically cheaper to compute. Skip inspecting the LHS if
@@ -6070,6 +6067,20 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
   default:
     break;
   }
+
+  // With no-signed-zeros semantics, +0 and -0 are interchangeable. 
+  // If the operation has nsz and only one sign of zero is possible in the result,
+  // the other must also be considered possible. 
+  if (const auto *FPOp = dyn_cast_or_null<FPMathOperator>(Op)) {
+    if (FPOp->hasNoSignedZeros()) {
+      FPClassTest KnownZero = Known.KnownFPClasses & fcZero;
+      if (KnownZero && KnownZero != fcZero) {
+        Known.KnownFPClasses |= fcZero;
+        // The sign of zero is now indeterminate since nsz allows either sign.
+        Known.SignBit = std::nullopt;
+      }
+    }
+  }
 }
 
 KnownFPClass llvm::computeKnownFPClass(const Value *V,

>From f28f81f9fdf62b2a2c061436233d1941439664aa Mon Sep 17 00:00:00 2001
From: cardigan1008 <ybni at cse.cuhk.edu.hk>
Date: Fri, 10 Apr 2026 16:49:28 +0800
Subject: [PATCH 4/4] [ValueTracking] Fix format issues

---
 llvm/lib/Analysis/ValueTracking.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index edd96ac264614..c530230a8d840 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6068,9 +6068,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
     break;
   }
 
-  // With no-signed-zeros semantics, +0 and -0 are interchangeable. 
-  // If the operation has nsz and only one sign of zero is possible in the result,
-  // the other must also be considered possible. 
+  // With no-signed-zeros semantics, +0 and -0 are interchangeable.
+  // If the operation has nsz and only one sign of zero is possible in the
+  // result, the other must also be considered possible.
   if (const auto *FPOp = dyn_cast_or_null<FPMathOperator>(Op)) {
     if (FPOp->hasNoSignedZeros()) {
       FPClassTest KnownZero = Known.KnownFPClasses & fcZero;



More information about the llvm-commits mailing list