[llvm-branch-commits] [llvm] ValueTracking: Improve handling for fma/fmuladd (PR #175614)

Matt Arsenault via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Jan 14 11:24:20 PST 2026


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

>From 4a31e2d982fc3a107445a113b1ec04aaec2a05fe Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 12 Jan 2026 13:32:55 +0100
Subject: [PATCH 1/3] ValueTracking: Improve handling for fma/fmuladd

The handling for fma was very basic and only handled the
repeated input case. Re-use the fmul and fadd handling for more
accurate sign bit and nan handling.
---
 llvm/include/llvm/Support/KnownFPClass.h      | 11 +++
 llvm/lib/Analysis/ValueTracking.cpp           | 46 ++++++++---
 llvm/lib/Support/KnownFPClass.cpp             | 13 +++
 .../Transforms/Attributor/nofpclass-fma.ll    | 80 +++++++++----------
 4 files changed, 98 insertions(+), 52 deletions(-)

diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h
index e2b0d20c790a9..ceb488fe8f66c 100644
--- a/llvm/include/llvm/Support/KnownFPClass.h
+++ b/llvm/include/llvm/Support/KnownFPClass.h
@@ -237,6 +237,17 @@ struct KnownFPClass {
     return Known;
   }
 
+  /// Report known values for fma
+  LLVM_ABI static KnownFPClass
+  fma(const KnownFPClass &LHS, const KnownFPClass &RHS,
+      const KnownFPClass &Addend,
+      DenormalMode Mode = DenormalMode::getDynamic());
+
+  /// Report known values for fma squared, squared, addend
+  LLVM_ABI static KnownFPClass
+  fma_square(const KnownFPClass &Squared, const KnownFPClass &Addend,
+             DenormalMode Mode = DenormalMode::getDynamic());
+
   /// Report known values for exp, exp2 and exp10.
   LLVM_ABI static KnownFPClass exp(const KnownFPClass &Src);
 
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index ece8425aef698..85ed2e435ecae 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5128,21 +5128,43 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       if ((InterestedClasses & fcNegative) == fcNone)
         break;
 
-      if (II->getArgOperand(0) != II->getArgOperand(1) ||
-          !isGuaranteedNotToBeUndef(II->getArgOperand(0), Q.AC, Q.CxtI, Q.DT,
-                                    Depth + 1))
-        break;
+      if (II->getArgOperand(0) == II->getArgOperand(1) &&
+          isGuaranteedNotToBeUndef(II->getArgOperand(0), Q.AC, Q.CxtI, Q.DT,
+                                   Depth + 1)) {
+        KnownFPClass KnownAddend;
+        computeKnownFPClass(II->getArgOperand(2), DemandedElts,
+                            InterestedClasses, KnownAddend, Q, Depth + 1);
+        if (KnownAddend.isUnknown())
+          return;
 
-      // The multiply cannot be -0 and therefore the add can't be -0
-      Known.knownNot(fcNegZero);
+        KnownFPClass KnownSrc;
+        computeKnownFPClass(II->getArgOperand(0), DemandedElts,
+                            InterestedClasses, KnownSrc, Q, Depth + 1);
 
-      // x * x + y is non-negative if y is non-negative.
-      KnownFPClass KnownAddend;
-      computeKnownFPClass(II->getArgOperand(2), DemandedElts, InterestedClasses,
-                          KnownAddend, Q, Depth + 1);
+        const Function *F = II->getFunction();
+        const fltSemantics &FltSem =
+            II->getType()->getScalarType()->getFltSemantics();
+        DenormalMode Mode =
+            F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
 
-      if (KnownAddend.cannotBeOrderedLessThanZero())
-        Known.knownNot(fcNegative);
+        Known = KnownFPClass::fma_square(KnownSrc, KnownAddend, Mode);
+        break;
+      }
+
+      KnownFPClass KnownSrc[3];
+      for (int I = 0; I != 3; ++I) {
+        computeKnownFPClass(II->getArgOperand(I), DemandedElts,
+                            InterestedClasses, KnownSrc[I], Q, Depth + 1);
+        if (KnownSrc[I].isUnknown())
+          return;
+      }
+
+      const Function *F = II->getFunction();
+      const fltSemantics &FltSem =
+          II->getType()->getScalarType()->getFltSemantics();
+      DenormalMode Mode =
+          F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic();
+      Known = KnownFPClass::fma(KnownSrc[0], KnownSrc[1], KnownSrc[2], Mode);
       break;
     }
     case Intrinsic::sqrt:
diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index ae8c4a9133897..abf7e01377796 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -332,6 +332,19 @@ KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS,
   return Known;
 }
 
+KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
+                               const KnownFPClass &KnownRHS,
+                               const KnownFPClass &KnownAddend,
+                               DenormalMode Mode) {
+  return fadd(fmul(KnownLHS, KnownRHS, Mode), KnownAddend, Mode);
+}
+
+KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
+                                      const KnownFPClass &KnownAddend,
+                                      DenormalMode Mode) {
+  return fadd(square(KnownSquared, Mode), KnownAddend, Mode);
+}
+
 KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) {
   KnownFPClass Known;
   Known.knownNot(fcNegative);
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fma.ll b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
index a1e0d1964f0c1..ec6a37ff9a720 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fma.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
@@ -9,9 +9,9 @@ declare nofpclass(pinf pzero psub pnorm) half @returns_negative_or_nan()
 
 
 define float @ret_fma_same_mul_arg(float noundef %arg0, float %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) float @ret_fma_same_mul_arg
+; CHECK-LABEL: define float @ret_fma_same_mul_arg
 ; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
@@ -49,9 +49,9 @@ define float @ret_fma_different_mul_arg_positive_addend(float noundef %arg0, flo
 }
 
 define float @ret_fmuladd_same_mul_arg(float noundef %arg0, float %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) float @ret_fmuladd_same_mul_arg
+; CHECK-LABEL: define float @ret_fmuladd_same_mul_arg
 ; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.fmuladd.f32(float %arg0, float %arg0, float %arg1)
@@ -84,11 +84,11 @@ define float @ret_fmuladd_different_same_arg_positive_addend(float noundef %arg0
 
 ; 1. operand0=positive, operand1=negative, operand2=positive
 define half @ret_fma__pos0__neg1__pos2() {
-; CHECK-LABEL: define half @ret_fma__pos0__neg1__pos2() {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__pos0__neg1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -100,11 +100,11 @@ define half @ret_fma__pos0__neg1__pos2() {
 
 ; 2. operand0=positive, operand1=negative, operand2=negative
 define half @ret_fma__pos0__neg1__neg2() {
-; CHECK-LABEL: define half @ret_fma__pos0__neg1__neg2() {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) half @ret_fma__pos0__neg1__neg2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(pinf psub pnorm) half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -116,11 +116,11 @@ define half @ret_fma__pos0__neg1__neg2() {
 
 ; 3. operand0=positive, operand1=positive, operand2=positive
 define half @ret_fma__pos0__pos1__pos2() {
-; CHECK-LABEL: define half @ret_fma__pos0__pos1__pos2() {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__pos0__pos1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -132,11 +132,11 @@ define half @ret_fma__pos0__pos1__pos2() {
 
 ; 4. operand0=positive, operand1=positive, operand2=negative
 define half @ret_fma__pos0__pos1__neg2() {
-; CHECK-LABEL: define half @ret_fma__pos0__pos1__neg2() {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__pos0__pos1__neg2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -148,11 +148,11 @@ define half @ret_fma__pos0__pos1__neg2() {
 
 ; 5. operand0=negative, operand1=negative, operand2=positive
 define half @ret_fma__neg0__neg1__pos2() {
-; CHECK-LABEL: define half @ret_fma__neg0__neg1__pos2() {
+; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__neg0__neg1__pos2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -164,11 +164,11 @@ define half @ret_fma__neg0__neg1__pos2() {
 
 ; 6. operand0=negative, operand1=negative, operand2=negative
 define half @ret_fma__neg0__neg1__neg2() {
-; CHECK-LABEL: define half @ret_fma__neg0__neg1__neg2() {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__neg0__neg1__neg2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -180,11 +180,11 @@ define half @ret_fma__neg0__neg1__neg2() {
 
 ; 7. operand0=negative, operand1=positive, operand2=positive
 define half @ret_fma__neg0__pos1__pos2() {
-; CHECK-LABEL: define half @ret_fma__neg0__pos1__pos2() {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__neg0__pos1__pos2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -196,11 +196,11 @@ define half @ret_fma__neg0__pos1__pos2() {
 
 ; 8. operand0=negative, operand1=positive, operand2=negative
 define half @ret_fma__neg0__pos1__neg2() {
-; CHECK-LABEL: define half @ret_fma__neg0__pos1__neg2() {
+; CHECK-LABEL: define nofpclass(pinf psub pnorm) half @ret_fma__neg0__pos1__neg2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(pinf psub pnorm) half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -212,11 +212,11 @@ define half @ret_fma__neg0__pos1__neg2() {
 
 ; 1. operand0=positive, operand1=negative, operand2=positive
 define half @ret_fmuladd__pos0__neg1__pos2() {
-; CHECK-LABEL: define half @ret_fmuladd__pos0__neg1__pos2() {
+; CHECK-LABEL: define nofpclass(nzero) half @ret_fmuladd__pos0__neg1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fmuladd.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fmuladd.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -311,9 +311,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(nzero) 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(nzero) 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)
@@ -321,9 +321,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(nzero) 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(nzero) 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)
@@ -332,9 +332,9 @@ define half @ret_fma__no_nan__no_nan__no_nan_inf(half nofpclass(nan) %arg0, half
 
 ; can infer no-nan output
 define half @ret_fma__no_nan_inf__no_nan_inf__no_nan_inf(half nofpclass(nan inf) %arg0, half nofpclass(nan inf) %arg1, half nofpclass(nan inf) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan_inf__no_nan_inf__no_nan_inf
+; CHECK-LABEL: define nofpclass(nan) half @ret_fma__no_nan_inf__no_nan_inf__no_nan_inf
 ; CHECK-SAME: (half nofpclass(nan inf) [[ARG0:%.*]], half nofpclass(nan inf) [[ARG1:%.*]], half nofpclass(nan inf) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan inf) [[ARG0]], half nofpclass(nan inf) [[ARG1]], half nofpclass(nan inf) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nan) half @llvm.fma.f16(half nofpclass(nan inf) [[ARG0]], half nofpclass(nan inf) [[ARG1]], half nofpclass(nan inf) [[ARG2]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -343,9 +343,9 @@ define half @ret_fma__no_nan_inf__no_nan_inf__no_nan_inf(half nofpclass(nan inf)
 
 ; can infer no-nan output
 define half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf(half nofpclass(nan zero) %arg0, half nofpclass(nan zero) %arg1, half nofpclass(nan zero inf) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf
+; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf
 ; CHECK-SAME: (half nofpclass(nan zero) [[ARG0:%.*]], half nofpclass(nan zero) [[ARG1:%.*]], half nofpclass(nan inf zero) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan zero) [[ARG0]], half nofpclass(nan zero) [[ARG1]], half nofpclass(nan inf zero) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half nofpclass(nan zero) [[ARG0]], half nofpclass(nan zero) [[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)
@@ -353,9 +353,9 @@ define half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf(half nof
 }
 
 define half @ret_fma__no_nan_ninf_zero__no_nan_ninf_zero__no_nan_inf(half nofpclass(nan ninf zero) %arg0, half nofpclass(nan ninf zero) %arg1, half nofpclass(nan inf) %arg2) {
-; CHECK-LABEL: define half @ret_fma__no_nan_ninf_zero__no_nan_ninf_zero__no_nan_inf
+; CHECK-LABEL: define nofpclass(nan) half @ret_fma__no_nan_ninf_zero__no_nan_ninf_zero__no_nan_inf
 ; CHECK-SAME: (half nofpclass(nan ninf zero) [[ARG0:%.*]], half nofpclass(nan ninf zero) [[ARG1:%.*]], half nofpclass(nan inf) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half nofpclass(nan ninf zero) [[ARG0]], half nofpclass(nan ninf zero) [[ARG1]], half nofpclass(nan inf) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nan) half @llvm.fma.f16(half nofpclass(nan ninf zero) [[ARG0]], half nofpclass(nan ninf zero) [[ARG1]], half nofpclass(nan inf) [[ARG2]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -394,9 +394,9 @@ define half @ret_fma_square__no_nan__no_nan_inf_zero(half noundef nofpclass(nan)
 }
 
 define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf_zero(half noundef nofpclass(nan inf zero) %arg0, half nofpclass(nan inf zero) %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf_zero
+; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf_zero
 ; CHECK-SAME: (half noundef nofpclass(nan inf zero) [[ARG0:%.*]], half nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf zero) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf zero) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -404,9 +404,9 @@ define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf_zero(half noundef
 }
 
 define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf(half noundef nofpclass(nan inf zero) %arg0, half nofpclass(nan inf) %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf
+; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf
 ; CHECK-SAME: (half noundef nofpclass(nan inf zero) [[ARG0:%.*]], half nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -414,9 +414,9 @@ define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf(half noundef nofp
 }
 
 define half @ret_fma_square__no_nan_no_inf__no_nan_inf(half noundef nofpclass(nan inf zero) %arg0, half nofpclass(nan inf) %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf__no_nan_inf
+; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma_square__no_nan_no_inf__no_nan_inf
 ; CHECK-SAME: (half noundef nofpclass(nan inf zero) [[ARG0:%.*]], half nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)
@@ -424,9 +424,9 @@ define half @ret_fma_square__no_nan_no_inf__no_nan_inf(half noundef nofpclass(na
 }
 
 define half @ret_fma_square__no_nan_no_inf__no_nan_no_inf(half noundef nofpclass(nan inf) %arg0, half nofpclass(nan inf) %arg1) {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf__no_nan_no_inf
+; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma_square__no_nan_no_inf__no_nan_no_inf
 ; CHECK-SAME: (half noundef nofpclass(nan inf) [[ARG0:%.*]], half nofpclass(nan inf) [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf) [[ARG0]], half noundef nofpclass(nan inf) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half noundef nofpclass(nan inf) [[ARG0]], half noundef nofpclass(nan inf) [[ARG0]], half nofpclass(nan inf) [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret half [[CALL]]
 ;
   %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1)

>From ae318a7c83c06fafab05f709ed517095b6639555 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 13 Jan 2026 18:16:44 +0100
Subject: [PATCH 2/3] Fix regression

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

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 85ed2e435ecae..a99fca1de3118 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5131,13 +5131,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
       if (II->getArgOperand(0) == II->getArgOperand(1) &&
           isGuaranteedNotToBeUndef(II->getArgOperand(0), Q.AC, Q.CxtI, Q.DT,
                                    Depth + 1)) {
-        KnownFPClass KnownAddend;
+        KnownFPClass KnownSrc, KnownAddend;
         computeKnownFPClass(II->getArgOperand(2), DemandedElts,
                             InterestedClasses, KnownAddend, Q, Depth + 1);
-        if (KnownAddend.isUnknown())
-          return;
-
-        KnownFPClass KnownSrc;
         computeKnownFPClass(II->getArgOperand(0), DemandedElts,
                             InterestedClasses, KnownSrc, Q, Depth + 1);
 

>From 22c10b0dea3c90f8778f57fbdb5fe0ec51cb2182 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 13 Jan 2026 18:43:46 +0100
Subject: [PATCH 3/3] Can't prove -0 for fma

---
 llvm/lib/Support/KnownFPClass.cpp             | 27 ++++++++---
 .../Transforms/Attributor/nofpclass-fma.ll    | 48 +++++++++----------
 2 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp
index abf7e01377796..e96d4b94ec07c 100644
--- a/llvm/lib/Support/KnownFPClass.cpp
+++ b/llvm/lib/Support/KnownFPClass.cpp
@@ -233,9 +233,9 @@ KnownFPClass KnownFPClass::canonicalize(const KnownFPClass &KnownSrc,
   return Known;
 }
 
-KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
-                                const KnownFPClass &KnownRHS,
-                                DenormalMode Mode) {
+// Handle known sign bit and nan cases for fadd.
+static KnownFPClass fadd_impl(const KnownFPClass &KnownLHS,
+                              const KnownFPClass &KnownRHS, DenormalMode Mode) {
   KnownFPClass Known;
 
   // Adding positive and negative infinity produces NaN.
@@ -246,11 +246,19 @@ KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
 
   if (KnownLHS.cannotBeOrderedLessThanZero() &&
       KnownRHS.cannotBeOrderedLessThanZero())
-    Known.knownNot(OrderedLessThanZeroMask);
+    Known.knownNot(KnownFPClass::OrderedLessThanZeroMask);
 
   if (KnownLHS.cannotBeOrderedGreaterThanZero() &&
       KnownRHS.cannotBeOrderedGreaterThanZero())
-    Known.knownNot(OrderedGreaterThanZeroMask);
+    Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask);
+
+  return Known;
+}
+
+KnownFPClass KnownFPClass::fadd(const KnownFPClass &KnownLHS,
+                                const KnownFPClass &KnownRHS,
+                                DenormalMode Mode) {
+  KnownFPClass Known = fadd_impl(KnownLHS, KnownRHS, Mode);
 
   // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0.
   if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) ||
@@ -336,7 +344,14 @@ KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS,
                                const KnownFPClass &KnownRHS,
                                const KnownFPClass &KnownAddend,
                                DenormalMode Mode) {
-  return fadd(fmul(KnownLHS, KnownRHS, Mode), KnownAddend, Mode);
+  KnownFPClass Mul = fmul(KnownLHS, KnownRHS, Mode);
+
+  // FMA differs from the base fmul + fadd handling only in the treatment of -0
+  // results.
+  //
+  // 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 KnownFPClass::fma_square(const KnownFPClass &KnownSquared,
diff --git a/llvm/test/Transforms/Attributor/nofpclass-fma.ll b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
index ec6a37ff9a720..84f89f3c463d9 100644
--- a/llvm/test/Transforms/Attributor/nofpclass-fma.ll
+++ b/llvm/test/Transforms/Attributor/nofpclass-fma.ll
@@ -9,9 +9,9 @@ declare nofpclass(pinf pzero psub pnorm) half @returns_negative_or_nan()
 
 
 define float @ret_fma_same_mul_arg(float noundef %arg0, float %arg1) {
-; CHECK-LABEL: define float @ret_fma_same_mul_arg
+; CHECK-LABEL: define nofpclass(nzero) float @ret_fma_same_mul_arg
 ; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1:[0-9]+]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.fma.f32(float %arg0, float %arg0, float %arg1)
@@ -49,9 +49,9 @@ define float @ret_fma_different_mul_arg_positive_addend(float noundef %arg0, flo
 }
 
 define float @ret_fmuladd_same_mul_arg(float noundef %arg0, float %arg1) {
-; CHECK-LABEL: define float @ret_fmuladd_same_mul_arg
+; CHECK-LABEL: define nofpclass(nzero) float @ret_fmuladd_same_mul_arg
 ; CHECK-SAME: (float noundef [[ARG0:%.*]], float [[ARG1:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[CALL:%.*]] = call float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2]]
+; CHECK-NEXT:    [[CALL:%.*]] = call nofpclass(nzero) float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float [[ARG1]]) #[[ATTR2]]
 ; CHECK-NEXT:    ret float [[CALL]]
 ;
   %call = call float @llvm.fmuladd.f32(float %arg0, float %arg0, float %arg1)
@@ -84,11 +84,11 @@ define float @ret_fmuladd_different_same_arg_positive_addend(float noundef %arg0
 
 ; 1. operand0=positive, operand1=negative, operand2=positive
 define half @ret_fma__pos0__neg1__pos2() {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__pos0__neg1__pos2() {
+; CHECK-LABEL: define half @ret_fma__pos0__neg1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -116,11 +116,11 @@ define half @ret_fma__pos0__neg1__neg2() {
 
 ; 3. operand0=positive, operand1=positive, operand2=positive
 define half @ret_fma__pos0__pos1__pos2() {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__pos0__pos1__pos2() {
+; CHECK-LABEL: define nofpclass(ninf nsub nnorm) half @ret_fma__pos0__pos1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nsub nnorm) half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -132,11 +132,11 @@ define half @ret_fma__pos0__pos1__pos2() {
 
 ; 4. operand0=positive, operand1=positive, operand2=negative
 define half @ret_fma__pos0__pos1__neg2() {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__pos0__pos1__neg2() {
+; CHECK-LABEL: define half @ret_fma__pos0__pos1__neg2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[POS0]], half [[POS1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -148,11 +148,11 @@ define half @ret_fma__pos0__pos1__neg2() {
 
 ; 5. operand0=negative, operand1=negative, operand2=positive
 define half @ret_fma__neg0__neg1__pos2() {
-; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__neg0__neg1__pos2() {
+; CHECK-LABEL: define nofpclass(ninf nsub nnorm) half @ret_fma__neg0__neg1__pos2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nzero nsub nnorm) half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(ninf nsub nnorm) half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -164,11 +164,11 @@ define half @ret_fma__neg0__neg1__pos2() {
 
 ; 6. operand0=negative, operand1=negative, operand2=negative
 define half @ret_fma__neg0__neg1__neg2() {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__neg0__neg1__neg2() {
+; CHECK-LABEL: define half @ret_fma__neg0__neg1__neg2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[NEG2:%.*]] = call half @returns_negative_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[NEG2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[NEG1]], half [[NEG2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -180,11 +180,11 @@ define half @ret_fma__neg0__neg1__neg2() {
 
 ; 7. operand0=negative, operand1=positive, operand2=positive
 define half @ret_fma__neg0__pos1__pos2() {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__neg0__pos1__pos2() {
+; CHECK-LABEL: define half @ret_fma__neg0__pos1__pos2() {
 ; CHECK-NEXT:    [[NEG0:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS1:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fma.f16(half [[NEG0]], half [[POS1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %neg0 = call half @returns_negative_or_nan()
@@ -212,11 +212,11 @@ define half @ret_fma__neg0__pos1__neg2() {
 
 ; 1. operand0=positive, operand1=negative, operand2=positive
 define half @ret_fmuladd__pos0__neg1__pos2() {
-; CHECK-LABEL: define nofpclass(nzero) half @ret_fmuladd__pos0__neg1__pos2() {
+; CHECK-LABEL: define half @ret_fmuladd__pos0__neg1__pos2() {
 ; CHECK-NEXT:    [[POS0:%.*]] = call half @returns_positive_or_nan()
 ; CHECK-NEXT:    [[NEG1:%.*]] = call half @returns_negative_or_nan()
 ; CHECK-NEXT:    [[POS2:%.*]] = call half @returns_positive_or_nan()
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nzero) half @llvm.fmuladd.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
+; CHECK-NEXT:    [[RESULT:%.*]] = call half @llvm.fmuladd.f16(half [[POS0]], half [[NEG1]], half [[POS2]])
 ; CHECK-NEXT:    ret half [[RESULT]]
 ;
   %pos0 = call half @returns_positive_or_nan()
@@ -311,9 +311,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 nofpclass(nzero) half @ret_fma__no_nan__no_nan__no_nan_zero
+; CHECK-LABEL: define 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 nofpclass(nzero) half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan zero) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call 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)
@@ -321,9 +321,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 nofpclass(nzero) half @ret_fma__no_nan__no_nan__no_nan_inf
+; CHECK-LABEL: define 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 nofpclass(nzero) half @llvm.fma.f16(half nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]], half nofpclass(nan inf zero) [[ARG2]]) #[[ATTR2]]
+; 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:    ret half [[RESULT]]
 ;
   %result = call half @llvm.fma.f16(half %arg0, half %arg1, half %arg2)
@@ -343,9 +343,9 @@ define half @ret_fma__no_nan_inf__no_nan_inf__no_nan_inf(half nofpclass(nan inf)
 
 ; can infer no-nan output
 define half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf(half nofpclass(nan zero) %arg0, half nofpclass(nan zero) %arg1, half nofpclass(nan zero inf) %arg2) {
-; CHECK-LABEL: define nofpclass(nan nzero) half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf
+; CHECK-LABEL: define nofpclass(nan) half @ret_fma__no_nan_zero_inf__no_nan_zero_inf__no_nan_zero_inf
 ; CHECK-SAME: (half nofpclass(nan zero) [[ARG0:%.*]], half nofpclass(nan zero) [[ARG1:%.*]], half nofpclass(nan inf zero) [[ARG2:%.*]]) #[[ATTR1]] {
-; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nan nzero) half @llvm.fma.f16(half nofpclass(nan zero) [[ARG0]], half nofpclass(nan zero) [[ARG1]], half nofpclass(nan inf zero) [[ARG2]]) #[[ATTR2]]
+; CHECK-NEXT:    [[RESULT:%.*]] = call nofpclass(nan) half @llvm.fma.f16(half nofpclass(nan zero) [[ARG0]], half nofpclass(nan zero) [[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)



More information about the llvm-branch-commits mailing list