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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154960 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Joe Groff 2012-04-17 23:05:54 +00:00
parent e652b521f9
commit d5bda5ec66
4 changed files with 372 additions and 18 deletions

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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
}