https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/175852
>From d96ba8b2e5a122703515cb499974cb82d9828214 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Mon, 5 Jan 2026 14:20:21 +0100 Subject: [PATCH 1/2] InstCombine: Handle fsub in SimplifyDemandedFPClass alive2 fails on some of the tests, but this is due to existing folds in instsimplify and https://github.com/AliveToolkit/alive2/issues/1273 --- llvm/include/llvm/Support/KnownFPClass.h | 5 + llvm/lib/Analysis/ValueTracking.cpp | 81 +++-------- llvm/lib/Support/KnownFPClass.cpp | 21 +++ .../InstCombineSimplifyDemanded.cpp | 15 +- .../simplify-demanded-fpclass-fsub.ll | 128 ++++++++---------- 5 files changed, 112 insertions(+), 138 deletions(-) diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index e2b0d20c790a9..010ca6a3e84ec 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -222,6 +222,11 @@ struct KnownFPClass { fadd_self(const KnownFPClass &Src, DenormalMode Mode = DenormalMode::getDynamic()); + /// Report known values for fsub + LLVM_ABI static KnownFPClass + fsub(const KnownFPClass &LHS, const KnownFPClass &RHS, + DenormalMode Mode = DenormalMode::getDynamic()); + /// Report known values for fmul LLVM_ABI static KnownFPClass fmul(const KnownFPClass &LHS, const KnownFPClass &RHS, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index ece8425aef698..51fbffd6fd371 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5524,78 +5524,37 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, KnownRHS, Q, Depth + 1); // Special case fadd x, x, which is the canonical form of fmul x, 2. - bool SelfAdd = Op->getOperand(0) == Op->getOperand(1) && - isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI, - Q.DT, Depth + 1); - if (SelfAdd) + bool Self = Op->getOperand(0) == Op->getOperand(1) && + isGuaranteedNotToBeUndef(Op->getOperand(0), Q.AC, Q.CxtI, Q.DT, + Depth + 1); + if (Self) KnownLHS = KnownRHS; if ((WantNaN && KnownRHS.isKnownNeverNaN()) || (WantNegative && KnownRHS.cannotBeOrderedLessThanZero()) || WantNegZero || Opc == Instruction::FSub) { - if (!SelfAdd) { - // RHS is canonically cheaper to compute. Skip inspecting the LHS if - // there's no point. - computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs, - KnownLHS, Q, Depth + 1); - } - - // Adding positive and negative infinity produces NaN. - // TODO: Check sign of infinities. - if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() && - (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity())) - Known.knownNot(fcNan); - // FIXME: Context function should always be passed in separately const Function *F = cast<Instruction>(Op)->getFunction(); + const fltSemantics &FltSem = + Op->getType()->getScalarType()->getFltSemantics(); + DenormalMode Mode = + F ? F->getDenormalMode(FltSem) : DenormalMode::getDynamic(); - if (Op->getOpcode() == Instruction::FAdd) { - if (KnownLHS.cannotBeOrderedLessThanZero() && - KnownRHS.cannotBeOrderedLessThanZero()) - Known.knownNot(KnownFPClass::OrderedLessThanZeroMask); - if (KnownLHS.cannotBeOrderedGreaterThanZero() && - KnownRHS.cannotBeOrderedGreaterThanZero()) - Known.knownNot(KnownFPClass::OrderedGreaterThanZeroMask); - - if (!F) - break; - - const fltSemantics &FltSem = - Op->getType()->getScalarType()->getFltSemantics(); - DenormalMode Mode = F->getDenormalMode(FltSem); - - // Doubling 0 will give the same 0. - if (SelfAdd && KnownRHS.isKnownNeverLogicalPosZero(Mode) && - (Mode.Output == DenormalMode::IEEE || - (Mode.Output == DenormalMode::PreserveSign && - KnownRHS.isKnownNeverPosSubnormal()) || - (Mode.Output == DenormalMode::PositiveZero && - KnownRHS.isKnownNeverSubnormal()))) - Known.knownNot(fcPosZero); - - // (fadd x, 0.0) is guaranteed to return +0.0, not -0.0. - if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) || - KnownRHS.isKnownNeverLogicalNegZero(Mode)) && - // Make sure output negative denormal can't flush to -0 - (Mode.Output == DenormalMode::IEEE || - Mode.Output == DenormalMode::PositiveZero)) - Known.knownNot(fcNegZero); + if (Self && Opc == Instruction::FAdd) { + Known = KnownFPClass::fadd_self(KnownLHS, Mode); } else { - if (!F) - break; + // RHS is canonically cheaper to compute. Skip inspecting the LHS if + // there's no point. - const fltSemantics &FltSem = - Op->getType()->getScalarType()->getFltSemantics(); - DenormalMode Mode = F->getDenormalMode(FltSem); - - // Only fsub -0, +0 can return -0 - if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) || - KnownRHS.isKnownNeverLogicalPosZero(Mode)) && - // Make sure output negative denormal can't flush to -0 - (Mode.Output == DenormalMode::IEEE || - Mode.Output == DenormalMode::PositiveZero)) - Known.knownNot(fcNegZero); + if (!Self) { + computeKnownFPClass(Op->getOperand(0), DemandedElts, InterestedSrcs, + KnownLHS, Q, Depth + 1); + } + + Known = Opc == Instruction::FAdd + ? KnownFPClass::fadd(KnownLHS, KnownRHS, Mode) + : KnownFPClass::fsub(KnownLHS, KnownRHS, Mode); } } diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index ae8c4a9133897..dbd5707873f5d 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -279,6 +279,27 @@ KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc, return Known; } +KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS, + const KnownFPClass &KnownRHS, + DenormalMode Mode) { + KnownFPClass Known; + // Adding positive and negative infinity produces NaN. + // TODO: Check sign of infinities. + if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() && + (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity())) + Known.knownNot(fcNan); + + // Only fsub -0, +0 can return -0 + if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) || + KnownRHS.isKnownNeverLogicalPosZero(Mode)) && + // Make sure output negative denormal can't flush to -0 + (Mode.Output == DenormalMode::IEEE || + Mode.Output == DenormalMode::PositiveZero)) + Known.knownNot(fcNegZero); + + return Known; +} + KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS, const KnownFPClass &KnownRHS, DenormalMode Mode) { diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 05ed123b8be75..a483f44c01ab8 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2081,13 +2081,15 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, Known.fneg(); break; } - case Instruction::FAdd: { + case Instruction::FAdd: + case Instruction::FSub: { KnownFPClass KnownLHS, KnownRHS; const SimplifyQuery &SQ = getSimplifyQuery(); // fadd x, x can be handled more aggressively. if (I->getOperand(0) == I->getOperand(1) && + I->getOpcode() == Instruction::FAdd && isGuaranteedNotToBeUndef(I->getOperand(0), SQ.AC, CxtI, SQ.DT, Depth + 1)) { Type *EltTy = VTy->getScalarType(); @@ -2141,7 +2143,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, Type *EltTy = VTy->getScalarType(); DenormalMode Mode = F.getDenormalMode(EltTy->getFltSemantics()); - Known = KnownFPClass::fadd(KnownLHS, KnownRHS, Mode); + + Known = I->getOpcode() == Instruction::FAdd + ? KnownFPClass::fadd(KnownLHS, KnownRHS, Mode) + : KnownFPClass::fsub(KnownLHS, KnownRHS, Mode); } FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; @@ -2157,11 +2162,13 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, } // With nnan: X + {+/-}Inf --> {+/-}Inf - if (KnownRHS.isKnownAlways(fcInf | fcNan) && - KnownLHS.isKnownNever(fcNan)) + if (I->getOpcode() == Instruction::FAdd && + KnownRHS.isKnownAlways(fcInf | fcNan) && KnownLHS.isKnownNever(fcNan)) { return I->getOperand(1); + } // With nnan: {+/-}Inf + X --> {+/-}Inf + // With nnan: {+/-}Inf - X --> {+/-}Inf if (KnownLHS.isKnownAlways(fcInf | fcNan) && KnownRHS.isKnownNever(fcNan)) return I->getOperand(0); diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fsub.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fsub.ll index 53c2817612662..b4a98bd59c71c 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fsub.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-fsub.ll @@ -34,8 +34,7 @@ declare void @use(half) define nofpclass(inf zero sub norm) half @ret_only_nan(half %x, half %y) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_only_nan( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half 0xH7E00 ; %add = fsub half %x, %y ret half %add @@ -64,7 +63,7 @@ define nofpclass(qnan inf zero sub norm) half @ret_only_snan(half %x, half %y) { define nofpclass(nan inf sub norm) half @ret_only_zero(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan inf sub norm) half @ret_only_zero( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -92,7 +91,7 @@ define nofpclass(nan inf pzero sub norm) half @ret_only_nzero(half %x, half %y) define nofpclass(nan zero sub norm) half @ret_only_inf(half %x, half %y) { ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @ret_only_inf( ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -218,9 +217,7 @@ define nofpclass(nan inf) half @ret_nofpclass_inf_nan__fsub_select_unknown_or_in ; CHECK-SAME: i1 [[COND:%.*]], half [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[INF0:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[INF1:%.*]] = call half @returns_inf() -; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[INF0]] -; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[INF1]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X_OR_INF]], [[Y_OR_INF]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %inf0 = call half @returns_inf() @@ -236,7 +233,7 @@ define nofpclass(inf sub norm) half @nan_result_demands_inf_input_lhs(i1 %cond, ; CHECK-LABEL: define nofpclass(inf sub norm) half @nan_result_demands_inf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(nan inf zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() -; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[PINF]] +; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00 ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; @@ -251,7 +248,7 @@ define nofpclass(inf sub norm) half @nan_result_demands_inf_input_rhs(i1 %cond, ; CHECK-LABEL: define nofpclass(inf sub norm) half @nan_result_demands_inf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() -; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[PINF]] +; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00 ; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; @@ -267,7 +264,7 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_inf_input_lhs(i1 %c ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[INF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X_OR_INF]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() @@ -282,7 +279,7 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_inf_input_rhs(i1 %c ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() ; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[INF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y_OR_INF]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() @@ -296,8 +293,8 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_pinf_input_lhs(i1 % ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_pinf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() -; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[PINF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X_OR_INF]], [[Y]] +; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half 0xH7C00 +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() @@ -311,8 +308,8 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_pinf_input_rhs(i1 % ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_pinf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[PINF:%.*]] = call half @returns_pinf() -; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[PINF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y_OR_INF]] +; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half 0xH7C00 +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %pinf = call half @returns_pinf() @@ -326,8 +323,8 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_ninf_input_lhs(i1 % ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_ninf_input_lhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[NINF:%.*]] = call half @returns_ninf() -; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half [[NINF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X_OR_INF]], [[Y]] +; CHECK-NEXT: [[X_OR_INF:%.*]] = select i1 [[COND]], half [[X]], half 0xHFC00 +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X_OR_INF]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %ninf = call half @returns_ninf() @@ -341,8 +338,8 @@ define nofpclass(nan sub norm zero) half @inf_result_demands_ninf_input_rhs(i1 % ; CHECK-LABEL: define nofpclass(nan zero sub norm) half @inf_result_demands_ninf_input_rhs( ; CHECK-SAME: i1 [[COND:%.*]], half nofpclass(zero) [[X:%.*]], half nofpclass(zero) [[Y:%.*]]) { ; CHECK-NEXT: [[NINF:%.*]] = call half @returns_ninf() -; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half [[NINF]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y_OR_INF]] +; CHECK-NEXT: [[Y_OR_INF:%.*]] = select i1 [[COND]], half [[Y]], half 0xHFC00 +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y_OR_INF]] ; CHECK-NEXT: ret half [[ADD]] ; %ninf = call half @returns_ninf() @@ -367,7 +364,7 @@ define nofpclass(snan) half @no_nans_inputs(half nofpclass(nan) %x, half nofpcla define nofpclass(nan) half @no_nans_input_and_output(half nofpclass(nan) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nan) half @no_nans_input_and_output( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -390,7 +387,7 @@ define nofpclass(snan) half @no_infs_inputs(half nofpclass(inf) %x, half nofpcla define nofpclass(inf) half @no_infs_inputs_and_outputs(half nofpclass(inf) %x, half nofpclass(inf) %y) { ; CHECK-LABEL: define nofpclass(inf) half @no_infs_inputs_and_outputs( ; CHECK-SAME: half nofpclass(inf) [[X:%.*]], half nofpclass(inf) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -401,7 +398,7 @@ define nofpclass(inf) half @no_infs_inputs_and_outputs(half nofpclass(inf) %x, h define nofpclass(snan) half @no_nans_infs_inputs(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(snan) half @no_nans_infs_inputs( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -412,7 +409,7 @@ define nofpclass(snan) half @no_nans_infs_inputs(half nofpclass(nan inf) %x, hal define nofpclass(inf) half @no_nans_infs_inputs__noinfs_output(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(inf) half @no_nans_infs_inputs__noinfs_output( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan ninf half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -423,7 +420,7 @@ define nofpclass(inf) half @no_nans_infs_inputs__noinfs_output(half nofpclass(na define nofpclass(nan) half @no_nans_infs_inputs__nonans_output(half nofpclass(nan inf) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(nan) half @no_nans_infs_inputs__nonans_output( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -434,7 +431,7 @@ define nofpclass(nan) half @no_nans_infs_inputs__nonans_output(half nofpclass(na define nofpclass(nzero) half @inferred_nan_output__noinfs_only_lhs(half nofpclass(nan inf) %x, half nofpclass(nan) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__noinfs_only_lhs( ; CHECK-SAME: half nofpclass(nan inf) [[X:%.*]], half nofpclass(nan) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -445,7 +442,7 @@ define nofpclass(nzero) half @inferred_nan_output__noinfs_only_lhs(half nofpclas define nofpclass(nzero) half @inferred_nan_output__noinfs_only_rhs(half nofpclass(nan) %x, half nofpclass(nan inf) %y) { ; CHECK-LABEL: define nofpclass(nzero) half @inferred_nan_output__noinfs_only_rhs( ; CHECK-SAME: half nofpclass(nan) [[X:%.*]], half nofpclass(nan inf) [[Y:%.*]]) { -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[X]], [[Y]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[X]], [[Y]] ; CHECK-NEXT: ret half [[ADD]] ; %add = fsub half %x, %y @@ -516,7 +513,7 @@ define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_or_nan_sources() ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_or_nan_sources() { ; CHECK-NEXT: [[POSITIVE_OR_NAN0:%.*]] = call half @returns_positive_or_nan() ; CHECK-NEXT: [[POSITIVE_OR_NAN1:%.*]] = call half @returns_positive_or_nan() -; CHECK-NEXT: [[KNOWN_POSITIVE_ADD:%.*]] = fsub half [[POSITIVE_OR_NAN0]], [[POSITIVE_OR_NAN1]] +; CHECK-NEXT: [[KNOWN_POSITIVE_ADD:%.*]] = fsub nnan half [[POSITIVE_OR_NAN0]], [[POSITIVE_OR_NAN1]] ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_POSITIVE_ADD]]) ; CHECK-NEXT: ret half [[FABS]] ; @@ -532,9 +529,7 @@ define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fabs_fsub_known_positive_sources() { ; CHECK-NEXT: [[POSITIVE0:%.*]] = call half @returns_positive() ; CHECK-NEXT: [[POSITIVE1:%.*]] = call half @returns_positive() -; CHECK-NEXT: [[KNOWN_POSITIVE_ADD:%.*]] = fsub half [[POSITIVE1]], [[POSITIVE1]] -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_POSITIVE_ADD]]) -; CHECK-NEXT: ret half [[FABS]] +; CHECK-NEXT: ret half 0xH0000 ; %positive0 = call half @returns_positive() %positive1 = call half @returns_positive() @@ -595,7 +590,7 @@ define nofpclass(nan) half @ret_nonan__unknown__fsub__inf(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__inf( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[INF]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[INF]] ; CHECK-NEXT: ret half [[ADD]] ; %inf = call half @returns_inf() @@ -607,8 +602,7 @@ define nofpclass(nan) half @ret_nonan__inf__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF:%.*]] = call half @returns_inf() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[INF]], [[UNKNOWN]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[INF]] ; %inf = call half @returns_inf() %add = fsub half %inf, %unknown @@ -619,7 +613,7 @@ define nofpclass(nan) half @ret_nonan__unknown__fsub__inf_or_nan(half %unknown) ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__inf_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[INF_OR_NAN]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[INF_OR_NAN]] ; CHECK-NEXT: ret half [[ADD]] ; %inf.or.nan = call half @returns_inf_or_nan() @@ -631,8 +625,7 @@ define nofpclass(nan) half @ret_nonan__inf_or_nan__fsub__unknown(half %unknown) ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__inf_or_nan__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[INF_OR_NAN:%.*]] = call half @returns_inf_or_nan() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[INF_OR_NAN]], [[UNKNOWN]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[INF_OR_NAN]] ; %inf.or.nan = call half @returns_inf_or_nan() %add = fsub half %inf.or.nan, %unknown @@ -667,7 +660,7 @@ define nofpclass(nan) half @ret_nonan__unknown__fsub__zero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__zero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[ZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[UNKNOWN]], [[ZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() @@ -679,7 +672,7 @@ define nofpclass(nan) half @ret_nonan__zero__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__zero__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[ZERO:%.*]] = call half @returns_zero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[ZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half [[ZERO]], [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %zero = call half @returns_zero() @@ -691,8 +684,7 @@ define nofpclass(snan) half @unknown__fsub__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero = call half @returns_pzero() %add = fsub half %unknown, %pzero @@ -703,7 +695,7 @@ define nofpclass(snan) half @pzero__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -715,8 +707,7 @@ define nofpclass(nan) half @ret_nonan__unknown__fsub__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero = call half @returns_pzero() %add = fsub half %unknown, %pzero @@ -727,7 +718,7 @@ define nofpclass(nan) half @ret_nonan__pzero__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__pzero__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fsub nnan half 0xH0000, [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -739,7 +730,7 @@ define nofpclass(snan) half @unknown__fsub__nzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub__nzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[NZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fadd half [[UNKNOWN]], 0xH0000 ; CHECK-NEXT: ret half [[ADD]] ; %nzero = call half @returns_nzero() @@ -751,7 +742,7 @@ define nofpclass(snan) half @nzero__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @nzero__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fneg half [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nzero = call half @returns_nzero() @@ -787,7 +778,7 @@ define nofpclass(nan) half @ret_nonan__unknown__fsub__nzero(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__unknown__fsub__nzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[UNKNOWN]], [[NZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fadd nnan half [[UNKNOWN]], 0xH0000 ; CHECK-NEXT: ret half [[ADD]] ; %nzero = call half @returns_nzero() @@ -799,7 +790,7 @@ define nofpclass(nan) half @ret_nonan__nzero__fsub__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__nzero__fsub__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NZERO:%.*]] = call half @returns_nzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fneg half [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %nzero = call half @returns_nzero() @@ -835,8 +826,7 @@ define nofpclass(snan) half @not_nzero__fsub__pzero(half nofpclass(nzero) %not.n ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__pzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fsub half %not.nzero, %pzero @@ -847,7 +837,7 @@ define nofpclass(snan) half @pzero__fsub__not_nzero(half nofpclass(nzero) %not.n ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[NOT_NZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -907,8 +897,7 @@ define nofpclass(snan) half @unknown__fsub_nsz__pzero(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_nsz__pzero( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[UNKNOWN]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero = call half @returns_pzero() %add = fsub nsz half %unknown, %pzero @@ -919,7 +908,7 @@ define nofpclass(snan) half @pzero__fsub_nsz__unknown(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub_nsz__unknown( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[PZERO]], [[UNKNOWN]] +; CHECK-NEXT: [[ADD:%.*]] = fneg nsz half [[UNKNOWN]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -931,8 +920,7 @@ define nofpclass(snan) half @unknown__fsub_nsz__pzero_or_nan(half %unknown) { ; CHECK-LABEL: define nofpclass(snan) half @unknown__fsub_nsz__pzero_or_nan( ; CHECK-SAME: half [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[PZERO_OR_NAN:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub nsz half [[UNKNOWN]], [[PZERO_OR_NAN]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[UNKNOWN]] ; %pzero.or.nan = call half @returns_pzero() %add = fsub nsz half %unknown, %pzero.or.nan @@ -1031,8 +1019,7 @@ define nofpclass(snan) half @not_nzero__fsub__pzero__daz(half nofpclass(nzero) % ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__pzero__daz( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fsub half %not.nzero, %pzero @@ -1043,7 +1030,7 @@ define nofpclass(snan) half @pzero__fsub__not_nzero__daz(half nofpclass(nzero) % ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero__daz( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[NOT_NZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -1055,8 +1042,7 @@ define nofpclass(snan) half @not_nzero__fsub__pzero__dynamic(half nofpclass(nzer ; CHECK-LABEL: define nofpclass(snan) half @not_nzero__fsub__pzero__dynamic( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[NOT_NZERO]] ; %pzero = call half @returns_pzero() %add = fsub half %not.nzero, %pzero @@ -1067,7 +1053,7 @@ define nofpclass(snan) half @pzero__fsub__not_nzero__dynamic(half nofpclass(nzer ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero__dynamic( ; CHECK-SAME: half nofpclass(nzero) [[NOT_NZERO:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[NOT_NZERO]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[NOT_NZERO]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -1079,8 +1065,7 @@ define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__daz(half nofpclass(nze ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__daz( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO_NSUB]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fsub half %not.nzero.nsub, %pzero @@ -1091,7 +1076,7 @@ define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__daz(half nofpclass(nze ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__daz( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[NOT_NZERO_NSUB]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[NOT_NZERO_NSUB]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -1103,8 +1088,7 @@ define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__dynamic(half nofpclass ; CHECK-LABEL: define nofpclass(snan) half @not_nzero_nsub__fsub__pzero__dynamic( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[NOT_NZERO_NSUB]], [[PZERO]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half [[NOT_NZERO_NSUB]] ; %pzero = call half @returns_pzero() %add = fsub half %not.nzero.nsub, %pzero @@ -1115,7 +1099,7 @@ define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__dynamic(half nofpclass ; CHECK-LABEL: define nofpclass(snan) half @pzero__fsub__not_nzero_nsub__dynamic( ; CHECK-SAME: half nofpclass(nzero nsub) [[NOT_NZERO_NSUB:%.*]]) #[[ATTR1]] { ; CHECK-NEXT: [[PZERO:%.*]] = call half @returns_pzero() -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[PZERO]], [[NOT_NZERO_NSUB]] +; CHECK-NEXT: [[ADD:%.*]] = fsub half 0xH0000, [[NOT_NZERO_NSUB]] ; CHECK-NEXT: ret half [[ADD]] ; %pzero = call half @returns_pzero() @@ -1127,9 +1111,7 @@ define nofpclass(nan) half @ret_nonan__fsub_self__nonan(i1 %cond, half noundef % ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan__fsub_self__nonan( ; CHECK-SAME: i1 [[COND:%.*]], half noundef [[UNKNOWN:%.*]]) { ; CHECK-NEXT: [[NAN:%.*]] = call noundef half @returns_nan() -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], half [[NAN]], half [[UNKNOWN]] -; CHECK-NEXT: [[ADD:%.*]] = fsub half [[SELECT]], [[SELECT]] -; CHECK-NEXT: ret half [[ADD]] +; CHECK-NEXT: ret half 0xH0000 ; %nan = call noundef half @returns_nan() %select = select i1 %cond, half %nan, half %unknown @@ -1141,7 +1123,7 @@ define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_or_nan_sourc ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_or_nan_sources() { ; CHECK-NEXT: [[NEGATIVE_OR_NAN0:%.*]] = call half @returns_negative_or_nan() ; CHECK-NEXT: [[NEGATIVE_OR_NAN1:%.*]] = call half @returns_negative_or_nan() -; CHECK-NEXT: [[KNOWN_NEGATIVE_SUB:%.*]] = fsub half [[NEGATIVE_OR_NAN0]], [[NEGATIVE_OR_NAN1]] +; CHECK-NEXT: [[KNOWN_NEGATIVE_SUB:%.*]] = fsub nnan half [[NEGATIVE_OR_NAN0]], [[NEGATIVE_OR_NAN1]] ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_NEGATIVE_SUB]]) ; CHECK-NEXT: [[NEG_FABS:%.*]] = fneg half [[FABS]] ; CHECK-NEXT: ret half [[NEG_FABS]] @@ -1158,7 +1140,7 @@ define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_sources() { ; CHECK-LABEL: define nofpclass(nan) half @ret_nonan_fneg_fabs_fsub_known_negative_sources() { ; CHECK-NEXT: [[NEGATIVE0:%.*]] = call half @returns_negative() ; CHECK-NEXT: [[NEGATIVE1:%.*]] = call half @returns_negative() -; CHECK-NEXT: [[KNOWN_NEGATIVE_OP:%.*]] = fsub half [[NEGATIVE0]], [[NEGATIVE1]] +; CHECK-NEXT: [[KNOWN_NEGATIVE_OP:%.*]] = fsub nnan half [[NEGATIVE0]], [[NEGATIVE1]] ; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[KNOWN_NEGATIVE_OP]]) ; CHECK-NEXT: [[NEG_FABS:%.*]] = fneg half [[FABS]] ; CHECK-NEXT: ret half [[NEG_FABS]] >From d670efc4765cfd7746c6fa1cec41f3b19c554c17 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Wed, 14 Jan 2026 17:02:20 +0100 Subject: [PATCH 2/2] Implement as fadd+fneg --- llvm/include/llvm/Support/KnownFPClass.h | 6 ++++++ llvm/lib/Support/KnownFPClass.cpp | 17 +---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index 010ca6a3e84ec..358804c932891 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -176,6 +176,12 @@ struct KnownFPClass { SignBit = !*SignBit; } + static KnownFPClass fneg(const KnownFPClass &Src) { + KnownFPClass Known = Src; + Known.fneg(); + return Known; + } + void fabs() { if (KnownFPClasses & fcNegZero) KnownFPClasses |= fcPosZero; diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index dbd5707873f5d..2946c597aa286 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -282,22 +282,7 @@ KnownFPClass KnownFPClass::fadd_self(const KnownFPClass &KnownSrc, KnownFPClass KnownFPClass::fsub(const KnownFPClass &KnownLHS, const KnownFPClass &KnownRHS, DenormalMode Mode) { - KnownFPClass Known; - // Adding positive and negative infinity produces NaN. - // TODO: Check sign of infinities. - if (KnownLHS.isKnownNeverNaN() && KnownRHS.isKnownNeverNaN() && - (KnownLHS.isKnownNeverInfinity() || KnownRHS.isKnownNeverInfinity())) - Known.knownNot(fcNan); - - // Only fsub -0, +0 can return -0 - if ((KnownLHS.isKnownNeverLogicalNegZero(Mode) || - KnownRHS.isKnownNeverLogicalPosZero(Mode)) && - // Make sure output negative denormal can't flush to -0 - (Mode.Output == DenormalMode::IEEE || - Mode.Output == DenormalMode::PositiveZero)) - Known.knownNot(fcNegZero); - - return Known; + return fadd(KnownLHS, fneg(KnownRHS), Mode); } KnownFPClass KnownFPClass::fmul(const KnownFPClass &KnownLHS, _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
