Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -1648,6 +1648,78 @@ return RValue::get(Builder.CreateCall(F, { Src, Src, ShiftAmt })); } +// Map math builtins for long-double to f128 version. +static unsigned adjustLongDoubleBuiltin(unsigned BuiltinID) { + switch (BuiltinID) { +#define ADJUST_LDBL(func) \ + case Builtin::BI__builtin_##func##l: \ + return Builtin::BI__builtin_##func##f128; + ADJUST_LDBL(sqrt) + ADJUST_LDBL(cbrt) + ADJUST_LDBL(fabs) + ADJUST_LDBL(log) + ADJUST_LDBL(log2) + ADJUST_LDBL(log10) + ADJUST_LDBL(log1p) + ADJUST_LDBL(logb) + ADJUST_LDBL(exp) + ADJUST_LDBL(exp2) + ADJUST_LDBL(expm1) + ADJUST_LDBL(fdim) + ADJUST_LDBL(hypot) + ADJUST_LDBL(ilogb) + ADJUST_LDBL(pow) + ADJUST_LDBL(fmin) + ADJUST_LDBL(fmax) + ADJUST_LDBL(ceil) + ADJUST_LDBL(trunc) + ADJUST_LDBL(rint) + ADJUST_LDBL(nearbyint) + ADJUST_LDBL(round) + ADJUST_LDBL(floor) + ADJUST_LDBL(lround) + ADJUST_LDBL(llround) + ADJUST_LDBL(lrint) + ADJUST_LDBL(llrint) + ADJUST_LDBL(fmod) + ADJUST_LDBL(modf) + ADJUST_LDBL(nan) + ADJUST_LDBL(nans) + ADJUST_LDBL(inf) + ADJUST_LDBL(fma) + ADJUST_LDBL(sin) + ADJUST_LDBL(cos) + ADJUST_LDBL(tan) + ADJUST_LDBL(sinh) + ADJUST_LDBL(cosh) + ADJUST_LDBL(tanh) + ADJUST_LDBL(asin) + ADJUST_LDBL(acos) + ADJUST_LDBL(atan) + ADJUST_LDBL(asinh) + ADJUST_LDBL(acosh) + ADJUST_LDBL(atanh) + ADJUST_LDBL(atan2) + ADJUST_LDBL(erf) + ADJUST_LDBL(erfc) + ADJUST_LDBL(ldexp) + ADJUST_LDBL(frexp) + ADJUST_LDBL(huge_val) + ADJUST_LDBL(copysign) + ADJUST_LDBL(nextafter) + ADJUST_LDBL(nexttoward) + ADJUST_LDBL(remainder) + ADJUST_LDBL(remquo) + ADJUST_LDBL(scalbln) + ADJUST_LDBL(scalbn) + ADJUST_LDBL(tgamma) + ADJUST_LDBL(lgamma) +#undef ADJUST_LDBL + default: + return BuiltinID; + } +} + RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -1664,6 +1736,11 @@ Result.Val.getFloat())); } + // If current long-double semantics is IEEE 128-bit, replace math builtins + // of long-double with f128 equivalent. + if (&getTarget().getLongDoubleFormat() == &llvm::APFloat::IEEEquad()) + BuiltinID = adjustLongDoubleBuiltin(BuiltinID); + // If the builtin has been declared explicitly with an assembler label, // disable the specialized emitting below. Ideally we should communicate the // rename in IR, or at least avoid generating the intrinsic calls that are Index: clang/test/CodeGen/math-builtins-adjust.c =================================================================== --- /dev/null +++ clang/test/CodeGen/math-builtins-adjust.c @@ -0,0 +1,307 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s -fmath-errno | FileCheck %s -check-prefix=F80 +// RUN: %clang_cc1 -triple ppc64le-unknown-unknown -w -S -o - -emit-llvm %s -fmath-errno | FileCheck %s -check-prefix=PPC +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -mlong-double-128 -w -S -o - -emit-llvm %s -fmath-errno | FileCheck %s -check-prefix=F128 +// RUN: %clang_cc1 -triple ppc64le-unknown-unknown -mabi=ieeelongdouble -w -S -o - -emit-llvm %s -fmath-errno | FileCheck %s -check-prefix=F128 + +void bar(long double); + +void foo(long double f, long double *l, int *i, const char *c) { + // F80: call x86_fp80 @fmodl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @fmodf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @fmodl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_fmodl(f,f); + + // F80: call x86_fp80 @atan2l(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @atan2f128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @atan2l(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_atan2l(f,f); + + // F80: call x86_fp80 @llvm.copysign.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.copysign.f128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.copysign.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_copysignl(f,f); + + // F80: call x86_fp80 @llvm.fabs.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.fabs.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 %{{.+}}) + __builtin_fabsl(f); + + // F80: call x86_fp80 @frexpl(x86_fp80 %{{.+}}, i32* %{{.+}}) + // F128: call fp128 @frexpf128(fp128 %{{.+}}, i32* %{{.+}}) + // PPC: call ppc_fp128 @frexpl(ppc_fp128 %{{.+}}, i32* %{{.+}}) + __builtin_frexpl(f,i); + + // F80: store x86_fp80 0xK7FFF8000000000000000, x86_fp80* + // F128: store fp128 0xL00000000000000007FFF000000000000, fp128* + // PPC: store ppc_fp128 0xM7FF00000000000000000000000000000, ppc_fp128* + *l = __builtin_huge_vall(); + + // F80: store x86_fp80 0xK7FFF8000000000000000, x86_fp80* + // F128: store fp128 0xL00000000000000007FFF000000000000, fp128* + // PPC: store ppc_fp128 0xM7FF00000000000000000000000000000, ppc_fp128* + *l = __builtin_infl(); + + // F80: call x86_fp80 @ldexpl(x86_fp80 %{{.+}}, i32 %{{.+}}) + // F128: call fp128 @ldexpf128(fp128 %{{.+}}, {{(signext)?.+}}) + // PPC: call ppc_fp128 @ldexpl(ppc_fp128 %{{.+}}, {{(signext)?.+}}) + __builtin_ldexpl(f,f); + + // F80: call x86_fp80 @modfl(x86_fp80 %{{.+}}, x86_fp80* %{{.+}}) + // F128: call fp128 @modff128(fp128 %{{.+}}, fp128* %{{.+}}) + // PPC: call ppc_fp128 @modfl(ppc_fp128 %{{.+}}, ppc_fp128* %{{.+}}) + __builtin_modfl(f,l); + + // F80: call x86_fp80 @nanl(i8* %{{.+}}) + // F128: call fp128 @nanf128(i8* %{{.+}}) + // PPC: call ppc_fp128 @nanl(i8* %{{.+}}) + __builtin_nanl(c); + + // F80: call x86_fp80 @nansl(i8* %{{.+}}) + // F128: call fp128 @nansf128(i8* %{{.+}}) + // PPC: call ppc_fp128 @nansl(i8* %{{.+}}) + __builtin_nansl(c); + + // F80: call x86_fp80 @powl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @powf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @powl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_powl(f,f); + + // F80: call x86_fp80 @acosl(x86_fp80 %{{.+}}) + // F128: call fp128 @acosf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @acosl(ppc_fp128 %{{.+}}) + __builtin_acosl(f); + + // F80: call x86_fp80 @acoshl(x86_fp80 %{{.+}}) + // F128: call fp128 @acoshf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @acoshl(ppc_fp128 %{{.+}}) + __builtin_acoshl(f); + + // F80: call x86_fp80 @asinl(x86_fp80 %{{.+}}) + // F128: call fp128 @asinf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @asinl(ppc_fp128 %{{.+}}) + __builtin_asinl(f); + + // F80: call x86_fp80 @asinhl(x86_fp80 %{{.+}}) + // F128: call fp128 @asinhf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @asinhl(ppc_fp128 %{{.+}}) + __builtin_asinhl(f); + + // F80: call x86_fp80 @atanl(x86_fp80 %{{.+}}) + // F128: call fp128 @atanf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @atanl(ppc_fp128 %{{.+}}) + __builtin_atanl(f); + + // F80: call x86_fp80 @atanhl(x86_fp80 %{{.+}}) + // F128: call fp128 @atanhf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @atanhl(ppc_fp128 %{{.+}}) + __builtin_atanhl(f); + + // F80: call x86_fp80 @cbrtl(x86_fp80 %{{.+}}) + // F128: call fp128 @cbrtf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @cbrtl(ppc_fp128 %{{.+}}) + __builtin_cbrtl(f); + + // F80: call x86_fp80 @llvm.ceil.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.ceil.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.ceil.ppcf128(ppc_fp128 %{{.+}}) + __builtin_ceill(f); + + // F80: call x86_fp80 @cosl(x86_fp80 %{{.+}}) + // F128: call fp128 @cosf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @cosl(ppc_fp128 %{{.+}}) + __builtin_cosl(f); + + // F80: call x86_fp80 @coshl(x86_fp80 %{{.+}}) + // F128: call fp128 @coshf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @coshl(ppc_fp128 %{{.+}}) + __builtin_coshl(f); + + // F80: call x86_fp80 @llvm.floor.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.floor.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.floor.ppcf128(ppc_fp128 %{{.+}}) + __builtin_floorl(f); + + // F80: call x86_fp80 @llvm.maxnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.maxnum.f128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_fmaxl(f,f); + + // F80: call x86_fp80 @llvm.minnum.f80(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.minnum.f128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_fminl(f,f); + + // F80: call x86_fp80 @llvm.nearbyint.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.nearbyint.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.nearbyint.ppcf128(ppc_fp128 %{{.+}}) + __builtin_nearbyintl(f); + + // F80: call x86_fp80 @llvm.trunc.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.trunc.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.trunc.ppcf128(ppc_fp128 %{{.+}}) + __builtin_truncl(f); + + // F80: call x86_fp80 @llvm.rint.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.rint.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.rint.ppcf128(ppc_fp128 %{{.+}}) + __builtin_rintl(f); + + // F80: call x86_fp80 @llvm.round.f80(x86_fp80 %{{.+}}) + // F128: call fp128 @llvm.round.f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @llvm.round.ppcf128(ppc_fp128 %{{.+}}) + __builtin_roundl(f); + // F80: call x86_fp80 @erfl(x86_fp80 %{{.+}}) + // F128: call fp128 @erff128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @erfl(ppc_fp128 %{{.+}}) + __builtin_erfl(f); + + // F80: call x86_fp80 @erfcl(x86_fp80 %{{.+}}) + // F128: call fp128 @erfcf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @erfcl(ppc_fp128 %{{.+}}) + __builtin_erfcl(f); + + // F80: call x86_fp80 @expl(x86_fp80 %{{.+}}) + // F128: call fp128 @expf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @expl(ppc_fp128 %{{.+}}) + __builtin_expl(f); + + // F80: call x86_fp80 @exp2l(x86_fp80 %{{.+}}) + // F128: call fp128 @exp2f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @exp2l(ppc_fp128 %{{.+}}) + __builtin_exp2l(f); + + // F80: call x86_fp80 @expm1l(x86_fp80 %{{.+}}) + // F128: call fp128 @expm1f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @expm1l(ppc_fp128 %{{.+}}) + __builtin_expm1l(f); + + // F80: call x86_fp80 @fdiml(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @fdimf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @fdiml(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_fdiml(f,f); + + // F80: call x86_fp80 @fmal(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @fmaf128(fp128 %{{.+}}, fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @fmal(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_fmal(f,f,f); + + // F80: call x86_fp80 @hypotl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @hypotf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @hypotl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_hypotl(f,f); + + // F80: call i32 @ilogbl(x86_fp80 %{{.+}}) + // F128: call {{(i32)|(signext i32)}} @ilogbf128(fp128 %{{.+}}) + // PPC: call {{(i32)|(signext i32)}} @ilogbl(ppc_fp128 %{{.+}}) + __builtin_ilogbl(f); + + // F80: call x86_fp80 @lgammal(x86_fp80 %{{.+}}) + // F128: call fp128 @lgammaf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @lgammal(ppc_fp128 %{{.+}}) + __builtin_lgammal(f); + + // F80: call i64 @llrintl(x86_fp80 %{{.+}}) + // F128: call i64 @llrintf128(fp128 %{{.+}}) + // PPC: call i64 @llrintl(ppc_fp128 %{{.+}}) + __builtin_llrintl(f); + + // F80: call i64 @llroundl(x86_fp80 %{{.+}}) + // F128: call i64 @llroundf128(fp128 %{{.+}}) + // PPC: call i64 @llroundl(ppc_fp128 %{{.+}}) + __builtin_llroundl(f); + + // F80: call x86_fp80 @logl(x86_fp80 %{{.+}}) + // F128: call fp128 @logf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @logl(ppc_fp128 %{{.+}}) + __builtin_logl(f); + + // F80: call x86_fp80 @log10l(x86_fp80 %{{.+}}) + // F128: call fp128 @log10f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @log10l(ppc_fp128 %{{.+}}) + __builtin_log10l(f); + + // F80: call x86_fp80 @log1pl(x86_fp80 %{{.+}}) + // F128: call fp128 @log1pf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @log1pl(ppc_fp128 %{{.+}}) + __builtin_log1pl(f); + + // F80: call x86_fp80 @log2l(x86_fp80 %{{.+}}) + // F128: call fp128 @log2f128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @log2l(ppc_fp128 %{{.+}}) + __builtin_log2l(f); + + // F80: call x86_fp80 @logbl(x86_fp80 %{{.+}}) + // F128: call fp128 @logbf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @logbl(ppc_fp128 %{{.+}}) + __builtin_logbl(f); + + // F80: call i64 @lrintl(x86_fp80 %{{.+}}) + // F128: call i64 @lrintf128(fp128 %{{.+}}) + // PPC: call i64 @lrintl(ppc_fp128 %{{.+}}) + __builtin_lrintl(f); + + // F80: call i64 @lroundl(x86_fp80 %{{.+}}) + // F128: call i64 @lroundf128(fp128 %{{.+}}) + // PPC: call i64 @lroundl(ppc_fp128 %{{.+}}) + __builtin_lroundl(f); + + // F80: call x86_fp80 @nextafterl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @nextafterf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @nextafterl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_nextafterl(f,f); + + // F80: call x86_fp80 @nexttowardl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @nexttowardf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @nexttowardl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_nexttowardl(f,f); + + // F80: call x86_fp80 @remainderl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) + // F128: call fp128 @remainderf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPC: call ppc_fp128 @remainderl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) + __builtin_remainderl(f,f); + + // F80: call x86_fp80 @remquol(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}, i32* %{{.+}}) + // F128: call fp128 @remquof128(fp128 %{{.+}}, fp128 %{{.+}}, i32* %{{.+}}) + // PPC: call ppc_fp128 @remquol(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}, i32* %{{.+}}) + __builtin_remquol(f,f,i); + + // F80: call x86_fp80 @scalblnl(x86_fp80 %{{.+}}, i64 %{{.+}}) + // F128: call fp128 @scalblnf128(fp128 %{{.+}}, i64 %{{.+}}) + // PPC: call ppc_fp128 @scalblnl(ppc_fp128 %{{.+}}, i64 %{{.+}}) + __builtin_scalblnl(f,f); + + // F80: call x86_fp80 @scalbnl(x86_fp80 %{{.+}}, i32 %{{.+}}) + // F128: call fp128 @scalbnf128(fp128 %{{.+}}, {{(signext)?.+}}) + // PPC: call ppc_fp128 @scalbnl(ppc_fp128 %{{.+}}, {{(signext)?.+}}) + __builtin_scalbnl(f,f); + + // F80: call x86_fp80 @sinl(x86_fp80 %{{.+}}) + // F128: call fp128 @sinf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @sinl(ppc_fp128 %{{.+}}) + __builtin_sinl(f); + + // F80: call x86_fp80 @sinhl(x86_fp80 %{{.+}}) + // F128: call fp128 @sinhf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @sinhl(ppc_fp128 %{{.+}}) + __builtin_sinhl(f); + + // F80: call x86_fp80 @sqrtl(x86_fp80 %{{.+}}) + // F128: call fp128 @sqrtf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @sqrtl(ppc_fp128 %{{.+}}) + __builtin_sqrtl(f); + + // F80: call x86_fp80 @tanl(x86_fp80 %{{.+}}) + // F128: call fp128 @tanf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @tanl(ppc_fp128 %{{.+}}) + __builtin_tanl(f); + + // F80: call x86_fp80 @tanhl(x86_fp80 %{{.+}}) + // F128: call fp128 @tanhf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @tanhl(ppc_fp128 %{{.+}}) + __builtin_tanhl(f); + + // F80: call x86_fp80 @tgammal(x86_fp80 %{{.+}}) + // F128: call fp128 @tgammaf128(fp128 %{{.+}}) + // PPC: call ppc_fp128 @tgammal(ppc_fp128 %{{.+}}) + __builtin_tgammal(f); +}