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

Eric Ross via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 11 12:56:41 PDT 2026


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

>From c4f38f2fb533f6da9c6e287a8f5efc9acec0e21d Mon Sep 17 00:00:00 2001
From: zerico <zerico2005 at gmail.com>
Date: Mon, 7 Sep 2026 22:32:20 -0600
Subject: [PATCH] [KnownFPClass] Propagate non-sNaN for fadd/fsub, fmul, fdiv,
 and fma

---
 llvm/lib/Support/KnownFPClass.cpp             |  21 ++-
 .../AMDGPU/nofpclass-amdgcn-trig-preop.ll     |   4 +-
 .../Attributor/nofpclass-fadd-fsub.ll         | 148 ++++++++++++++-
 .../Transforms/Attributor/nofpclass-fdiv.ll   |  62 +++++--
 .../Transforms/Attributor/nofpclass-fma.ll    | 174 ++++++++++++++++--
 .../Transforms/Attributor/nofpclass-fmul.ll   |  48 ++++-
 .../Attributor/nofpclass-nan-fmul.ll          |  24 +--
 llvm/unittests/Analysis/ValueTrackingTest.cpp |  14 +-
 8 files changed, 437 insertions(+), 58 deletions(-)

diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index 75636ffc73361..e544980742fbc 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/AMDGPU/nofpclass-amdgcn-trig-preop.ll b/llvm/test/Transforms/Attributor/AMDGPU/nofpclass-amdgcn-trig-preop.ll
index 292dc05756d2f..6ee4548cb635c 100644
--- a/llvm/test/Transforms/Attributor/AMDGPU/nofpclass-amdgcn-trig-preop.ll
+++ b/llvm/test/Transforms/Attributor/AMDGPU/nofpclass-amdgcn-trig-preop.ll
@@ -36,7 +36,7 @@ define double @ret_trig_preop__fmul__not_inf(double nofpclass(inf) %not.inf, dou
 }
 
 define double @ret_not_nan__fmul__trig_preop(double nofpclass(nan) %not.nan, double %x, i32 %n) {
-; CHECK-LABEL: define double @ret_not_nan__fmul__trig_preop(
+; CHECK-LABEL: define nofpclass(snan) double @ret_not_nan__fmul__trig_preop(
 ; CHECK-SAME: double nofpclass(nan) [[NOT_NAN:%.*]], double [[X:%.*]], i32 [[N:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[TRIG_PREOP:%.*]] = call double @llvm.amdgcn.trig.preop.f64(double [[X]], i32 [[N]]) #[[ATTR2]]
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[NOT_NAN]], [[TRIG_PREOP]]
@@ -48,7 +48,7 @@ define double @ret_not_nan__fmul__trig_preop(double nofpclass(nan) %not.nan, dou
 }
 
 define double @ret_trig_preop__fmul__not_nan(double nofpclass(nan) %not.nan, double %x, i32 %n) {
-; CHECK-LABEL: define double @ret_trig_preop__fmul__not_nan(
+; CHECK-LABEL: define nofpclass(snan) double @ret_trig_preop__fmul__not_nan(
 ; CHECK-SAME: double nofpclass(nan) [[NOT_NAN:%.*]], double [[X:%.*]], i32 [[N:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[TRIG_PREOP:%.*]] = call double @llvm.amdgcn.trig.preop.f64(double [[X]], i32 [[N]]) #[[ATTR2]]
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul double [[TRIG_PREOP]], [[NOT_NAN]]
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll b/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll
index 7c4823fe24740..05a4da5e5878d 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fadd-fsub.ll
@@ -1,9 +1,149 @@
 ; 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:[0-9]+]] {
+; CHECK-SAME: float [[ARG0:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], 0.000000e+00
 ; CHECK-NEXT:    ret float [[ADD]]
 ;
@@ -362,7 +502,7 @@ define float @test_fadd_no_nan_from_no_pinf(float nofpclass(nan pinf) %arg0, flo
 }
 
 define float @test_fadd_may_nan_from_no_pinf_no_ninf(float nofpclass(nan pinf) %arg0, float nofpclass(nan ninf) %arg1) {
-; CHECK-LABEL: define float @test_fadd_may_nan_from_no_pinf_no_ninf(
+; CHECK-LABEL: define nofpclass(snan) float @test_fadd_may_nan_from_no_pinf_no_ninf(
 ; CHECK-SAME: float nofpclass(nan pinf) [[ARG0:%.*]], float nofpclass(nan ninf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -372,7 +512,7 @@ define float @test_fadd_may_nan_from_no_pinf_no_ninf(float nofpclass(nan pinf) %
 }
 
 define float @test_fadd_may_nan_from_no_ninf_no_pinf(float nofpclass(nan ninf) %arg0, float nofpclass(nan pinf) %arg1) {
-; CHECK-LABEL: define float @test_fadd_may_nan_from_no_ninf_no_pinf(
+; CHECK-LABEL: define nofpclass(snan) float @test_fadd_may_nan_from_no_ninf_no_pinf(
 ; CHECK-SAME: float nofpclass(nan ninf) [[ARG0:%.*]], float nofpclass(nan pinf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[ADD]]
@@ -494,7 +634,7 @@ define float @fadd_double(float noundef %arg) {
 }
 
 define float @fadd_double_nnan(float noundef nofpclass(nan) %arg) {
-; CHECK-LABEL: define noundef float @fadd_double_nnan(
+; CHECK-LABEL: define noundef nofpclass(snan) float @fadd_double_nnan(
 ; CHECK-SAME: float noundef nofpclass(nan) [[ARG:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[ARG]], [[ARG]]
 ; CHECK-NEXT:    ret float [[ADD]]
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
index f49b13d7b3f78..f2d2a5ddd86ed 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fdiv.ll
@@ -92,7 +92,7 @@ define float @ret_fdiv_ieee_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %
 }
 
 define float @ret_fdiv_daz_nonan_nozero__nonan_noinf(float nofpclass(nan zero) %arg0, float nofpclass(nan inf) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fdiv_daz_nonan_nozero__nonan_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_daz_nonan_nozero__nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -102,7 +102,7 @@ define float @ret_fdiv_daz_nonan_nozero__nonan_noinf(float nofpclass(nan zero) %
 }
 
 define float @ret_fdiv_daz_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %arg0, float nofpclass(nan zero) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fdiv_daz_nonan_noinf__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_daz_nonan_noinf__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -132,7 +132,7 @@ define float @ret_fdiv_daz_nonan_noinf__nonan_nozero_nosub(float nofpclass(nan i
 }
 
 define float @ret_fdiv_ieee_nonan_noinf__nonan_noinf(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fdiv_ieee_nonan_noinf__nonan_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_ieee_nonan_noinf__nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -152,7 +152,7 @@ define float @ret_fdiv_ieee_nonan_noinf_nozero__nonan_noinf_nozero(float nofpcla
 }
 
 define float @ret_fdiv_daz_nonan_noinf_nozero__nonan_noinf_nozero(float nofpclass(nan inf zero) %arg0, float nofpclass(nan inf zero) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fdiv_daz_nonan_noinf_nozero__nonan_noinf_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_daz_nonan_noinf_nozero__nonan_noinf_nozero
 ; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -162,7 +162,7 @@ define float @ret_fdiv_daz_nonan_noinf_nozero__nonan_noinf_nozero(float nofpclas
 }
 
 define float @ret_fdiv_dapz_nonan_noinf_nozero__nonan_noinf_nozero(float nofpclass(nan inf zero) %arg0, float nofpclass(nan inf zero) %arg1) #2 {
-; CHECK-LABEL: define float @ret_fdiv_dapz_nonan_noinf_nozero__nonan_noinf_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_dapz_nonan_noinf_nozero__nonan_noinf_nozero
 ; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR2:[0-9]+]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -172,7 +172,7 @@ define float @ret_fdiv_dapz_nonan_noinf_nozero__nonan_noinf_nozero(float nofpcla
 }
 
 define float @ret_fdiv_dynamic_nonan_noinf_nozero__nonan_noinf_nozero(float nofpclass(nan inf zero) %arg0, float nofpclass(nan inf zero) %arg1) #3 {
-; CHECK-LABEL: define float @ret_fdiv_dynamic_nonan_noinf_nozero__nonan_noinf_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_dynamic_nonan_noinf_nozero__nonan_noinf_nozero
 ; CHECK-SAME: (float nofpclass(nan inf zero) [[ARG0:%.*]], float nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR3:[0-9]+]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -182,7 +182,7 @@ define float @ret_fdiv_dynamic_nonan_noinf_nozero__nonan_noinf_nozero(float nofp
 }
 
 define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noinf(float nofpclass(nan inf) %arg0, float nofpclass(nan inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noinf
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -212,7 +212,7 @@ define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_nozero(float nofpclas
 }
 
 define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noposzero(float nofpclass(nan inf) %arg0, float nofpclass(nan pzero) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noposzero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noposzero
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan pzero) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -222,7 +222,7 @@ define float @ret_fdiv_ieee_nonan_noinf_noinf__nonan_noinf_noposzero(float nofpc
 }
 
 define float @ret_fdiv_ieee_nonan_noinf_noposzero__nonan_noinf_noinf(float nofpclass(nan pzero) %arg0, float nofpclass(nan inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fdiv_ieee_nonan_noinf_noposzero__nonan_noinf_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fdiv_ieee_nonan_noinf_noposzero__nonan_noinf_noinf
 ; CHECK-SAME: (float nofpclass(nan pzero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -962,7 +962,7 @@ define float @ret_fdiv_rhs_negative_lhs_positive(float %lhs, float %rhs) {
 
 ; Could be inf of either sign
 define float @ret_known_inf_fdiv_known_inf(float nofpclass(norm sub zero nan) %arg0, float nofpclass(norm sub zero nan) %arg1) {
-; CHECK-LABEL: define nofpclass(sub norm) float @ret_known_inf_fdiv_known_inf
+; CHECK-LABEL: define nofpclass(snan sub norm) float @ret_known_inf_fdiv_known_inf
 ; CHECK-SAME: (float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -995,7 +995,7 @@ define float @ret_known_inf_or_nan_fdiv_known_inf(float nofpclass(norm sub zero)
 
 ; Could be zero of either sign
 define float @ret_known_zero_fdiv_known_zero(float nofpclass(inf norm sub nan) %arg0, float nofpclass(inf norm sub nan) %arg1) {
-; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_known_zero_fdiv_known_zero
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_known_zero_fdiv_known_zero
 ; CHECK-SAME: (float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FDIV]]
@@ -1056,6 +1056,46 @@ define float @ret_known_inf_or_nan_fdiv_known_inf_or_nan(float nofpclass(norm su
   ret float %fdiv
 }
 
+define float @fdiv_no_nan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fdiv_no_nan
+; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @fdiv_no_snan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @fdiv_no_snan
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @fdiv_lhs_no_snan(float nofpclass(snan) %arg0, float %arg1) {
+; CHECK-LABEL: define float @fdiv_lhs_no_snan
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
+define float @fdiv_rhs_no_snan(float %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @fdiv_rhs_no_snan
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR4]] {
+; CHECK-NEXT:    [[FDIV:%.*]] = fdiv float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[FDIV]]
+;
+  %fdiv = fdiv float %arg0, %arg1
+  ret float %fdiv
+}
+
 attributes #0 = { denormal_fpenv(ieee|ieee) }
 attributes #1 = { denormal_fpenv(ieee|preservesign) }
 attributes #2 = { denormal_fpenv(ieee|positivezero) }
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fma.ll b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
index 0284b97181177..de20233afc7e2 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fma.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
@@ -325,9 +325,9 @@ define half @ret_fmuladd__pos01_pos01__pos2() {
 
 ; all no-nan inputs does not imply no-nan output
 define half @ret_fma__no_nan__no_nan__no_nan(half nofpclass(nan) %arg0, half nofpclass(nan) %arg1, half nofpclass(nan) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan__no_nan__no_nan
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma__no_nan__no_nan__no_nan
 ; CHECK-SAME: (half nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]], half nofpclass(nan) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan) [[ARG2]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -335,9 +335,9 @@ define half @ret_fma__no_nan__no_nan__no_nan(half nofpclass(nan) %arg0, half nof
 }
 
 define half @ret_fma__no_nan__no_nan__no_nan_zero(half nofpclass(nan) %arg0, half nofpclass(nan) %arg1, half nofpclass(nan zero) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan__no_nan__no_nan_zero
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma__no_nan__no_nan__no_nan_zero
 ; CHECK-SAME: (half nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]], half nofpclass(nan zero) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan zero) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan zero) [[ARG2]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -345,9 +345,9 @@ define half @ret_fma__no_nan__no_nan__no_nan_zero(half nofpclass(nan) %arg0, hal
 }
 
 define half @ret_fma__no_nan__no_nan__no_nan_inf(half nofpclass(nan) %arg0, half nofpclass(nan) %arg1, half nofpclass(nan zero inf) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan__no_nan__no_nan_inf
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma__no_nan__no_nan__no_nan_inf
 ; CHECK-SAME: (half nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]], half nofpclass(nan inf zero) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan inf zero) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan inf zero) [[ARG2]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -388,9 +388,9 @@ define half @ret_fma__no_nan_ninf_zero__no_nan_ninf_zero__no_nan_inf(half nofpcl
 
 ; Cannot infer nnan output
 define half @ret_fma_square__no_nan__no_nan(half noundef nofpclass(nan) %arg0, half nofpclass(nan) %arg1) {
-; CHECK-LABEL: define half @ret_fma_square__no_nan__no_nan
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma_square__no_nan__no_nan
 ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -398,9 +398,9 @@ define half @ret_fma_square__no_nan__no_nan(half noundef nofpclass(nan) %arg0, h
 }
 
 define half @ret_fma_square__no_nan__no_nan_zero(half noundef nofpclass(nan) %arg0, half nofpclass(nan zero) %arg1) {
-; CHECK-LABEL: define half @ret_fma_square__no_nan__no_nan_zero
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma_square__no_nan__no_nan_zero
 ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan zero) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan zero) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -458,9 +458,9 @@ define half @ret_fma_square__no_nan_no_inf__no_nan_no_inf(half noundef nofpclass
 }
 
 define half @ret_fma_square__no_nan_no_inf__no_nan_no_pinf(half noundef nofpclass(nan inf) %arg0, half nofpclass(nan pinf) %arg1) {
-; CHECK-LABEL: define half @ret_fma_square__no_nan_no_inf__no_nan_no_pinf
+; CHECK-LABEL: define nofpclass(snan) half @ret_fma_square__no_nan_no_inf__no_nan_no_pinf
 ; CHECK-SAME: (half noundef nofpclass(nan inf) [[ARG0:%.*]], half nofpclass(nan pinf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan inf) [[ARG0]], half noundef nofpclass(nan inf) [[ARG0]], half nofpclass(nan pinf) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half noundef nofpclass(nan inf) [[ARG0]], half noundef nofpclass(nan inf) [[ARG0]], half nofpclass(nan pinf) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -498,9 +498,9 @@ define half @ret_fma_ninf_square__no_nan__no_nan(half noundef nofpclass(nan) %ar
 }
 
 define nofpclass(inf) half @ret_noinf_fma_square__no_nan__no_nan(half noundef nofpclass(nan) %arg0, half nofpclass(nan) %arg1) {
-; CHECK-LABEL: define nofpclass(inf) half @ret_noinf_fma_square__no_nan__no_nan
+; CHECK-LABEL: define nofpclass(snan inf) half @ret_noinf_fma_square__no_nan__no_nan
 ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -510,7 +510,7 @@ define nofpclass(inf) half @ret_noinf_fma_square__no_nan__no_nan(half noundef no
 define nofpclass(nan) half @ret_nonan_fma_square__no_nan__no_nan(half noundef nofpclass(nan) %arg0, half nofpclass(nan) %arg1) {
 ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fma_square__no_nan__no_nan
 ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -527,5 +527,149 @@ define half @ret_fma_ninf__no_nan_inputs(half nofpclass(nan) %arg0, half nofpcla
   ret half %call
 }
 
+;---------------------------------------------------------------------
+; Rule out sNaN if and only if all arguments are not sNaN.
+;---------------------------------------------------------------------
+
+define float @ret_fma__any__any__any(float %arg0, float %arg1, float %arg2) {
+; CHECK-LABEL: define float @ret_fma__any__any__any
+; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]], float [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float [[ARG0]], float [[ARG1]], float [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__any__any__no_snan(float %arg0, float %arg1, float nofpclass(snan) %arg2) {
+; CHECK-LABEL: define float @ret_fma__any__any__no_snan
+; CHECK-SAME: (float [[ARG0:%.*]], float [[ARG1:%.*]], float nofpclass(snan) [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float [[ARG0]], float [[ARG1]], float nofpclass(snan) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__any__no_snan__any(float %arg0, float nofpclass(snan) %arg1, float %arg2) {
+; CHECK-LABEL: define float @ret_fma__any__no_snan__any
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]], float [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float [[ARG0]], float nofpclass(snan) [[ARG1]], float [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__any__no_snan__no_snan(float %arg0, float nofpclass(snan) %arg1, float nofpclass(snan) %arg2) {
+; CHECK-LABEL: define float @ret_fma__any__no_snan__no_snan
+; CHECK-SAME: (float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]], float nofpclass(snan) [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float [[ARG0]], float nofpclass(snan) [[ARG1]], float nofpclass(snan) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__no_snan__any__any(float nofpclass(snan) %arg0, float %arg1, float %arg2) {
+; CHECK-LABEL: define float @ret_fma__no_snan__any__any
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]], float [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float nofpclass(snan) [[ARG0]], float [[ARG1]], float [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__no_snan__any__no_snan(float nofpclass(snan) %arg0, float %arg1, float nofpclass(snan) %arg2) {
+; CHECK-LABEL: define float @ret_fma__no_snan__any__no_snan
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]], float nofpclass(snan) [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float nofpclass(snan) [[ARG0]], float [[ARG1]], float nofpclass(snan) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__no_snan__no_snan__any(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1, float %arg2) {
+; CHECK-LABEL: define float @ret_fma__no_snan__no_snan__any
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]], float [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float nofpclass(snan) [[ARG0]], float nofpclass(snan) [[ARG1]], float [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma__no_snan__no_snan__no_snan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1, float nofpclass(snan) %arg2) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_fma__no_snan__no_snan__no_snan
+; CHECK-SAME: (float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]], float nofpclass(snan) [[ARG2:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) float @llvm.fma.f32(float nofpclass(snan) [[ARG0]], float nofpclass(snan) [[ARG1]], float nofpclass(snan) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg1, float %arg2)
+  ret float %call
+}
+
+define float @ret_fma_square__any__any(float noundef %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fma_square__any__any
+; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
+  ret float %call
+}
+
+define float @ret_fma_square__any__no_snan(float noundef %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @ret_fma_square__any__no_snan
+; CHECK-SAME: (float noundef [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float nofpclass(snan) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
+  ret float %call
+}
+
+define float @ret_fma_square__no_snan__any(float noundef nofpclass(snan) %arg0, float %arg1) {
+; CHECK-LABEL: define float @ret_fma_square__no_snan__any
+; CHECK-SAME: (float noundef nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float noundef nofpclass(snan) [[ARG0]], float noundef nofpclass(snan) [[ARG0]], float [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
+  ret float %call
+}
+
+define float @ret_fma_square__no_snan__no_snan(float noundef nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @ret_fma_square__no_snan__no_snan
+; CHECK-SAME: (float noundef nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(snan) float @llvm.fma.f32(float noundef nofpclass(snan) [[ARG0]], float noundef nofpclass(snan) [[ARG0]], float nofpclass(snan) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
+  ret float %call
+}
+
+define float @ret_fma_same_arg__any(float noundef %arg0) {
+; CHECK-LABEL: define noundef float @ret_fma_same_arg__any
+; CHECK-SAME: (float noundef [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call noundef float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float noundef [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg0)
+  ret float %call
+}
+
+define float @ret_fma_same_arg__no_snan(float noundef nofpclass(snan) %arg0) {
+; CHECK-LABEL: define noundef nofpclass(snan) float @ret_fma_same_arg__no_snan
+; CHECK-SAME: (float noundef nofpclass(snan) [[ARG0:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[CALL:%.*]] = call noundef nofpclass(snan) float @llvm.fma.f32(float noundef nofpclass(snan) [[ARG0]], float noundef nofpclass(snan) [[ARG0]], float noundef nofpclass(snan) [[ARG0]]) #[[ATTR2]]
+; CHECK-NEXT:    ret float [[CALL]]
+;
+  %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg0)
+  ret float %call
+}
+
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
 ; TUNIT: {{.*}}
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fmul.ll b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll
index aa7b7a7a8395e..2adc39385a988 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fmul.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fmul.ll
@@ -44,6 +44,46 @@ define float @ret_mul_exponent_f32_22(float %arg0) {
   ret float %call
 }
 
+define float @fmul_no_nan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fmul_no_nan(
+; CHECK-SAME: float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %fmul = fmul float %arg0, %arg1
+  ret float %fmul
+}
+
+define float @fmul_no_snan(float nofpclass(snan) %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define nofpclass(snan) float @fmul_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %fmul = fmul float %arg0, %arg1
+  ret float %fmul
+}
+
+define float @fmul_lhs_no_snan(float nofpclass(snan) %arg0, float %arg1) {
+; CHECK-LABEL: define float @fmul_lhs_no_snan(
+; CHECK-SAME: float nofpclass(snan) [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %fmul = fmul float %arg0, %arg1
+  ret float %fmul
+}
+
+define float @fmul_rhs_no_snan(float %arg0, float nofpclass(snan) %arg1) {
+; CHECK-LABEL: define float @fmul_rhs_no_snan(
+; CHECK-SAME: float [[ARG0:%.*]], float nofpclass(snan) [[ARG1:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
+; CHECK-NEXT:    ret float [[MUL]]
+;
+  %fmul = fmul float %arg0, %arg1
+  ret float %fmul
+}
+
 define float @ret_fmul_square_f32_src_no_nan(float noundef nofpclass(nan) %arg) {
 ; CHECK-LABEL: define noundef nofpclass(nan ninf nzero nsub nnorm) float @ret_fmul_square_f32_src_no_nan(
 ; CHECK-SAME: float noundef nofpclass(nan) [[ARG:%.*]]) #[[ATTR0]] {
@@ -528,7 +568,7 @@ define float @ret_fmul_f32_known_ninf_or_nan_rhs(float %arg0, float nofpclass(pi
 
 ; -> nan
 define float @ret_known_inf_mul_known_zero(float nofpclass(nan norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
-; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_known_inf_mul_known_zero(
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_known_inf_mul_known_zero(
 ; CHECK-SAME: float nofpclass(nan zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -561,7 +601,7 @@ define float @ret_known_inf_mul_known_zero_or_nan(float nofpclass(nan norm sub z
 
 ; -> nan
 define float @ret_known_ninf_mul_known_zero(float nofpclass(nan pinf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
-; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_known_ninf_mul_known_zero(
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_known_ninf_mul_known_zero(
 ; CHECK-SAME: float nofpclass(nan pinf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -572,7 +612,7 @@ define float @ret_known_ninf_mul_known_zero(float nofpclass(nan pinf norm sub ze
 
 ; -> nan
 define float @ret_known_pinf_mul_known_zero(float nofpclass(nan ninf norm sub zero) %arg0, float nofpclass(nan inf norm sub) %arg1) {
-; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_known_pinf_mul_known_zero(
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_known_pinf_mul_known_zero(
 ; CHECK-SAME: float nofpclass(nan ninf zero sub norm) [[ARG0:%.*]], float nofpclass(nan inf sub norm) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -583,7 +623,7 @@ define float @ret_known_pinf_mul_known_zero(float nofpclass(nan ninf norm sub ze
 
 ; -> nan
 define float @ret_known_zero_mul_known_inf(float nofpclass(nan inf norm sub) %arg0, float nofpclass(nan norm sub zero) %arg1) {
-; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_known_zero_mul_known_inf(
+; CHECK-LABEL: define nofpclass(snan inf zero sub norm) float @ret_known_zero_mul_known_inf(
 ; CHECK-SAME: float nofpclass(nan inf sub norm) [[ARG0:%.*]], float nofpclass(nan zero sub norm) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
diff --git a/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll b/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
index f67ced498a29f..61eeac03f42ac 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-nan-fmul.ll
@@ -2,7 +2,7 @@
 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
 
 define float @ret_fmul_ieee_nonan__nonan(float nofpclass(nan) %arg0, float nofpclass(nan) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan__nonan
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nonan__nonan
 ; CHECK-SAME: (float nofpclass(nan) [[ARG0:%.*]], float nofpclass(nan) [[ARG1:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -22,7 +22,7 @@ define float @ret_fmul_ieee_nonan_nozero__nonan_nozero(float nofpclass(nan zero)
 }
 
 define float @ret_fmul_daz_nonan_nozero__nonan_nozero(float nofpclass(nan zero) %arg0, float nofpclass(nan zero) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fmul_daz_nonan_nozero__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_daz_nonan_nozero__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR1:[0-9]+]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -32,7 +32,7 @@ define float @ret_fmul_daz_nonan_nozero__nonan_nozero(float nofpclass(nan zero)
 }
 
 define float @ret_fmul_dapz_nonan_nozero__nonan_nozero(float nofpclass(nan zero) %arg0, float nofpclass(nan zero) %arg1) #2 {
-; CHECK-LABEL: define float @ret_fmul_dapz_nonan_nozero__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_dapz_nonan_nozero__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR2:[0-9]+]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -42,7 +42,7 @@ define float @ret_fmul_dapz_nonan_nozero__nonan_nozero(float nofpclass(nan zero)
 }
 
 define float @ret_fmul_dynamic_nonan_nozero__nonan_nozero(float nofpclass(nan zero) %arg0, float nofpclass(nan zero) %arg1) #3 {
-; CHECK-LABEL: define float @ret_fmul_dynamic_nonan_nozero__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_dynamic_nonan_nozero__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR3:[0-9]+]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -62,7 +62,7 @@ define float @ret_fmul_ieee_nonan_noinf__nonan_noinf(float nofpclass(nan inf) %a
 }
 
 define float @ret_fmul_ieee_nonan_nozero__nonan_noinf(float nofpclass(nan zero) %arg0, float nofpclass(nan inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan_nozero__nonan_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nonan_nozero__nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -72,7 +72,7 @@ define float @ret_fmul_ieee_nonan_nozero__nonan_noinf(float nofpclass(nan zero)
 }
 
 define float @ret_fmul_ieee_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %arg0, float nofpclass(nan zero) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan_noinf__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nonan_noinf__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -82,7 +82,7 @@ define float @ret_fmul_ieee_nonan_noinf__nonan_nozero(float nofpclass(nan inf) %
 }
 
 define float @ret_fmul_ieee_nonan_noinf__nonan_noposzero(float nofpclass(nan inf) %arg0, float nofpclass(nan pzero) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan_noinf__nonan_noposzero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nonan_noinf__nonan_noposzero
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan pzero) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -92,7 +92,7 @@ define float @ret_fmul_ieee_nonan_noinf__nonan_noposzero(float nofpclass(nan inf
 }
 
 define float @ret_fmul_ieee_nonan_noposzero__nonan_noinf(float nofpclass(nan pzero) %arg0, float nofpclass(nan inf) %arg1) #0 {
-; CHECK-LABEL: define float @ret_fmul_ieee_nonan_noposzero__nonan_noinf
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nonan_noposzero__nonan_noinf
 ; CHECK-SAME: (float nofpclass(nan pzero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR0]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -144,7 +144,7 @@ define float @ret_fmul_dynamic_nonan_nozero_nosub__nonan_nozero_nosub(float nofp
 
 ; Missing no-subnormal on lhs
 define float @ret_fmul_daz_nonan_nozero__nonan_nozero_nosub(float nofpclass(nan zero) %arg0, float nofpclass(nan zero sub) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fmul_daz_nonan_nozero__nonan_nozero_nosub
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_daz_nonan_nozero__nonan_nozero_nosub
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan zero sub) [[ARG1:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -155,7 +155,7 @@ define float @ret_fmul_daz_nonan_nozero__nonan_nozero_nosub(float nofpclass(nan
 
 ; Missing no-subnormal on lhs
 define float @ret_fmul_daz_nonan_nozero_nosub__nonan_nozero(float nofpclass(nan zero sub) %arg0, float nofpclass(nan zero) %arg1) #1 {
-; CHECK-LABEL: define float @ret_fmul_daz_nonan_nozero_nosub__nonan_nozero
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_daz_nonan_nozero_nosub__nonan_nozero
 ; CHECK-SAME: (float nofpclass(nan zero sub) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR1]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -285,7 +285,7 @@ define float @ret_fmul_ieee_noinf_nonan__nozero(float nofpclass(inf nan) %arg0,
 }
 
 define float @ret_fmul_ieee_nozero_nonan__noinf_nonan(float nofpclass(zero nan) %arg0, float nofpclass(inf nan) %arg1) {
-; CHECK-LABEL: define float @ret_fmul_ieee_nozero_nonan__noinf_nonan
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_nozero_nonan__noinf_nonan
 ; CHECK-SAME: (float nofpclass(nan zero) [[ARG0:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
@@ -295,7 +295,7 @@ define float @ret_fmul_ieee_nozero_nonan__noinf_nonan(float nofpclass(zero nan)
 }
 
 define float @ret_fmul_ieee_noinf_nonan__nozero_nonan(float nofpclass(inf nan) %arg0, float nofpclass(zero nan) %arg1) {
-; CHECK-LABEL: define float @ret_fmul_ieee_noinf_nonan__nozero_nonan
+; CHECK-LABEL: define nofpclass(snan) float @ret_fmul_ieee_noinf_nonan__nozero_nonan
 ; CHECK-SAME: (float nofpclass(nan inf) [[ARG0:%.*]], float nofpclass(nan zero) [[ARG1:%.*]]) #[[ATTR4]] {
 ; CHECK-NEXT:    [[FMUL:%.*]] = fmul float [[ARG0]], [[ARG1]]
 ; CHECK-NEXT:    ret float [[FMUL]]
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index 0634f43f3e79c..04749b89663c9 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -1794,7 +1794,7 @@ TEST_F(ComputeKnownFPClassTest, FAdd) {
   expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);
   expectKnownFPClass(fcAllFlags, std::nullopt, A3);
   expectKnownFPClass(fcAllFlags, std::nullopt, A4);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A5);
+  expectKnownFPClass(~fcSNan, std::nullopt, A5);
 }
 
 TEST_F(ComputeKnownFPClassTest, FSub) {
@@ -1811,7 +1811,7 @@ TEST_F(ComputeKnownFPClassTest, FSub) {
   expectKnownFPClass(fcFinite | fcInf, std::nullopt, A2);
   expectKnownFPClass(fcAllFlags, std::nullopt, A3);
   expectKnownFPClass(fcAllFlags, std::nullopt, A4);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A5);
+  expectKnownFPClass(~fcSNan, std::nullopt, A5);
 }
 
 TEST_F(ComputeKnownFPClassTest, FMul) {
@@ -1825,8 +1825,8 @@ TEST_F(ComputeKnownFPClassTest, FMul) {
       "  ret float %A\n"
       "}\n");
   expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A2);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A3);
+  expectKnownFPClass(~fcSNan, std::nullopt, A2);
+  expectKnownFPClass(~fcSNan, std::nullopt, A3);
   expectKnownFPClass(fcAllFlags, std::nullopt, A4);
   expectKnownFPClass(fcPositive, false, A5);
 }
@@ -1845,11 +1845,11 @@ TEST_F(ComputeKnownFPClassTest, FMulNoZero) {
       "}\n");
   expectKnownFPClass(fcFinite | fcInf, std::nullopt, A);
   expectKnownFPClass(fcPositive | fcNan, std::nullopt, A2);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A3);
+  expectKnownFPClass(~fcSNan, std::nullopt, A3);
   expectKnownFPClass(fcAllFlags, std::nullopt, A4);
   expectKnownFPClass(fcAllFlags, std::nullopt, A5);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A6);
-  expectKnownFPClass(fcAllFlags, std::nullopt, A7);
+  expectKnownFPClass(~fcSNan, std::nullopt, A6);
+  expectKnownFPClass(~fcSNan, std::nullopt, A7);
 }
 
 TEST_F(ComputeKnownFPClassTest, MinimumNumSignBit) {



More information about the llvm-commits mailing list