forked from OSchip/llvm-project
fix pr12559: mark unavailable win32 math libcalls
also fix SimplifyLibCalls to use TLI rather than compile-time conditionals to enable optimizations on floor, ceil, round, rint, and nearbyint llvm-svn: 154960
This commit is contained in:
parent
1b73869a9b
commit
a81bcbb9bb
|
@ -83,7 +83,7 @@ namespace llvm {
|
|||
/// long double expm1l(long double x);
|
||||
expm1l,
|
||||
/// float expm1f(float x);
|
||||
expl1f,
|
||||
expm1f,
|
||||
/// double fabs(double x);
|
||||
fabs,
|
||||
/// long double fabsl(long double x);
|
||||
|
@ -159,8 +159,14 @@ namespace llvm {
|
|||
rint,
|
||||
/// float rintf(float x);
|
||||
rintf,
|
||||
/// long dobule rintl(long double x);
|
||||
/// long double rintl(long double x);
|
||||
rintl,
|
||||
/// double round(double x);
|
||||
round,
|
||||
/// float roundf(float x);
|
||||
roundf,
|
||||
/// long double roundl(long double x);
|
||||
roundl,
|
||||
/// double sin(double x);
|
||||
sin,
|
||||
/// long double sinl(long double x);
|
||||
|
|
|
@ -56,7 +56,7 @@ const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
|
|||
"exp2f",
|
||||
"expm1",
|
||||
"expm1l",
|
||||
"expl1f",
|
||||
"expm1f",
|
||||
"fabs",
|
||||
"fabsl",
|
||||
"fabsf",
|
||||
|
@ -95,6 +95,9 @@ const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
|
|||
"rint",
|
||||
"rintf",
|
||||
"rintl",
|
||||
"round",
|
||||
"roundf",
|
||||
"roundl",
|
||||
"sin",
|
||||
"sinl",
|
||||
"sinf",
|
||||
|
@ -155,6 +158,81 @@ static void initialize(TargetLibraryInfo &TLI, const Triple &T) {
|
|||
TLI.setUnavailable(LibFunc::siprintf);
|
||||
TLI.setUnavailable(LibFunc::fiprintf);
|
||||
}
|
||||
|
||||
if (T.getOS() == Triple::Win32) {
|
||||
// Win32 does not support long double
|
||||
TLI.setUnavailable(LibFunc::acosl);
|
||||
TLI.setUnavailable(LibFunc::asinl);
|
||||
TLI.setUnavailable(LibFunc::atanl);
|
||||
TLI.setUnavailable(LibFunc::atan2l);
|
||||
TLI.setUnavailable(LibFunc::ceill);
|
||||
TLI.setUnavailable(LibFunc::copysignl);
|
||||
TLI.setUnavailable(LibFunc::cosl);
|
||||
TLI.setUnavailable(LibFunc::coshl);
|
||||
TLI.setUnavailable(LibFunc::expl);
|
||||
TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf
|
||||
TLI.setUnavailable(LibFunc::fabsl);
|
||||
TLI.setUnavailable(LibFunc::floorl);
|
||||
TLI.setUnavailable(LibFunc::fmodl);
|
||||
TLI.setUnavailable(LibFunc::logl);
|
||||
TLI.setUnavailable(LibFunc::powl);
|
||||
TLI.setUnavailable(LibFunc::sinl);
|
||||
TLI.setUnavailable(LibFunc::sinhl);
|
||||
TLI.setUnavailable(LibFunc::sqrtl);
|
||||
TLI.setUnavailable(LibFunc::tanl);
|
||||
TLI.setUnavailable(LibFunc::tanhl);
|
||||
|
||||
// Win32 only has C89 math
|
||||
TLI.setUnavailable(LibFunc::exp2);
|
||||
TLI.setUnavailable(LibFunc::exp2f);
|
||||
TLI.setUnavailable(LibFunc::exp2l);
|
||||
TLI.setUnavailable(LibFunc::expm1);
|
||||
TLI.setUnavailable(LibFunc::expm1f);
|
||||
TLI.setUnavailable(LibFunc::expm1l);
|
||||
TLI.setUnavailable(LibFunc::log2);
|
||||
TLI.setUnavailable(LibFunc::log2f);
|
||||
TLI.setUnavailable(LibFunc::log2l);
|
||||
TLI.setUnavailable(LibFunc::log1p);
|
||||
TLI.setUnavailable(LibFunc::log1pf);
|
||||
TLI.setUnavailable(LibFunc::log1pl);
|
||||
TLI.setUnavailable(LibFunc::nearbyint);
|
||||
TLI.setUnavailable(LibFunc::nearbyintf);
|
||||
TLI.setUnavailable(LibFunc::nearbyintl);
|
||||
TLI.setUnavailable(LibFunc::rint);
|
||||
TLI.setUnavailable(LibFunc::rintf);
|
||||
TLI.setUnavailable(LibFunc::rintl);
|
||||
TLI.setUnavailable(LibFunc::round);
|
||||
TLI.setUnavailable(LibFunc::roundf);
|
||||
TLI.setUnavailable(LibFunc::roundl);
|
||||
TLI.setUnavailable(LibFunc::trunc);
|
||||
TLI.setUnavailable(LibFunc::truncf);
|
||||
TLI.setUnavailable(LibFunc::truncl);
|
||||
|
||||
// Win32 provides some C99 math with mangled names
|
||||
TLI.setAvailableWithName(LibFunc::copysign, "_copysign");
|
||||
|
||||
if (T.getArch() == Triple::x86) {
|
||||
// Win32 on x86 implements single-precision math functions as macros
|
||||
TLI.setUnavailable(LibFunc::acosf);
|
||||
TLI.setUnavailable(LibFunc::asinf);
|
||||
TLI.setUnavailable(LibFunc::atanf);
|
||||
TLI.setUnavailable(LibFunc::atan2f);
|
||||
TLI.setUnavailable(LibFunc::ceilf);
|
||||
TLI.setUnavailable(LibFunc::copysignf);
|
||||
TLI.setUnavailable(LibFunc::cosf);
|
||||
TLI.setUnavailable(LibFunc::coshf);
|
||||
TLI.setUnavailable(LibFunc::expf);
|
||||
TLI.setUnavailable(LibFunc::floorf);
|
||||
TLI.setUnavailable(LibFunc::fmodf);
|
||||
TLI.setUnavailable(LibFunc::logf);
|
||||
TLI.setUnavailable(LibFunc::powf);
|
||||
TLI.setUnavailable(LibFunc::sinf);
|
||||
TLI.setUnavailable(LibFunc::sinhf);
|
||||
TLI.setUnavailable(LibFunc::sqrtf);
|
||||
TLI.setUnavailable(LibFunc::tanf);
|
||||
TLI.setUnavailable(LibFunc::tanhf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1583,21 +1583,16 @@ void SimplifyLibCalls::InitOptimizations() {
|
|||
Optimizations["llvm.exp2.f64"] = &Exp2;
|
||||
Optimizations["llvm.exp2.f32"] = &Exp2;
|
||||
|
||||
#ifdef HAVE_FLOORF
|
||||
Optimizations["floor"] = &UnaryDoubleFP;
|
||||
#endif
|
||||
#ifdef HAVE_CEILF
|
||||
Optimizations["ceil"] = &UnaryDoubleFP;
|
||||
#endif
|
||||
#ifdef HAVE_ROUNDF
|
||||
Optimizations["round"] = &UnaryDoubleFP;
|
||||
#endif
|
||||
#ifdef HAVE_RINTF
|
||||
Optimizations["rint"] = &UnaryDoubleFP;
|
||||
#endif
|
||||
#ifdef HAVE_NEARBYINTF
|
||||
Optimizations["nearbyint"] = &UnaryDoubleFP;
|
||||
#endif
|
||||
if (TLI->has(LibFunc::floor) && TLI->has(LibFunc::floorf))
|
||||
Optimizations["floor"] = &UnaryDoubleFP;
|
||||
if (TLI->has(LibFunc::ceil) && TLI->has(LibFunc::ceilf))
|
||||
Optimizations["ceil"] = &UnaryDoubleFP;
|
||||
if (TLI->has(LibFunc::round) && TLI->has(LibFunc::roundf))
|
||||
Optimizations["round"] = &UnaryDoubleFP;
|
||||
if (TLI->has(LibFunc::rint) && TLI->has(LibFunc::rintf))
|
||||
Optimizations["rint"] = &UnaryDoubleFP;
|
||||
if (TLI->has(LibFunc::nearbyint) && TLI->has(LibFunc::nearbyintf))
|
||||
Optimizations["nearbyint"] = &UnaryDoubleFP;
|
||||
|
||||
// Integer Optimizations
|
||||
Optimizations["ffs"] = &FFS;
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
; RUN: opt -O2 -S -mtriple=i386-pc-win32 < %s | FileCheck %s -check-prefix=WIN32
|
||||
; RUN: opt -O2 -S -mtriple=x86_64-pc-win32 < %s | FileCheck %s -check-prefix=WIN64
|
||||
; RUN: opt -O2 -S -mtriple=i386-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW32
|
||||
; RUN: opt -O2 -S -mtriple=x86_64-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW64
|
||||
|
||||
; x86 win32 msvcrt does not provide entry points for single-precision libm.
|
||||
; x86-64 win32 msvcrt does (except for fabsf)
|
||||
; msvcrt does not provide C99 math, but mingw32 does.
|
||||
|
||||
declare double @acos(double %x)
|
||||
define float @float_acos(float %x) nounwind readnone {
|
||||
; WIN32: @float_acos
|
||||
; WIN32-NOT: float @acosf
|
||||
; WIN32: double @acos
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @acos(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @asin(double %x)
|
||||
define float @float_asin(float %x) nounwind readnone {
|
||||
; WIN32: @float_asin
|
||||
; WIN32-NOT: float @asinf
|
||||
; WIN32: double @asin
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @asin(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @atan(double %x)
|
||||
define float @float_atan(float %x) nounwind readnone {
|
||||
; WIN32: @float_atan
|
||||
; WIN32-NOT: float @atanf
|
||||
; WIN32: double @atan
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @atan(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @atan2(double %x, double %y)
|
||||
define float @float_atan2(float %x, float %y) nounwind readnone {
|
||||
; WIN32: @float_atan2
|
||||
; WIN32-NOT: float @atan2f
|
||||
; WIN32: double @atan2
|
||||
%1 = fpext float %x to double
|
||||
%2 = fpext float %y to double
|
||||
%3 = call double @atan2(double %1, double %2)
|
||||
%4 = fptrunc double %3 to float
|
||||
ret float %4
|
||||
}
|
||||
|
||||
declare double @ceil(double %x)
|
||||
define float @float_ceil(float %x) nounwind readnone {
|
||||
; WIN32: @float_ceil
|
||||
; WIN32-NOT: float @ceilf
|
||||
; WIN32: double @ceil
|
||||
; WIN64: @float_ceil
|
||||
; WIN64: float @ceilf
|
||||
; WIN64-NOT: double @ceil
|
||||
; MINGW32: @float_ceil
|
||||
; MINGW32: float @ceilf
|
||||
; MINGW32-NOT: double @ceil
|
||||
; MINGW64: @float_ceil
|
||||
; MINGW64: float @ceilf
|
||||
; MINGW64-NOT: double @ceil
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @ceil(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @_copysign(double %x)
|
||||
define float @float_copysign(float %x) nounwind readnone {
|
||||
; WIN32: @float_copysign
|
||||
; WIN32-NOT: float @copysignf
|
||||
; WIN32-NOT: float @_copysignf
|
||||
; WIN32: double @_copysign
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @_copysign(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @cos(double %x)
|
||||
define float @float_cos(float %x) nounwind readnone {
|
||||
; WIN32: @float_cos
|
||||
; WIN32-NOT: float @cosf
|
||||
; WIN32: double @cos
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @cos(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @cosh(double %x)
|
||||
define float @float_cosh(float %x) nounwind readnone {
|
||||
; WIN32: @float_cosh
|
||||
; WIN32-NOT: float @coshf
|
||||
; WIN32: double @cosh
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @cosh(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @exp(double %x, double %y)
|
||||
define float @float_exp(float %x, float %y) nounwind readnone {
|
||||
; WIN32: @float_exp
|
||||
; WIN32-NOT: float @expf
|
||||
; WIN32: double @exp
|
||||
%1 = fpext float %x to double
|
||||
%2 = fpext float %y to double
|
||||
%3 = call double @exp(double %1, double %2)
|
||||
%4 = fptrunc double %3 to float
|
||||
ret float %4
|
||||
}
|
||||
|
||||
declare double @fabs(double %x, double %y)
|
||||
define float @float_fabs(float %x, float %y) nounwind readnone {
|
||||
; WIN32: @float_fabs
|
||||
; WIN32-NOT: float @fabsf
|
||||
; WIN32: double @fabs
|
||||
; WIN64: @float_fabs
|
||||
; WIN64-NOT: float @fabsf
|
||||
; WIN64: double @fabs
|
||||
%1 = fpext float %x to double
|
||||
%2 = fpext float %y to double
|
||||
%3 = call double @fabs(double %1, double %2)
|
||||
%4 = fptrunc double %3 to float
|
||||
ret float %4
|
||||
}
|
||||
|
||||
declare double @floor(double %x)
|
||||
define float @float_floor(float %x) nounwind readnone {
|
||||
; WIN32: @float_floor
|
||||
; WIN32-NOT: float @floorf
|
||||
; WIN32: double @floor
|
||||
; WIN64: @float_floor
|
||||
; WIN64: float @floorf
|
||||
; WIN64-NOT: double @floor
|
||||
; MINGW32: @float_floor
|
||||
; MINGW32: float @floorf
|
||||
; MINGW32-NOT: double @floor
|
||||
; MINGW64: @float_floor
|
||||
; MINGW64: float @floorf
|
||||
; MINGW64-NOT: double @floor
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @floor(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @fmod(double %x, double %y)
|
||||
define float @float_fmod(float %x, float %y) nounwind readnone {
|
||||
; WIN32: @float_fmod
|
||||
; WIN32-NOT: float @fmodf
|
||||
; WIN32: double @fmod
|
||||
%1 = fpext float %x to double
|
||||
%2 = fpext float %y to double
|
||||
%3 = call double @fmod(double %1, double %2)
|
||||
%4 = fptrunc double %3 to float
|
||||
ret float %4
|
||||
}
|
||||
|
||||
declare double @log(double %x)
|
||||
define float @float_log(float %x) nounwind readnone {
|
||||
; WIN32: @float_log
|
||||
; WIN32-NOT: float @logf
|
||||
; WIN32: double @log
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @log(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @pow(double %x, double %y)
|
||||
define float @float_pow(float %x, float %y) nounwind readnone {
|
||||
; WIN32: @float_pow
|
||||
; WIN32-NOT: float @powf
|
||||
; WIN32: double @pow
|
||||
%1 = fpext float %x to double
|
||||
%2 = fpext float %y to double
|
||||
%3 = call double @pow(double %1, double %2)
|
||||
%4 = fptrunc double %3 to float
|
||||
ret float %4
|
||||
}
|
||||
|
||||
declare double @sin(double %x)
|
||||
define float @float_sin(float %x) nounwind readnone {
|
||||
; WIN32: @float_sin
|
||||
; WIN32-NOT: float @sinf
|
||||
; WIN32: double @sin
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @sin(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @sinh(double %x)
|
||||
define float @float_sinh(float %x) nounwind readnone {
|
||||
; WIN32: @float_sinh
|
||||
; WIN32-NOT: float @sinhf
|
||||
; WIN32: double @sinh
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @sinh(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @sqrt(double %x)
|
||||
define float @float_sqrt(float %x) nounwind readnone {
|
||||
; WIN32: @float_sqrt
|
||||
; WIN32-NOT: float @sqrtf
|
||||
; WIN32: double @sqrt
|
||||
; WIN64: @float_sqrt
|
||||
; WIN64: float @sqrtf
|
||||
; WIN64-NOT: double @sqrt
|
||||
; MINGW32: @float_sqrt
|
||||
; MINGW32: float @sqrtf
|
||||
; MINGW32-NOT: double @sqrt
|
||||
; MINGW64: @float_sqrt
|
||||
; MINGW64: float @sqrtf
|
||||
; MINGW64-NOT: double @sqrt
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @sqrt(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @tan(double %x)
|
||||
define float @float_tan(float %x) nounwind readnone {
|
||||
; WIN32: @float_tan
|
||||
; WIN32-NOT: float @tanf
|
||||
; WIN32: double @tan
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @tan(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
declare double @tanh(double %x)
|
||||
define float @float_tanh(float %x) nounwind readnone {
|
||||
; WIN32: @float_tanh
|
||||
; WIN32-NOT: float @tanhf
|
||||
; WIN32: double @tanh
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @tanh(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
||||
; win32 does not have round; mingw32 does
|
||||
declare double @round(double %x)
|
||||
define float @float_round(float %x) nounwind readnone {
|
||||
; WIN32: @float_round
|
||||
; WIN32-NOT: float @roundf
|
||||
; WIN32: double @round
|
||||
; WIN64: @float_round
|
||||
; WIN64-NOT: float @roundf
|
||||
; WIN64: double @round
|
||||
; MINGW32: @float_round
|
||||
; MINGW32: float @roundf
|
||||
; MINGW32-NOT: double @round
|
||||
; MINGW64: @float_round
|
||||
; MINGW64: float @roundf
|
||||
; MINGW64-NOT: double @round
|
||||
%1 = fpext float %x to double
|
||||
%2 = call double @round(double %1)
|
||||
%3 = fptrunc double %2 to float
|
||||
ret float %3
|
||||
}
|
||||
|
Loading…
Reference in New Issue