[llvm] [KnownFPClass] Propagate non-`sNaN` for `fadd`/`fsub`, `fmul`, `fdiv`, and `fma` (PR #221876)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 21:54:46 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-support

@llvm/pr-subscribers-llvm-transforms

Author: Eric Ross (ZERICO2005)

<details>
<summary>Changes</summary>

`fadd`, `fsub`, `fmul`, `fdiv`, and `fma` can only return `sNaN` if at least one of their inputs are `sNaN`. This means that we can rule out `sNaN` from the result if all of the arguments are known to never be `sNaN`.

`sNaN` propagation for `frem` is handled in this PR: https://github.com/llvm/llvm-project/pull/219303


---

Patch is 218.57 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/221876.diff


8 Files Affected:

- (modified) llvm/lib/Support/KnownFPClass.cpp (+18-3) 
- (added) llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll (+1296) 
- (modified) llvm/test/Transforms/Attributor/nofpclass-fdiv.ll (+51-11) 
- (modified) llvm/test/Transforms/Attributor/nofpclass-fma.ll (+159-15) 
- (modified) llvm/test/Transforms/Attributor/nofpclass-fmul.ll (+44-4) 
- (modified) llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll (+12-12) 
- (modified) llvm/test/Transforms/Attributor/nofpclass.ll (+142-1339) 
- (modified) llvm/unittests/Analysis/ValueTrackingTest.cpp (+7-7) 


``````````diff
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 1f596edd74100..0d47986415b5b 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -377,6 +377,8 @@ KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
        Mode.Output == DenormalMode::PositiveZero))
     Known.knownNot(fcNegZero);
 
+  Known.propagateNonSNaN(KnownLHS, KnownRHS);
+
   return Known;
 }
 
