https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/174842
>From d96b09c6e485cbc3d078e4efd7d1eb49d6154c77 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Mon, 29 Dec 2025 19:46:09 +0100 Subject: [PATCH 1/8] InstCombine: Handle rounding intrinsics in SimplifyDemandedFPClass --- llvm/include/llvm/Support/KnownFPClass.h | 7 + llvm/lib/Analysis/ValueTracking.cpp | 22 +-- llvm/lib/Support/KnownFPClass.cpp | 28 ++++ .../InstCombineSimplifyDemanded.cpp | 66 ++++++++ ...fy-demanded-fpclass-rounding-intrinsics.ll | 144 +++++++----------- 5 files changed, 158 insertions(+), 109 deletions(-) diff --git a/llvm/include/llvm/Support/KnownFPClass.h b/llvm/include/llvm/Support/KnownFPClass.h index 5a3ed677bd762..193a3511b9f8e 100644 --- a/llvm/include/llvm/Support/KnownFPClass.h +++ b/llvm/include/llvm/Support/KnownFPClass.h @@ -299,6 +299,13 @@ struct KnownFPClass { const fltSemantics &DstTy, const fltSemantics &SrcTy); + /// Propagate known class for rounding intrinsics (trunc, floor, ceil, rint, + /// nearbyint, round, roundeven). This is trunc if \p IsTrunc. \p + /// IsMultiUnitFPType if this is for a multi-unit floating-point type. + static LLVM_ABI KnownFPClass roundToIntegral(const KnownFPClass &Src, + bool IsTrunc, + bool IsMultiUnitFPType); + void resetAll() { *this = KnownFPClass(); } }; diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 90e23bf81d99e..1e16647e6ccc1 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5220,26 +5220,8 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, KnownSrc, Q, Depth + 1); - // Integer results cannot be subnormal. - Known.knownNot(fcSubnormal); - - Known.propagateNaN(KnownSrc, true); - - // Pass through infinities, except PPC_FP128 is a special case for - // intrinsics other than trunc. - if (IID == Intrinsic::trunc || !V->getType()->isMultiUnitFPType()) { - if (KnownSrc.isKnownNeverPosInfinity()) - Known.knownNot(fcPosInf); - if (KnownSrc.isKnownNeverNegInfinity()) - Known.knownNot(fcNegInf); - } - - // Negative round ups to 0 produce -0 - if (KnownSrc.isKnownNever(fcPosFinite)) - Known.knownNot(fcPosFinite); - if (KnownSrc.isKnownNever(fcNegFinite)) - Known.knownNot(fcNegFinite); - + Known = KnownFPClass::roundToIntegral(KnownSrc, IID == Intrinsic::trunc, + V->getType()->isMultiUnitFPType()); break; } case Intrinsic::exp: diff --git a/llvm/lib/Support/KnownFPClass.cpp b/llvm/lib/Support/KnownFPClass.cpp index e621da9e39ed7..8f7f4e93d1c15 100644 --- a/llvm/lib/Support/KnownFPClass.cpp +++ b/llvm/lib/Support/KnownFPClass.cpp @@ -375,3 +375,31 @@ KnownFPClass KnownFPClass::fpext(const KnownFPClass &KnownSrc, return Known; } + +KnownFPClass KnownFPClass::roundToIntegral(const KnownFPClass &KnownSrc, + bool IsTrunc, + bool IsMultiUnitFPType) { + KnownFPClass Known; + + // Integer results cannot be subnormal. + Known.knownNot(fcSubnormal); + + Known.propagateNaN(KnownSrc, true); + + // Pass through infinities, except PPC_FP128 is a special case for + // intrinsics other than trunc. + if (IsTrunc || !IsMultiUnitFPType) { + if (KnownSrc.isKnownNeverPosInfinity()) + Known.knownNot(fcPosInf); + if (KnownSrc.isKnownNeverNegInfinity()) + Known.knownNot(fcNegInf); + } + + // Negative round ups to 0 produce -0 + if (KnownSrc.isKnownNever(fcPosFinite)) + Known.knownNot(fcPosFinite); + if (KnownSrc.isKnownNever(fcNegFinite)) + Known.knownNot(fcNegFinite); + + return Known; +} diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 22064638bb229..f88997fb6619f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2638,6 +2638,72 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, return getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true); } + case Intrinsic::trunc: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::rint: + case Intrinsic::nearbyint: + case Intrinsic::round: + case Intrinsic::roundeven: { + FPClassTest DemandedSrcMask = DemandedMask; + + // Zero results imply valid subnormal sources. + if (DemandedMask & fcNegZero) + DemandedSrcMask |= fcNegSubnormal; + + if (DemandedMask & fcPosZero) + DemandedSrcMask |= fcPosSubnormal; + + KnownFPClass KnownSrc; + if (SimplifyDemandedFPClass(CI, 0, DemandedSrcMask, KnownSrc, Depth + 1)) + return I; + + // Note: Possibly dropping snan quiet. + if (KnownSrc.isKnownAlways(fcInf | fcNan)) + return CI->getArgOperand(0); + + // Propagate nnan-ness to source to simplify source checks. + if ((DemandedMask & fcNan) == fcNone) + KnownSrc.knownNot(fcNan); + + bool IsRoundNearest = + IID == Intrinsic::round || IID == Intrinsic::roundeven || + IID == Intrinsic::nearbyint || IID == Intrinsic::rint; + + // Ignore denormals-as-zero, as canonicalization is not mandated. + if ((IID == Intrinsic::trunc || IID == Intrinsic::floor || + IsRoundNearest) && + (KnownSrc.isKnownAlways(fcPosZero | fcPosSubnormal))) + return ConstantFP::getZero(VTy); + + if ((IID == Intrinsic::trunc || IsRoundNearest) && + KnownSrc.isKnownAlways(fcNegZero | fcNegSubnormal)) + return ConstantFP::getZero(VTy, true); + + if (IID == Intrinsic::floor && KnownSrc.isKnownAlways(fcNegSubnormal)) + return ConstantFP::get(VTy, -1.0); + + if (IID == Intrinsic::ceil && KnownSrc.isKnownAlways(fcPosSubnormal)) + return ConstantFP::get(VTy, 1.0); + + Known = KnownFPClass::roundToIntegral(KnownSrc, IID == Intrinsic::trunc, + VTy->isMultiUnitFPType()); + + FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; + if (Constant *SingleVal = + getFPClassConstant(VTy, ValidResults, /*IsCanonicalizing=*/true)) + return SingleVal; + + if ((IID == Intrinsic::trunc || IsRoundNearest) && + KnownSrc.isKnownAlways(fcZero | fcSubnormal)) { + Value *Copysign = Builder.CreateCopySign(ConstantFP::getZero(VTy), + CI->getArgOperand(0)); + Copysign->takeName(CI); + return Copysign; + } + + return nullptr; + } case Intrinsic::canonicalize: { Type *EltTy = VTy->getScalarType(); diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll index 59e1a2215d838..1903bbe851ae2 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll @@ -14,8 +14,7 @@ define nofpclass(snan) float @ret_no_snan__floor_no_snan(float nofpclass(nan) %x define nofpclass(inf norm sub zero) float @ret_only_nan__floor(float %x) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) float @ret_only_nan__floor( ; CHECK-SAME: float [[X:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[X]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0x7FF8000000000000 ; %result = call float @llvm.floor.f32(float %x) ret float %result @@ -24,8 +23,7 @@ define nofpclass(inf norm sub zero) float @ret_only_nan__floor(float %x) { define nofpclass(inf norm sub zero) <2 x float> @ret_only_nan__floor_vec(<2 x float> %x) { ; CHECK-LABEL: define nofpclass(inf zero sub norm) <2 x float> @ret_only_nan__floor_vec( ; CHECK-SAME: <2 x float> [[X:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call <2 x float> @llvm.floor.v2f32(<2 x float> [[X]]) -; CHECK-NEXT: ret <2 x float> [[RESULT]] +; CHECK-NEXT: ret <2 x float> splat (float 0x7FF8000000000000) ; %result = call <2 x float> @llvm.floor.v2f32(<2 x float> %x) ret <2 x float> %result @@ -140,8 +138,7 @@ define nofpclass(nan inf) float @ret_no_nans_no_infs__floor(float %x) { define nofpclass(nan) float @ret_no_nans__simplify_select_nan__floor(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__floor( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -152,8 +149,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__floor(i1 %cond, f define nofpclass(inf) float @ret_no_infs__simplify_select_inf__floor(i1 %cond, float nofpclass(nan norm sub zero) %is.inf, float %unknown) { ; CHECK-LABEL: define nofpclass(inf) float @ret_no_infs__simplify_select_inf__floor( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(nan zero sub norm) [[IS_INF:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_INF]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.inf, float %unknown @@ -164,8 +160,7 @@ define nofpclass(inf) float @ret_no_infs__simplify_select_inf__floor(i1 %cond, f define nofpclass(nan inf) float @ret_no_inf_no_nan__simplify_select_inf_or_nan__floor(i1 %cond, float nofpclass(norm sub zero) %is.inf.or.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan inf) float @ret_no_inf_no_nan__simplify_select_inf_or_nan__floor( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(zero sub norm) [[IS_INF_OR_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_INF_OR_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.inf.or.nan, float %unknown @@ -228,8 +223,7 @@ define nofpclass(snan) <2 x float> @source_known_sub_or_zero_or_nan__floor_vec(< define nofpclass(snan) float @source_known_psub_or_pzero__floor(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__floor( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.floor.f32(float %psub.or.pzero) ret float %result @@ -268,8 +262,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero_or_nan__floor(float nof define nofpclass(snan) float @source_known_inf__floor(float nofpclass(nan norm sub zero) %inf) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf__floor( ; CHECK-SAME: float nofpclass(nan zero sub norm) [[INF:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF]] ; %result = call float @llvm.floor.f32(float %inf) ret float %result @@ -278,8 +271,7 @@ define nofpclass(snan) float @source_known_inf__floor(float nofpclass(nan norm s define nofpclass(snan) float @source_known_inf_or_nan__floor(float nofpclass(norm sub zero) %inf.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan__floor( ; CHECK-SAME: float nofpclass(zero sub norm) [[INF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF_OR_NAN]] ; %result = call float @llvm.floor.f32(float %inf.or.nan) ret float %result @@ -288,8 +280,7 @@ define nofpclass(snan) float @source_known_inf_or_nan__floor(float nofpclass(nor define nofpclass(snan) float @source_known_inf_or_nan_or_zero__floor(float nofpclass(norm sub) %inf.or.nan.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero__floor( ; CHECK-SAME: float nofpclass(sub norm) [[INF_OR_NAN_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_NAN_OR_ZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF_OR_NAN_OR_ZERO]] ; %result = call float @llvm.floor.f32(float %inf.or.nan.or.zero) ret float %result @@ -308,8 +299,7 @@ define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__floor(floa define nofpclass(snan) float @source_known_inf_or_zero__floor(float nofpclass(nan norm sub) %inf.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_zero__floor( ; CHECK-SAME: float nofpclass(nan sub norm) [[INF_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[INF_OR_ZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF_OR_ZERO]] ; %result = call float @llvm.floor.f32(float %inf.or.zero) ret float %result @@ -328,8 +318,7 @@ define nofpclass(snan) float @source_known_sub__floor(float nofpclass(inf nan no define nofpclass(snan) float @source_known_psub__floor(float nofpclass(inf nan norm nsub zero) %psub) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub__floor( ; CHECK-SAME: float nofpclass(nan inf zero nsub norm) [[PSUB:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PSUB]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.floor.f32(float %psub) ret float %result @@ -338,8 +327,7 @@ define nofpclass(snan) float @source_known_psub__floor(float nofpclass(inf nan n define nofpclass(snan) float @source_known_nsub__floor(float nofpclass(inf nan norm psub zero) %nsub) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub__floor( ; CHECK-SAME: float nofpclass(nan inf zero psub norm) [[NSUB:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NSUB]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -1.000000e+00 ; %result = call float @llvm.floor.f32(float %nsub) ret float %result @@ -357,8 +345,7 @@ define nofpclass(snan) float @source_known_pinf__floor(float nofpclass(nan ninf define nofpclass(snan) float @source_known_pinf_or_nan__floor(float nofpclass(ninf norm sub zero) %pinf.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_pinf_or_nan__floor( ; CHECK-SAME: float nofpclass(ninf zero sub norm) [[PINF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[PINF_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[PINF_OR_NAN]] ; %result = call float @llvm.floor.f32(float %pinf.or.nan) ret float %result @@ -376,8 +363,7 @@ define nofpclass(snan) float @source_known_ninf__floor(float nofpclass(nan pinf define nofpclass(snan) float @source_known_ninf_or_nan__floor(float nofpclass(pinf norm sub zero) %ninf.or.nan) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_ninf_or_nan__floor( ; CHECK-SAME: float nofpclass(pinf zero sub norm) [[NINF_OR_NAN:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.floor.f32(float [[NINF_OR_NAN]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[NINF_OR_NAN]] ; %result = call float @llvm.floor.f32(float %ninf.or.nan) ret float %result @@ -436,8 +422,7 @@ define nofpclass(snan) ppc_fp128 @source_known_not_ninf__floor_ppcf128(ppc_fp128 define nofpclass(nan) float @ret_no_nans__simplify_select_nan__trunc(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__trunc( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -448,8 +433,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__trunc(i1 %cond, f define nofpclass(nan) float @ret_no_nans__simplify_select_nan__ceil(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__ceil( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -460,8 +444,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__ceil(i1 %cond, fl define nofpclass(nan) float @ret_no_nans__simplify_select_nan__rint(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__rint( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -472,8 +455,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__rint(i1 %cond, fl define nofpclass(nan) float @ret_no_nans__simplify_select_nan__nearbyint(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__nearbyint( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -484,8 +466,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__nearbyint(i1 %con define nofpclass(nan) float @ret_no_nans__simplify_select_nan__round(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__round( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -496,8 +477,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__round(i1 %cond, f define nofpclass(nan) float @ret_no_nans__simplify_select_nan__roundeven(i1 %cond, float nofpclass(inf norm sub zero) %is.nan, float %unknown) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans__simplify_select_nan__roundeven( ; CHECK-SAME: i1 [[COND:%.*]], float nofpclass(inf zero sub norm) [[IS_NAN:%.*]], float [[UNKNOWN:%.*]]) { -; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[IS_NAN]], float [[UNKNOWN]] -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SELECT]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[UNKNOWN]]) ; CHECK-NEXT: ret float [[RESULT]] ; %select = select i1 %cond, float %is.nan, float %unknown @@ -508,7 +488,7 @@ define nofpclass(nan) float @ret_no_nans__simplify_select_nan__roundeven(i1 %con define nofpclass(snan) float @source_known_sub_or_zero__trunc(float nofpclass(nan inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__trunc( ; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.trunc.f32(float %sub.or.zero) @@ -518,8 +498,7 @@ define nofpclass(snan) float @source_known_sub_or_zero__trunc(float nofpclass(na define nofpclass(snan) float @source_known_psub_or_pzero__trunc(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__trunc( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.trunc.f32(float %psub.or.pzero) ret float %result @@ -528,8 +507,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__trunc(float nofpclass( define nofpclass(snan) float @source_known_nsub_or_nzero__trunc(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__trunc( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.trunc.f32(float %nsub.or.nzero) ret float %result @@ -538,8 +516,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero__trunc(float nofpclass( define nofpclass(snan) float @source_known_inf_or_nan_or_zero__trunc(float nofpclass(norm sub) %inf.or.nan.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_nan_or_zero__trunc( ; CHECK-SAME: float nofpclass(sub norm) [[INF_OR_NAN_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[INF_OR_NAN_OR_ZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF_OR_NAN_OR_ZERO]] ; %result = call float @llvm.trunc.f32(float %inf.or.nan.or.zero) ret float %result @@ -558,8 +535,7 @@ define nofpclass(snan) float @source_known_inf_or_nan_or_zero_or_sub__trunc(floa define nofpclass(snan) float @source_known_inf_or_zero__trunc(float nofpclass(nan norm sub) %inf.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_inf_or_zero__trunc( ; CHECK-SAME: float nofpclass(nan sub norm) [[INF_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[INF_OR_ZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float [[INF_OR_ZERO]] ; %result = call float @llvm.trunc.f32(float %inf.or.zero) ret float %result @@ -568,7 +544,7 @@ define nofpclass(snan) float @source_known_inf_or_zero__trunc(float nofpclass(na define nofpclass(snan) float @source_known_sub__trunc(float nofpclass(inf nan norm zero) %sub) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub__trunc( ; CHECK-SAME: float nofpclass(nan inf zero norm) [[SUB:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.trunc.f32(float %sub) @@ -578,8 +554,7 @@ define nofpclass(snan) float @source_known_sub__trunc(float nofpclass(inf nan no define nofpclass(snan) float @source_known_psub__trunc(float nofpclass(inf nan norm nsub zero) %psub) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub__trunc( ; CHECK-SAME: float nofpclass(nan inf zero nsub norm) [[PSUB:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.trunc.f32(float %psub) ret float %result @@ -588,8 +563,7 @@ define nofpclass(snan) float @source_known_psub__trunc(float nofpclass(inf nan n define nofpclass(snan) float @source_known_nsub__trunc(float nofpclass(inf nan norm psub zero) %nsub) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub__trunc( ; CHECK-SAME: float nofpclass(nan inf zero psub norm) [[NSUB:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.trunc.f32(float %nsub) ret float %result @@ -628,7 +602,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero__ceil(float nofpclass(n define nofpclass(snan) float @source_known_sub_or_zero__rint(float nofpclass(nan inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__rint( ; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.rint.f32(float %sub.or.zero) @@ -638,8 +612,7 @@ define nofpclass(snan) float @source_known_sub_or_zero__rint(float nofpclass(nan define nofpclass(snan) float @source_known_psub_or_pzero__rint(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__rint( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.rint.f32(float %psub.or.pzero) ret float %result @@ -648,8 +621,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__rint(float nofpclass(n define nofpclass(snan) float @source_known_nsub_or_nzero__rint(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__rint( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.rint.f32(float %nsub.or.nzero) ret float %result @@ -658,7 +630,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero__rint(float nofpclass(n define nofpclass(snan) float @source_known_sub_or_zero__nearbyint(float nofpclass(nan inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__nearbyint( ; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.nearbyint.f32(float %sub.or.zero) @@ -668,8 +640,7 @@ define nofpclass(snan) float @source_known_sub_or_zero__nearbyint(float nofpclas define nofpclass(snan) float @source_known_psub_or_pzero__nearbyint(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__nearbyint( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.nearbyint.f32(float %psub.or.pzero) ret float %result @@ -678,8 +649,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__nearbyint(float nofpcl define nofpclass(snan) float @source_known_nsub_or_nzero__nearbyint(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__nearbyint( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.nearbyint.f32(float %nsub.or.nzero) ret float %result @@ -688,7 +658,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero__nearbyint(float nofpcl define nofpclass(snan) float @source_known_sub_or_zero__round(float nofpclass(nan inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__round( ; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.round.f32(float %sub.or.zero) @@ -698,8 +668,7 @@ define nofpclass(snan) float @source_known_sub_or_zero__round(float nofpclass(na define nofpclass(snan) float @source_known_psub_or_pzero__round(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__round( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.round.f32(float %psub.or.pzero) ret float %result @@ -708,8 +677,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__round(float nofpclass( define nofpclass(snan) float @source_known_nsub_or_nzero__round(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__round( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.round.f32(float %nsub.or.nzero) ret float %result @@ -718,7 +686,7 @@ define nofpclass(snan) float @source_known_nsub_or_nzero__round(float nofpclass( define nofpclass(snan) float @source_known_sub_or_zero__roundeven(float nofpclass(nan inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_sub_or_zero__roundeven( ; CHECK-SAME: float nofpclass(nan inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.roundeven.f32(float %sub.or.zero) @@ -728,8 +696,7 @@ define nofpclass(snan) float @source_known_sub_or_zero__roundeven(float nofpclas define nofpclass(snan) float @source_known_psub_or_pzero__roundeven(float nofpclass(nan inf norm nsub nzero) %psub.or.pzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_psub_or_pzero__roundeven( ; CHECK-SAME: float nofpclass(nan inf nzero nsub norm) [[PSUB_OR_PZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[PSUB_OR_PZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float 0.000000e+00 ; %result = call float @llvm.roundeven.f32(float %psub.or.pzero) ret float %result @@ -738,8 +705,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__roundeven(float nofpcl define nofpclass(snan) float @source_known_nsub_or_nzero__roundeven(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__roundeven( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.roundeven.f32(float %nsub.or.nzero) ret float %result @@ -778,7 +744,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__floor define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__trunc(float nofpclass(inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__trunc( ; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.trunc.f32(float %sub.or.zero) @@ -788,7 +754,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__trunc( define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__trunc(float nofpclass(inf norm nsub) %psub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__trunc( ; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[PSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[PSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.trunc.f32(float %psub.or.zero) @@ -798,7 +764,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__trunc define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__trunc(float nofpclass(inf norm psub) %nsub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__trunc( ; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.trunc.f32(float [[NSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.trunc.f32(float %nsub.or.zero) @@ -838,7 +804,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__ceil( define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rint(float nofpclass(inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rint( ; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.rint.f32(float %sub.or.zero) @@ -848,7 +814,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rint(f define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__rint(float nofpclass(inf norm nsub) %psub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__rint( ; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[PSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[PSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.rint.f32(float %psub.or.zero) @@ -858,7 +824,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__rint( define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__rint(float nofpclass(inf norm psub) %nsub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__rint( ; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.rint.f32(float [[NSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.rint.f32(float %nsub.or.zero) @@ -868,7 +834,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__rint( define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__nearbyint(float nofpclass(inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__nearbyint( ; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.nearbyint.f32(float %sub.or.zero) @@ -878,7 +844,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__nearby define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__nearbyint(float nofpclass(inf norm nsub) %psub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__nearbyint( ; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[PSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[PSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.nearbyint.f32(float %psub.or.zero) @@ -888,7 +854,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__nearb define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__nearbyint(float nofpclass(inf norm psub) %nsub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__nearbyint( ; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.nearbyint.f32(float [[NSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.nearbyint.f32(float %nsub.or.zero) @@ -898,7 +864,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__nearb define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__round(float nofpclass(inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__round( ; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.round.f32(float %sub.or.zero) @@ -908,7 +874,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__round( define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round(float nofpclass(inf norm nsub) %psub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round( ; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[PSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[PSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.round.f32(float %psub.or.zero) @@ -918,7 +884,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__round(float nofpclass(inf norm psub) %nsub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__round( ; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.round.f32(float [[NSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.round.f32(float %nsub.or.zero) @@ -928,7 +894,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__round define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__roundeven(float nofpclass(inf norm) %sub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__roundeven( ; CHECK-SAME: float nofpclass(inf norm) [[SUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[SUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[SUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.roundeven.f32(float %sub.or.zero) @@ -938,7 +904,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_sub_or_zero_or_nan__rounde define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__roundeven(float nofpclass(inf norm nsub) %psub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__roundeven( ; CHECK-SAME: float nofpclass(inf nsub norm) [[PSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[PSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[PSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.roundeven.f32(float %psub.or.zero) @@ -948,7 +914,7 @@ define nofpclass(nan) float @ret_no_nans_source_known_psub_or_zero_or_nan__round define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__roundeven(float nofpclass(inf norm psub) %nsub.or.zero) { ; CHECK-LABEL: define nofpclass(nan) float @ret_no_nans_source_known_nsub_or_zero_or_nan__roundeven( ; CHECK-SAME: float nofpclass(inf psub norm) [[NSUB_OR_ZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.roundeven.f32(float [[NSUB_OR_ZERO]]) +; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[NSUB_OR_ZERO]]) ; CHECK-NEXT: ret float [[RESULT]] ; %result = call float @llvm.roundeven.f32(float %nsub.or.zero) >From 6a568ce2f446b72c591b20e418ade31eeb432a3a Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Thu, 8 Jan 2026 18:45:32 +0100 Subject: [PATCH 2/8] VTy->getScalarType()->isMultiUnitFPType() --- llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index f88997fb6619f..a7c6b1796bd73 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2687,7 +2687,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, return ConstantFP::get(VTy, 1.0); Known = KnownFPClass::roundToIntegral(KnownSrc, IID == Intrinsic::trunc, - VTy->isMultiUnitFPType()); + VTy->getScalarType()->isMultiUnitFPType()); FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; if (Constant *SingleVal = >From 633a6bb3a680c3f495bd3142bf3ec0c411c6a929 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Thu, 8 Jan 2026 18:46:44 +0100 Subject: [PATCH 3/8] also zero --- llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index a7c6b1796bd73..608d91868c2ed 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2659,7 +2659,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, return I; // Note: Possibly dropping snan quiet. - if (KnownSrc.isKnownAlways(fcInf | fcNan)) + if (KnownSrc.isKnownAlways(fcInf | fcNan | fcZero)) return CI->getArgOperand(0); // Propagate nnan-ness to source to simplify source checks. >From 69b5dd123f53a1bf4b0d37388697f2e561251a2e Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Thu, 8 Jan 2026 19:29:06 +0100 Subject: [PATCH 4/8] format --- .../Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 608d91868c2ed..4db0d4f8321ef 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2686,8 +2686,9 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, if (IID == Intrinsic::ceil && KnownSrc.isKnownAlways(fcPosSubnormal)) return ConstantFP::get(VTy, 1.0); - Known = KnownFPClass::roundToIntegral(KnownSrc, IID == Intrinsic::trunc, - VTy->getScalarType()->isMultiUnitFPType()); + Known = KnownFPClass::roundToIntegral( + KnownSrc, IID == Intrinsic::trunc, + VTy->getScalarType()->isMultiUnitFPType()); FPClassTest ValidResults = DemandedMask & Known.KnownFPClasses; if (Constant *SingleVal = >From 0c338529a7ad8fc6fa0049daf5969a4e54785d59 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 11 Jan 2026 09:34:29 +0100 Subject: [PATCH 5/8] Remove parentheses --- llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 4db0d4f8321ef..48bd2279e3211 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2673,7 +2673,7 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, // Ignore denormals-as-zero, as canonicalization is not mandated. if ((IID == Intrinsic::trunc || IID == Intrinsic::floor || IsRoundNearest) && - (KnownSrc.isKnownAlways(fcPosZero | fcPosSubnormal))) + KnownSrc.isKnownAlways(fcPosZero | fcPosSubnormal)) return ConstantFP::getZero(VTy); if ((IID == Intrinsic::trunc || IsRoundNearest) && >From da9e43306f9a5997737bd258d13a1c1e0991eb83 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 11 Jan 2026 09:37:12 +0100 Subject: [PATCH 6/8] getScalarType()->isMultiUnitFPType() --- llvm/lib/Analysis/ValueTracking.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 1e16647e6ccc1..859cfe75daa37 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5220,8 +5220,9 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, computeKnownFPClass(II->getArgOperand(0), DemandedElts, InterestedSrcs, KnownSrc, Q, Depth + 1); - Known = KnownFPClass::roundToIntegral(KnownSrc, IID == Intrinsic::trunc, - V->getType()->isMultiUnitFPType()); + Known = KnownFPClass::roundToIntegral( + KnownSrc, IID == Intrinsic::trunc, + V->getType()->getScalarType()->isMultiUnitFPType()); break; } case Intrinsic::exp: >From 9eac606963ed3ff5f596570fd76cb0440db909d5 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 11 Jan 2026 09:40:55 +0100 Subject: [PATCH 7/8] ceil to -0 --- .../lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 3 ++- .../simplify-demanded-fpclass-rounding-intrinsics.ll | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 48bd2279e3211..985ca67051d78 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2676,7 +2676,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, KnownSrc.isKnownAlways(fcPosZero | fcPosSubnormal)) return ConstantFP::getZero(VTy); - if ((IID == Intrinsic::trunc || IsRoundNearest) && + if ((IID == Intrinsic::trunc || IID == Intrinsic::ceil || + IsRoundNearest) && KnownSrc.isKnownAlways(fcNegZero | fcNegSubnormal)) return ConstantFP::getZero(VTy, true); diff --git a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll index 1903bbe851ae2..37018feb43adb 100644 --- a/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll +++ b/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass-rounding-intrinsics.ll @@ -592,8 +592,7 @@ define nofpclass(snan) float @source_known_psub_or_pzero__ceil(float nofpclass(n define nofpclass(snan) float @source_known_nsub_or_nzero__ceil(float nofpclass(nan inf norm psub pzero) %nsub.or.nzero) { ; CHECK-LABEL: define nofpclass(snan) float @source_known_nsub_or_nzero__ceil( ; CHECK-SAME: float nofpclass(nan inf pzero psub norm) [[NSUB_OR_NZERO:%.*]]) { -; CHECK-NEXT: [[RESULT:%.*]] = call float @llvm.ceil.f32(float [[NSUB_OR_NZERO]]) -; CHECK-NEXT: ret float [[RESULT]] +; CHECK-NEXT: ret float -0.000000e+00 ; %result = call float @llvm.ceil.f32(float %nsub.or.nzero) ret float %result >From bf5cc664fe1e9add67c1376ac079071bd5f9da3e Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 11 Jan 2026 09:46:37 +0100 Subject: [PATCH 8/8] Zero implies normal --- .../Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 985ca67051d78..2ff71b6f25086 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -2649,10 +2649,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseFPClass(Instruction *I, // Zero results imply valid subnormal sources. if (DemandedMask & fcNegZero) - DemandedSrcMask |= fcNegSubnormal; + DemandedSrcMask |= fcNegSubnormal | fcNegNormal; if (DemandedMask & fcPosZero) - DemandedSrcMask |= fcPosSubnormal; + DemandedSrcMask |= fcPosSubnormal | fcPosNormal; KnownFPClass KnownSrc; if (SimplifyDemandedFPClass(CI, 0, DemandedSrcMask, KnownSrc, Depth + 1)) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
