Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions llvm/include/llvm/Analysis/TargetLibraryInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,13 +410,18 @@ 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:
case LibFunc_memcpy: case LibFunc_memset: case LibFunc_memmove:
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:
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" ||
Expand Down Expand Up @@ -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";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit sad that adding full support for a new libcall requires adding it to a manually-maintained list of functions starting with the letter R.

case 's':
return Name == "sin" || Name == "sinf" ||
Name == "sinh" || Name == "sinhf" ||
Expand Down Expand Up @@ -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
}
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand All @@ -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) {
Expand Down
21 changes: 15 additions & 6 deletions llvm/lib/Transforms/Utils/BuildLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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:
Expand Down
39 changes: 33 additions & 6 deletions llvm/test/Transforms/InferFunctionAttrs/annotate.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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]+]]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something to be fixed in a future PR and not here, but these CHECK lines don't appear to do anything. I'm not sure why, but this test always seems to pass regardless of what the actual function attributes are.

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
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
30 changes: 30 additions & 0 deletions llvm/test/Transforms/InstCombine/float-shrink-compare.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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]+]]
Expand Down Expand Up @@ -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
Expand Down
Loading
Loading