@@ -407,6 +409,8 @@ KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
                                 DenormalMode Mode) {
   KnownFPClass Known;
 
+  Known.propagateNonSNaN(KnownLHS, KnownRHS);
+
   // +X * +Y or -X * -Y => +Q
   // +X * -Y or -X * +Y => -Q
   Known.propagateXorSign(KnownLHS, KnownRHS);
@@ -468,6 +472,8 @@ KnownFPClass KnownFPClass::fdiv(const KnownFPClass &KnownLHS,
                                 DenormalMode Mode) {
   KnownFPClass Known;
 
+  Known.propagateNonSNaN(KnownLHS, KnownRHS);
+
   // Only 0/0, Inf/Inf produce NaN.
   if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() &&
       (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity()) &&
@@ -509,10 +515,10 @@ KnownFPClass KnownFPClass::fdiv_self(const KnownFPClass &KnownSrc,
   // X / X is always exactly 1.0 or a NaN.
   KnownFPClass Known(fcNan | fcPosNormal);
 
+  Known.propagateNonSNaN(KnownSrc);
+
   if (KnownSrc.isKnownNeverInfOrNaN() && KnownSrc.isKnownNeverLogicalZero(Mode))
     Known.knownNot(fcNan);
-  else if (KnownSrc.isKnownNever(fcSNan))
-    Known.knownNot(fcSNan);
 
   return Known;
 }
@@ -570,7 +576,14 @@ KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
   //
   // If the multiply is a -0 due to rounding, the final -0 + 0 will be -0,
   // unlike for a separate fadd.
-  return fadd_impl(Mul, KnownAddend, Mode);
+  KnownFPClass Known = fadd_impl(Mul, KnownAddend, Mode);
+
+  // propagateNonSNaN for 3 arguments.
+  if (KnownLHS.isKnownNever(fcSNan) && KnownRHS.isKnownNever(fcSNan) &&
+      KnownAddend.isKnownNever(fcSNan))
+    Known.knownNot(fcSNan);
+
+  return Known;
 }
 
 KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
@@ -588,6 +601,8 @@ KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
   if (KnownAddend.isKnownNever(fcNegInf | fcNan) && Squared.isKnownNever(fcNan))
     Known.knownNot(fcNan);
 
+  Known.propagateNonSNaN(KnownSquared, KnownAddend);
+
   return Known;
 }
 
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll b/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll
new file mode 100644
index 0000000000000..05a4da5e5878d
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll
@@ -0,0 +1,1296 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal < %s | FileCheck %s
+
+define float @fadd_no_nan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fadd_no_nan(
+; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_no_snan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fadd_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_lhs_no_snan(float nofpclass(snan) %arg0, float %arg1) {
+; CHECK-LABEL: define float @fadd_lhs_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_rhs_no_snan(float %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @fadd_rhs_no_snan(
+; CHECK-SAME: float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_self_no_nan(float noundef nofpclass(nan) %arg0) {
+; CHECK-LABEL: define noundef nofpclass(snan) float @fadd_self_no_nan(
+; CHECK-SAME: float noundef nofpclass(nan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg0
+  ret float %add
+}
+
+define float @fadd_self_no_snan(float noundef nofpclass(snan) %arg0) {
+; CHECK-LABEL: define noundef nofpclass(snan) float @fadd_self_no_snan(
+; CHECK-SAME: float noundef nofpclass(snan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg0
+  ret float %add
+}
+
+define float @fadd_self_no_qnan(float noundef nofpclass(qnan) %arg0) {
+; CHECK-LABEL: define noundef float @fadd_self_no_qnan(
+; CHECK-SAME: float noundef nofpclass(qnan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg0
+  ret float %add
+}
+
+define float @fsub_no_nan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fsub_no_nan(
+; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg1
+  ret float %sub
+}
+
+define float @fsub_no_snan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fsub_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg1
+  ret float %sub
+}
+
+define float @fsub_lhs_no_snan(float nofpclass(snan) %arg0, float %arg1) {
+; CHECK-LABEL: define float @fsub_lhs_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg1
+  ret float %sub
+}
+
+define float @fsub_rhs_no_snan(float %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @fsub_rhs_no_snan(
+; CHECK-SAME: float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg1
+  ret float %sub
+}
+
+define float @fsub_self_no_nan(float noundef nofpclass(nan) %arg0) {
+; CHECK-LABEL: define noundef nofpclass(snan) float @fsub_self_no_nan(
+; CHECK-SAME: float noundef nofpclass(nan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg0
+  ret float %sub
+}
+
+define float @fsub_self_no_snan(float noundef nofpclass(snan) %arg0) {
+; CHECK-LABEL: define noundef nofpclass(snan) float @fsub_self_no_snan(
+; CHECK-SAME: float noundef nofpclass(snan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg0
+  ret float %sub
+}
+
+define float @fsub_self_no_qnan(float noundef nofpclass(qnan) %arg0) {
+; CHECK-LABEL: define noundef float @fsub_self_no_qnan(
+; CHECK-SAME: float noundef nofpclass(qnan) [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, %arg0
+  ret float %sub
+}
+
+define float @fadd_p0(float %arg0) {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_n0(float %arg0) {
+; CHECK-LABEL: define float @fadd_n0(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, -0.0
+  ret float %add
+}
+
+define float @fsub_p0(float %arg0) {
+; CHECK-LABEL: define float @fsub_p0(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, 0.0
+  ret float %sub
+}
+
+define float @fsub_n0(float %arg0) {
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, -0.0
+  ret float %sub
+}
+
+define float @fsub_p0_commute(float %arg0) {
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float 0.0, %arg0
+  ret float %sub
+}
+
+define float @fsub_n0_commute(float %arg0) {
+; CHECK-LABEL: define float @fsub_n0_commute(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float -0.0, %arg0
+  ret float %sub
+}
+
+define float @fadd_p0_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fadd_p0_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_p0_ftpz_dapz(float %arg0) #3 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ftpz_dapz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR2:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_p0_dynamic_dynamic(float %arg0) #6 {
+; CHECK-LABEL: define float @fadd_p0_dynamic_dynamic(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR3:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_n0_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fadd_n0_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, -0.0
+  ret float %add
+}
+
+define float @fsub_p0_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fsub_p0_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, 0.0
+  ret float %sub
+}
+
+define float @fsub_n0_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fsub_n0_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, -0.0
+  ret float %sub
+}
+
+define float @fsub_p0_commute_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fsub_p0_commute_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float 0.0, %arg0
+  ret float %sub
+}
+
+define float @fsub_n0_commute_ftz_daz(float %arg0) #0 {
+; CHECK-LABEL: define float @fsub_n0_commute_ftz_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float -0.0, %arg0
+  ret float %sub
+}
+
+define float @fadd_p0_ieee_daz(float %arg0) #2 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR4:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_p0_dapz_ieee(float %arg0) #4 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_p0_dapz_ieee(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR5:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, 0.0
+  ret float %add
+}
+
+define float @fadd_n0_ieee_daz(float %arg0) #2 {
+; CHECK-LABEL: define float @fadd_n0_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, -0.0
+  ret float %add
+}
+
+define float @fsub_p0_ieee_daz(float %arg0) #2 {
+; CHECK-LABEL: define float @fsub_p0_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], 0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, 0.0
+  ret float %sub
+}
+
+define float @fsub_n0_ieee_daz(float %arg0) #2 {
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_n0_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[ARG0]], -0.000000e+00
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float %arg0, -0.0
+  ret float %sub
+}
+
+define float @fsub_p0_commute_ieee_daz(float %arg0) #2 {
+; CHECK-LABEL: define nofpclass(nzero) float @fsub_p0_commute_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float 0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float 0.0, %arg0
+  ret float %sub
+}
+
+define float @fsub_n0_commute_ieee_daz(float %arg0) #1 {
+; CHECK-LABEL: define float @fsub_n0_commute_ieee_daz(
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR6:[0-9]+]] {
+; CHECK-NEXT:    [[SUB:%.*]] = fsub float -0.000000e+00, [[ARG0]]
+; CHECK-NEXT:    ret float [[SUB]]
+;
+  %sub = fsub float -0.0, %arg0
+  ret float %sub
+}
+
+define float @fadd_never_negzero_or_negsub(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub(
+; CHECK-SAME: float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_ftz_daz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #0 {
+; CHECK-LABEL: define float @fadd_never_negzero_or_ftz_daz(
+; CHECK-SAME: float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_negsub_daz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #2 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_daz(
+; CHECK-SAME: float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_negsub_dapz(float nofpclass(nzero nsub) %a, float nofpclass(nzero nsub) %b) #5 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_negsub_dapz(
+; CHECK-SAME: float nofpclass(nzero nsub) [[A:%.*]], float nofpclass(nzero nsub) [[B:%.*]]) #[[ATTR7:[0-9]+]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_possub(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub(
+; CHECK-SAME: float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_possub_daz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #2 {
+; CHECK-LABEL: define float @fadd_never_negzero_or_possub_daz(
+; CHECK-SAME: float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_possub_dapz(float nofpclass(nzero psub) %a, float nofpclass(nzero psub) %b) #5 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_possub_dapz(
+; CHECK-SAME: float nofpclass(nzero psub) [[A:%.*]], float nofpclass(nzero psub) [[B:%.*]]) #[[ATTR7]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_sub_daz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #2 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_daz(
+; CHECK-SAME: float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_never_negzero_or_sub_dapz(float nofpclass(nzero sub) %a, float nofpclass(nzero sub) %b) #5 {
+; CHECK-LABEL: define nofpclass(nzero) float @fadd_never_negzero_or_sub_dapz(
+; CHECK-SAME: float nofpclass(nzero sub) [[A:%.*]], float nofpclass(nzero sub) [[B:%.*]]) #[[ATTR7]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[A]], [[B]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %a, %b
+  ret float %add
+}
+
+define float @fadd_known_positive_lhs(float nofpclass(ninf nsub nnorm) %arg0, float %arg1) {
+; CHECK-LABEL: define float @fadd_known_positive_lhs(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_known_positive_rhs(float %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
+; CHECK-LABEL: define float @fadd_known_positive_rhs(
+; CHECK-SAME: float [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_known_positive(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) {
+; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[ADD]]
+;
+  %add = fadd float %arg0, %arg1
+  ret float %add
+}
+
+define float @fadd_known_positive_daz(float nofpclass(ninf nsub nnorm) %arg0, float nofpclass(ninf nsub nnorm) %arg1) #0 {
+; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @fadd_known_positive_daz(
+; CHECK-SAME: float nofpclass(ninf nsub nnorm) [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
+; CHECK-NEXT: ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/221876


More information about the llvm-commits mailing list