diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h index 0f98af69f12c6..022f0dbb04421 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h @@ -410,6 +410,10 @@ class TargetLibraryInfo { case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl: case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl: case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl: + case LibFunc_fmaximum_num: case LibFunc_fmaximum_numf: + case LibFunc_fmaximum_numl: + case LibFunc_fminimum_num: case LibFunc_fminimum_numf: + case LibFunc_fminimum_numl: case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl: case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l: case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp: @@ -417,6 +421,7 @@ class TargetLibraryInfo { case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl: case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl: case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl: + case LibFunc_roundeven: case LibFunc_roundevenf: case LibFunc_roundevenl: case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl: case LibFunc_sinh: case LibFunc_sinhf: case LibFunc_sinhl: case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl: diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 4e7c97194cc59..64d2512308935 100644 --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -205,6 +205,7 @@ class LibCallSimplifier { Value *replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B); Value *optimizeExp2(CallInst *CI, IRBuilderBase &B); Value *optimizeFMinFMax(CallInst *CI, IRBuilderBase &B); + Value *optimizeFMinimumnumFMaximumnum(CallInst *CI, IRBuilderBase &B); Value *optimizeLog(CallInst *CI, IRBuilderBase &B); Value *optimizeSqrt(CallInst *CI, IRBuilderBase &B); Value *optimizeFMod(CallInst *CI, IRBuilderBase &B); diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 63d12ee585e64..b39b32042dd2f 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1984,6 +1984,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { switch (Name[0]) { default: return false; + // clang-format off case 'a': return Name == "acos" || Name == "acosf" || Name == "asin" || Name == "asinf" || @@ -2014,7 +2015,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { case 'r': return Name == "remainder" || Name == "remainderf" || Name == "rint" || Name == "rintf" || - Name == "round" || Name == "roundf"; + Name == "round" || Name == "roundf" || + Name == "roundeven" || Name == "roundevenf"; case 's': return Name == "sin" || Name == "sinf" || Name == "sinh" || Name == "sinhf" || @@ -2052,6 +2054,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { case 's': return Name == "__sinh_finite" || Name == "__sinhf_finite"; } + // clang-format on } } @@ -2516,7 +2519,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, // Use internal versions of these intrinsics. - if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) { + if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint || + IntrinsicID == Intrinsic::roundeven) { U.roundToIntegral(APFloat::rmNearestTiesToEven); return ConstantFP::get(Ty->getContext(), U); } @@ -2988,6 +2992,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, case LibFunc_nearbyintf: case LibFunc_rint: case LibFunc_rintf: + case LibFunc_roundeven: + case LibFunc_roundevenf: if (TLI->has(Func)) { U.roundToIntegral(APFloat::rmNearestTiesToEven); return ConstantFP::get(Ty->getContext(), U); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 9cb6f19b9340c..6de4f57f75273 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4680,6 +4680,14 @@ Intrinsic::ID llvm::getIntrinsicForCallSite(const CallBase &CB, case LibFunc_fmaxf: case LibFunc_fmaxl: return Intrinsic::maxnum; + case LibFunc_fminimum_num: + case LibFunc_fminimum_numf: + case LibFunc_fminimum_numl: + return Intrinsic::minimumnum; + case LibFunc_fmaximum_num: + case LibFunc_fmaximum_numf: + case LibFunc_fmaximum_numl: + return Intrinsic::maximumnum; case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl: diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 09a0673bfe1bb..6f22730c90efe 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9710,6 +9710,12 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) { if (visitUnaryFloatCall(I, ISD::FROUND)) return; break; + case LibFunc_roundeven: + case LibFunc_roundevenf: + case LibFunc_roundevenl: + if (visitUnaryFloatCall(I, ISD::FROUNDEVEN)) + return; + break; case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl: diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp index 66d570b3f831e..8b1d765d77818 100644 --- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp @@ -1499,6 +1499,12 @@ const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = { {LibFunc_fminf, "llvm.minnum.f32"}, {LibFunc_fmin, "llvm.minnum.f64"}, {LibFunc_fminl, "llvm.minnum.f80"}, + {LibFunc_fmaximum_numf, "llvm.maximumnum.f32"}, + {LibFunc_fmaximum_num, "llvm.maximumnum.f64"}, + {LibFunc_fmaximum_numl, "llvm.maximumnum.f80"}, + {LibFunc_fminimum_numf, "llvm.minimumnum.f32"}, + {LibFunc_fminimum_num, "llvm.minimumnum.f64"}, + {LibFunc_fminimum_numl, "llvm.minimumnum.f80"}, {LibFunc_ceilf, "llvm.ceil.f32"}, {LibFunc_ceil, "llvm.ceil.f64"}, {LibFunc_ceill, "llvm.ceil.f80"}, @@ -1514,6 +1520,9 @@ const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = { {LibFunc_roundf, "llvm.round.f32"}, {LibFunc_round, "llvm.round.f64"}, {LibFunc_roundl, "llvm.round.f80"}, + {LibFunc_roundevenf, "llvm.roundeven.f32"}, + {LibFunc_roundeven, "llvm.roundeven.f64"}, + {LibFunc_roundevenl, "llvm.roundeven.f80"}, }; const char *KnownIntrinsic::get(LibFunc LFunc) { diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp index 02b73e85d783f..a245b9405cfb7 100644 --- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1227,9 +1227,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F, case LibFunc_atanhf: case LibFunc_atanhl: case LibFunc_atanl: - case LibFunc_ceil: - case LibFunc_ceilf: - case LibFunc_ceill: case LibFunc_cos: case LibFunc_cosh: case LibFunc_coshf: @@ -1298,9 +1295,6 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F, case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl: - case LibFunc_round: - case LibFunc_roundf: - case LibFunc_roundl: case LibFunc_scalbln: case LibFunc_scalblnf: case LibFunc_scalblnl: @@ -1338,6 +1332,9 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F, case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl: + case LibFunc_ceil: + case LibFunc_ceilf: + case LibFunc_ceill: case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl: @@ -1356,11 +1353,23 @@ bool llvm::inferNonMandatoryLibFuncAttrs(Function &F, case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl: + case LibFunc_fmaximum_num: + case LibFunc_fmaximum_numf: + case LibFunc_fmaximum_numl: + case LibFunc_fminimum_num: + case LibFunc_fminimum_numf: + case LibFunc_fminimum_numl: case LibFunc_labs: case LibFunc_llabs: case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl: + case LibFunc_round: + case LibFunc_roundf: + case LibFunc_roundl: + case LibFunc_roundeven: + case LibFunc_roundevenf: + case LibFunc_roundevenl: case LibFunc_toascii: case LibFunc_trunc: case LibFunc_truncf: diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index d1548694baa27..20d9b03bd87c8 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -2543,6 +2543,30 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) { CI->getArgOperand(1), FMF)); } +Value *LibCallSimplifier::optimizeFMinimumnumFMaximumnum(CallInst *CI, + IRBuilderBase &B) { + Module *M = CI->getModule(); + + // If we can shrink the call to a float function rather than a double + // function, do that first. + Function *Callee = CI->getCalledFunction(); + StringRef Name = Callee->getName(); + if ((Name == "fminimum_num" || Name == "fmaximum_num") && + hasFloatVersion(M, Name)) + if (Value *Ret = optimizeBinaryDoubleFP(CI, B, TLI)) + return Ret; + + // The new fminimum_num/fmaximum_num functions, unlike fmin/fmax, *are* + // sensitive to the sigh of zero, so we don't change the fast-math flags like + // we did for those. + + Intrinsic::ID IID = Callee->getName().starts_with("fminimum_num") + ? Intrinsic::minimumnum + : Intrinsic::maximumnum; + return copyFlags(*CI, B.CreateBinaryIntrinsic(IID, CI->getArgOperand(0), + CI->getArgOperand(1), CI)); +} + Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { Function *LogFn = Log->getCalledFunction(); StringRef LogNm = LogFn->getName(); @@ -4123,6 +4147,13 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI, case LibFunc_fmax: case LibFunc_fmaxl: return optimizeFMinFMax(CI, Builder); + case LibFunc_fminimum_numf: + case LibFunc_fminimum_num: + case LibFunc_fminimum_numl: + case LibFunc_fmaximum_numf: + case LibFunc_fmaximum_num: + case LibFunc_fmaximum_numl: + return optimizeFMinimumnumFMaximumnum(CI, Builder); case LibFunc_cabs: case LibFunc_cabsf: case LibFunc_cabsl: diff --git a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll index 25a70a026a0b7..27ae0d53350f4 100644 --- a/llvm/test/Transforms/InferFunctionAttrs/annotate.ll +++ b/llvm/test/Transforms/InferFunctionAttrs/annotate.ll @@ -304,13 +304,13 @@ declare float @cbrtf(float) ; CHECK: declare x86_fp80 @cbrtl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare x86_fp80 @cbrtl(x86_fp80) -; CHECK: declare double @ceil(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare double @ceil(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare double @ceil(double) -; CHECK: declare float @ceilf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare float @ceilf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare float @ceilf(float) -; CHECK: declare x86_fp80 @ceill(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare x86_fp80 @ceill(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare x86_fp80 @ceill(x86_fp80) ; The second argument of int chmod(FILE*, mode_t) is a 32-bit int on most @@ -473,6 +473,24 @@ declare float @fminf(float, float) ; CHECK: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare x86_fp80 @fminl(x86_fp80, x86_fp80) +; CHECK: declare double @fmaximum_num(double, double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare double @fmaximum_num(double, double) + +; CHECK: declare float @fmaximum_numf(float, float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare float @fmaximum_numf(float, float) + +; CHECK: declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80) + +; CHECK: declare double @fminimum_num(double, double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare double @fminimum_num(double, double) + +; CHECK: declare float @fminimum_numf(float, float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare float @fminimum_numf(float, float) + +; CHECK: declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80) + ; CHECK: declare double @fmod(double, double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare double @fmod(double, double) @@ -909,15 +927,24 @@ declare x86_fp80 @rintl(x86_fp80) ; CHECK: declare noundef i32 @rmdir(ptr noundef readonly captures(none)) [[NOFREE_NOUNWIND]] declare i32 @rmdir(ptr) -; CHECK: declare double @round(double) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare double @round(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare double @round(double) -; CHECK: declare float @roundf(float) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare float @roundf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare float @roundf(float) -; CHECK: declare x86_fp80 @roundl(x86_fp80) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +; CHECK: declare x86_fp80 @roundl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare x86_fp80 @roundl(x86_fp80) +; CHECK: declare double @roundeven(double) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare double @roundeven(double) + +; CHECK: declare float @roundevenf(float) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare float @roundevenf(float) + +; CHECK: declare x86_fp80 @roundevenl(x86_fp80) [[MEMNONE_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] +declare x86_fp80 @roundevenl(x86_fp80) + ; CHECK: declare double @scalbln(double, i64) [[ERRNOMEMONLY_NOFREE_NOUNWIND_WILLRETURN:#[0-9]+]] declare double @scalbln(double, i64) diff --git a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll index 77b6ed7c5abe8..6383feff3a6ee 100644 --- a/llvm/test/Transforms/InstCombine/float-shrink-compare.ll +++ b/llvm/test/Transforms/InstCombine/float-shrink-compare.ll @@ -463,6 +463,34 @@ define i1 @test18(float %x, float %y, float %z) { ret i1 %5 } +define i1 @test_fminimum_num(float %x, float %y, float %z) { +; CHECK-LABEL: @test_fminimum_num( +; CHECK-NEXT: [[FMINIMUM_NUMF:%.*]] = call float @llvm.minimumnum.f32(float [[X:%.*]], float [[Y:%.*]]) +; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq float [[FMINIMUM_NUMF]], [[Z:%.*]] +; CHECK-NEXT: ret i1 [[TMP5]] +; + %1 = fpext float %x to double + %2 = fpext float %y to double + %3 = call double @fminimum_num(double %1, double %2) nounwind + %4 = fpext float %z to double + %5 = fcmp oeq double %3, %4 + ret i1 %5 +} + +define i1 @test_fmaximum_num(float %x, float %y, float %z) { +; CHECK-LABEL: @test_fmaximum_num( +; CHECK-NEXT: [[FMAXIMUM_NUMF:%.*]] = call float @llvm.maximumnum.f32(float [[X:%.*]], float [[Y:%.*]]) +; CHECK-NEXT: [[TMP5:%.*]] = fcmp oeq float [[FMAXIMUM_NUMF]], [[Z:%.*]] +; CHECK-NEXT: ret i1 [[TMP5]] +; + %1 = fpext float %x to double + %2 = fpext float %y to double + %3 = call double @fmaximum_num(double %1, double %2) nounwind + %4 = fpext float %z to double + %5 = fcmp oeq double %3, %4 + ret i1 %5 +} + define i1 @test19(float %x, float %y, float %z) { ; CHECK-LABEL: @test19( ; CHECK-NEXT: [[COPYSIGNF:%.*]] = call float @copysignf(float [[X:%.*]], float [[Y:%.*]]) #[[ATTR0:[0-9]+]] @@ -518,6 +546,8 @@ declare double @roundeven(double) nounwind readnone declare double @trunc(double) nounwind readnone declare double @fmin(double, double) nounwind readnone declare double @fmax(double, double) nounwind readnone +declare double @fminimum_num(double, double) nounwind readnone +declare double @fmaximum_num(double, double) nounwind readnone declare double @llvm.fabs.f64(double) nounwind readnone declare double @llvm.ceil.f64(double) nounwind readnone diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll new file mode 100644 index 0000000000000..e6448847112fb --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/ConstProp/roundeven.ll @@ -0,0 +1,157 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -S -passes=early-cse -earlycse-debug-hash < %s | FileCheck %s + +declare float @roundevenf(float) #0 +declare float @llvm.roundeven.f32(float) +declare double @roundeven(double) #0 +declare double @llvm.roundeven.f64(double) + +define float @constant_fold_roundeven_f32_01() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_01( +; CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: ret float 1.000000e+00 +; + %x = call float @roundevenf(float 1.25) #0 + ret float %x +} + +define float @constant_fold_roundeven_f32_02() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_02( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float -1.000000e+00 +; + %x = call float @llvm.roundeven.f32(float -1.25) #0 + ret float %x +} + +; roundeven rounds ties to even, so 1.5 -> 2.0 (nearest even) +define float @constant_fold_roundeven_f32_03() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_03( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float 2.000000e+00 +; + %x = call float @roundevenf(float 1.5) #0 + ret float %x +} + +; roundeven rounds ties to even, so -1.5 -> -2.0 (nearest even) +define float @constant_fold_roundeven_f32_04() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_04( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float -2.000000e+00 +; + %x = call float @llvm.roundeven.f32(float -1.5) #0 + ret float %x +} + +; roundeven rounds ties to even, so 2.5 -> 2.0 (nearest even) +define float @constant_fold_roundeven_f32_05() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_05( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float 2.000000e+00 +; + %x = call float @roundevenf(float 2.5) #0 + ret float %x +} + +; roundeven rounds ties to even, so -2.5 -> -2.0 (nearest even) +define float @constant_fold_roundeven_f32_06() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_06( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float -2.000000e+00 +; + %x = call float @llvm.roundeven.f32(float -2.5) #0 + ret float %x +} + +define float @constant_fold_roundeven_f32_07() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_07( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float 3.000000e+00 +; + %x = call float @roundevenf(float 2.75) #0 + ret float %x +} + +define float @constant_fold_roundeven_f32_08() #0 { +; CHECK-LABEL: define float @constant_fold_roundeven_f32_08( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret float -3.000000e+00 +; + %x = call float @llvm.roundeven.f32(float -2.75) #0 + ret float %x +} + +define double @constant_fold_roundeven_f64_01() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_01( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double 1.000000e+00 +; + %x = call double @roundeven(double 1.3) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_02() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_02( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double -1.000000e+00 +; + %x = call double @llvm.roundeven.f64(double -1.3) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_03() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_03( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double 2.000000e+00 +; + %x = call double @roundeven(double 1.5) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_04() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_04( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double -2.000000e+00 +; + %x = call double @llvm.roundeven.f64(double -1.5) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_05() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_05( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double 2.000000e+00 +; + %x = call double @roundeven(double 2.5) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_06() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_06( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double -2.000000e+00 +; + %x = call double @llvm.roundeven.f64(double -2.5) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_07() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_07( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double 3.000000e+00 +; + %x = call double @roundeven(double 2.7) #0 + ret double %x +} + +define double @constant_fold_roundeven_f64_08() #0 { +; CHECK-LABEL: define double @constant_fold_roundeven_f64_08( +; CHECK-SAME: ) #[[ATTR0]] { +; CHECK-NEXT: ret double -3.000000e+00 +; + %x = call double @llvm.roundeven.f64(double -2.7) #0 + ret double %x +} + +attributes #0 = { nounwind readnone willreturn }