https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/175614
>From d46e8b02aa9b3904956432dbb934e2f5fb9c5fdb Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Mon, 12 Jan 2026 13:32:55 +0100 Subject: [PATCH 1/4] 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 6c1a6a7e9b5c3..e5994a1baf645 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -243,6 +243,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 171952120fc40..f081c61a4ed2b 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 06ddbd038f484791ad5310607ec9b4bd71489d05 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Tue, 13 Jan 2026 18:16:44 +0100 Subject: [PATCH 2/4] 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 f081c61a4ed2b..d1f620ac9eb3d 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 1a4852365951f54d92d5c6a846035c424c59f332 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Tue, 13 Jan 2026 18:43:46 +0100 Subject: [PATCH 3/4] 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) >From 22ce47707998f9277954d7cdea704023d2a12349 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Thu, 15 Jan 2026 19:16:40 +0100 Subject: [PATCH 4/4] use fadd_impl for fma_square case --- llvm/lib/Support/KnownFPClass.cpp | 2 +- .../Transforms/Attributor/nofpclass-fma.ll | 76 +++++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index e96d4b94ec07c..dc7f6d3ca237d 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -357,7 +357,7 @@ KnownFPClass KnownFPClass::fma(const KnownFPClass &KnownLHS, KnownFPClass KnownFPClass::fma_square(const KnownFPClass &KnownSquared, const KnownFPClass &KnownAddend, DenormalMode Mode) { - return fadd(square(KnownSquared, Mode), KnownAddend, Mode); + return fadd_impl(square(KnownSquared, Mode), KnownAddend, Mode); } KnownFPClass KnownFPClass::exp(const KnownFPClass &KnownSrc) { diff --git a/llvm/test/Transforms/Attributor/nofpclass-fma.ll b/llvm/test/Transforms/Attributor/nofpclass-fma.ll index 84f89f3c463d9..c4cdfd5e2b5a7 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) @@ -29,9 +29,9 @@ define float @ret_fma_same_mul_arg_maybe_undef(float %arg0, float %arg1) { } define float @ret_fma_same_mul_arg_positive_addend(float noundef %arg0, float nofpclass(ninf nsub nnorm) %arg1) { -; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fma_same_mul_arg_positive_addend +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_fma_same_mul_arg_positive_addend ; CHECK-SAME: (float noundef [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float nofpclass(ninf nsub nnorm) [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.fma.f32(float noundef [[ARG0]], float noundef [[ARG0]], float nofpclass(ninf nsub nnorm) [[ARG1]]) #[[ATTR2]] ; 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) @@ -69,9 +69,9 @@ define float @ret_fmuladd_same_mul_arg_maybe_undef(float %arg0, float %arg1) { } define float @ret_fmuladd_different_same_arg_positive_addend(float noundef %arg0, float nofpclass(ninf nsub nnorm) %arg1) { -; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_fmuladd_different_same_arg_positive_addend +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) float @ret_fmuladd_different_same_arg_positive_addend ; CHECK-SAME: (float noundef [[ARG0:%.*]], float nofpclass(ninf nsub nnorm) [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nzero nsub nnorm) float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float nofpclass(ninf nsub nnorm) [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(ninf nsub nnorm) float @llvm.fmuladd.f32(float noundef [[ARG0]], float noundef [[ARG0]], float nofpclass(ninf nsub nnorm) [[ARG1]]) #[[ATTR2]] ; CHECK-NEXT: ret float [[CALL]] ; %call = call float @llvm.fmuladd.f32(float %arg0, float %arg0, float %arg1) @@ -231,10 +231,10 @@ define half @ret_fmuladd__pos0__neg1__pos2() { ;--------------------------------------------------------------------- define half @ret_fma__pos01_pos01__pos2() { -; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__pos01_pos01__pos2() { +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) half @ret_fma__pos01_pos01__pos2() { ; CHECK-NEXT: [[POS01:%.*]] = call noundef 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 noundef [[POS01]], half noundef [[POS01]], half [[POS2]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nofpclass(ninf nsub nnorm) half @llvm.fma.f16(half noundef [[POS01]], half noundef [[POS01]], half [[POS2]]) ; CHECK-NEXT: ret half [[RESULT]] ; %pos01 = call noundef half @returns_positive_or_nan() @@ -244,10 +244,10 @@ define half @ret_fma__pos01_pos01__pos2() { } define half @ret_fma__pos01_pos01__neg2() { -; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__pos01_pos01__neg2() { +; CHECK-LABEL: define half @ret_fma__pos01_pos01__neg2() { ; CHECK-NEXT: [[POS01:%.*]] = call noundef 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 noundef [[POS01]], half noundef [[POS01]], half [[NEG2]]) +; CHECK-NEXT: [[RESULT:%.*]] = call half @llvm.fma.f16(half noundef [[POS01]], half noundef [[POS01]], half [[NEG2]]) ; CHECK-NEXT: ret half [[RESULT]] ; %pos01 = call noundef half @returns_positive_or_nan() @@ -257,10 +257,10 @@ define half @ret_fma__pos01_pos01__neg2() { } define half @ret_fma__neg01_neg01__pos2() { -; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fma__neg01_neg01__pos2() { +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) half @ret_fma__neg01_neg01__pos2() { ; CHECK-NEXT: [[NEG01:%.*]] = call noundef 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 noundef [[NEG01]], half noundef [[NEG01]], half [[POS2]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nofpclass(ninf nsub nnorm) half @llvm.fma.f16(half noundef [[NEG01]], half noundef [[NEG01]], half [[POS2]]) ; CHECK-NEXT: ret half [[RESULT]] ; %neg01 = call noundef half @returns_negative_or_nan() @@ -270,10 +270,10 @@ define half @ret_fma__neg01_neg01__pos2() { } define half @ret_fma__neg01_neg01__neg2() { -; CHECK-LABEL: define nofpclass(nzero) half @ret_fma__neg01_neg01__neg2() { +; CHECK-LABEL: define half @ret_fma__neg01_neg01__neg2() { ; CHECK-NEXT: [[NEG01:%.*]] = call noundef 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 noundef [[NEG01]], half noundef [[NEG01]], half [[NEG2]]) +; CHECK-NEXT: [[RESULT:%.*]] = call half @llvm.fma.f16(half noundef [[NEG01]], half noundef [[NEG01]], half [[NEG2]]) ; CHECK-NEXT: ret half [[RESULT]] ; %neg01 = call noundef half @returns_negative_or_nan() @@ -283,10 +283,10 @@ define half @ret_fma__neg01_neg01__neg2() { } define half @ret_fmuladd__pos01_pos01__pos2() { -; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) half @ret_fmuladd__pos01_pos01__pos2() { +; CHECK-LABEL: define nofpclass(ninf nsub nnorm) half @ret_fmuladd__pos01_pos01__pos2() { ; CHECK-NEXT: [[POS01:%.*]] = call noundef 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.fmuladd.f16(half noundef [[POS01]], half noundef [[POS01]], half [[POS2]]) +; CHECK-NEXT: [[RESULT:%.*]] = call nofpclass(ninf nsub nnorm) half @llvm.fmuladd.f16(half noundef [[POS01]], half noundef [[POS01]], half [[POS2]]) ; CHECK-NEXT: ret half [[RESULT]] ; %pos01 = call noundef half @returns_positive_or_nan() @@ -364,9 +364,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 nofpclass(nzero) half @ret_fma_square__no_nan__no_nan +; CHECK-LABEL: define half @ret_fma_square__no_nan__no_nan ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan) [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan) [[ARG1]]) #[[ATTR2]] +; 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: ret half [[CALL]] ; %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1) @@ -374,9 +374,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 nofpclass(nzero) half @ret_fma_square__no_nan__no_nan_zero +; CHECK-LABEL: define 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 nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan zero) [[ARG1]]) #[[ATTR2]] +; 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: ret half [[CALL]] ; %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1) @@ -384,9 +384,9 @@ define half @ret_fma_square__no_nan__no_nan_zero(half noundef nofpclass(nan) %ar } define half @ret_fma_square__no_nan__no_nan_inf_zero(half noundef nofpclass(nan) %arg0, half nofpclass(nan inf zero) %arg1) { -; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan__no_nan_inf_zero +; CHECK-LABEL: define half @ret_fma_square__no_nan__no_nan_inf_zero ; CHECK-SAME: (half noundef nofpclass(nan) [[ARG0:%.*]], half nofpclass(nan inf zero) [[ARG1:%.*]]) #[[ATTR1]] { -; CHECK-NEXT: [[CALL:%.*]] = call nofpclass(nzero) half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[ARG0]], half nofpclass(nan inf zero) [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan) [[ARG0]], half noundef nofpclass(nan) [[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) @@ -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(nan nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf_zero +; CHECK-LABEL: define nofpclass(nan) 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(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: [[CALL:%.*]] = call nofpclass(nan) 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(nan nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_inf +; CHECK-LABEL: define nofpclass(nan) 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(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: [[CALL:%.*]] = call nofpclass(nan) 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(nan nzero) half @ret_fma_square__no_nan_no_inf__no_nan_inf +; CHECK-LABEL: define nofpclass(nan) 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(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: [[CALL:%.*]] = call nofpclass(nan) 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(nan nzero) half @ret_fma_square__no_nan_no_inf__no_nan_no_inf +; CHECK-LABEL: define nofpclass(nan) 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(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: [[CALL:%.*]] = call nofpclass(nan) 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) @@ -434,9 +434,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 nofpclass(nzero) half @ret_fma_square__no_nan_no_inf__no_nan_no_pinf +; CHECK-LABEL: define 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 nofpclass(nzero) 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 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) @@ -444,9 +444,9 @@ define half @ret_fma_square__no_nan_no_inf__no_nan_no_pinf(half noundef nofpclas } define half @ret_fma_square__no_nan_no_inf__no_nan_no_ninf(half noundef nofpclass(nan inf) %arg0, half nofpclass(nan ninf) %arg1) { -; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf__no_nan_no_ninf +; CHECK-LABEL: define half @ret_fma_square__no_nan_no_inf__no_nan_no_ninf ; CHECK-SAME: (half noundef nofpclass(nan inf) [[ARG0:%.*]], half nofpclass(nan ninf) [[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 ninf) [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan inf) [[ARG0]], half noundef nofpclass(nan inf) [[ARG0]], half nofpclass(nan ninf) [[ARG1]]) #[[ATTR2]] ; CHECK-NEXT: ret half [[CALL]] ; %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1) @@ -454,9 +454,9 @@ define half @ret_fma_square__no_nan_no_inf__no_nan_no_ninf(half noundef nofpclas } define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_no_ninf(half noundef nofpclass(nan inf zero) %arg0, half nofpclass(nan ninf) %arg1) { -; CHECK-LABEL: define nofpclass(nzero) half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_no_ninf +; CHECK-LABEL: define half @ret_fma_square__no_nan_no_inf_no_zero__no_nan_no_ninf ; CHECK-SAME: (half noundef nofpclass(nan inf zero) [[ARG0:%.*]], half nofpclass(nan ninf) [[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 ninf) [[ARG1]]) #[[ATTR2]] +; CHECK-NEXT: [[CALL:%.*]] = call half @llvm.fma.f16(half noundef nofpclass(nan inf zero) [[ARG0]], half noundef nofpclass(nan inf zero) [[ARG0]], half nofpclass(nan ninf) [[ARG1]]) #[[ATTR2]] ; CHECK-NEXT: ret half [[CALL]] ; %call = call half @llvm.fma.f16(half %arg0, half %arg0, half %arg1) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
