[CodeGen] fix mapping from fmod calls to frem instruction

Similar to D40044 and discussed in D40594.

llvm-svn: 319619
This commit is contained in:
Sanjay Patel 2017-12-02 17:52:00 +00:00
parent 0c0f77d03d
commit 08fba37e9d
3 changed files with 38 additions and 32 deletions

View File

@ -854,12 +854,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Result.Val.getFloat()));
}
// Math builtins have the same semantics as their math library twins.
// There are LLVM math intrinsics corresponding to math library functions
// except the intrinsic will never set errno while the math library might.
// Thus, we can transform math library and builtin calls to their
// semantically-equivalent LLVM intrinsic counterparts if the call is marked
// 'const' (it is known to never set errno).
// There are LLVM math intrinsics/instructions corresponding to math library
// functions except the LLVM op will never set errno while the math library
// might. Also, math builtins have the same semantics as their math library
// twins. Thus, we can transform math library and builtin calls to their
// LLVM counterparts if the call is marked 'const' (known to never set errno).
if (FD->hasAttr<ConstAttr>()) {
switch (BuiltinID) {
case Builtin::BIceil:
@ -942,6 +941,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__builtin_fminl:
return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum));
// fmod() is a special-case. It maps to the frem instruction rather than an
// LLVM intrinsic.
case Builtin::BIfmod:
case Builtin::BIfmodf:
case Builtin::BIfmodl:
case Builtin::BI__builtin_fmod:
case Builtin::BI__builtin_fmodf:
case Builtin::BI__builtin_fmodl: {
Value *Arg1 = EmitScalarExpr(E->getArg(0));
Value *Arg2 = EmitScalarExpr(E->getArg(1));
return RValue::get(Builder.CreateFRem(Arg1, Arg2, "fmod"));
}
case Builtin::BIlog:
case Builtin::BIlogf:
case Builtin::BIlogl:
@ -1067,14 +1079,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Result);
}
case Builtin::BI__builtin_fmod:
case Builtin::BI__builtin_fmodf:
case Builtin::BI__builtin_fmodl: {
Value *Arg1 = EmitScalarExpr(E->getArg(0));
Value *Arg2 = EmitScalarExpr(E->getArg(1));
Value *Result = Builder.CreateFRem(Arg1, Arg2, "fmod");
return RValue::get(Result);
}
case Builtin::BI__builtin_conj:
case Builtin::BI__builtin_conjf:
case Builtin::BI__builtin_conjl: {

View File

@ -6,12 +6,21 @@
// Test attributes and codegen of math builtins.
void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
f = __builtin_fmod(f,f); f = __builtin_fmodf(f,f); f = __builtin_fmodl(f,f);
// NO__ERRNO: frem double
// NO__ERRNO: frem float
// NO__ERRNO: frem x86_fp80
// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
__builtin_atan2(f,f); __builtin_atan2f(f,f) ; __builtin_atan2l(f, f);
// NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]]
// NO__ERRNO: declare float @atan2f(float, float) [[READNONE]]
// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]]
// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE]]
// HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]]
@ -33,13 +42,6 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
__builtin_fmod(f,f); __builtin_fmodf(f,f); __builtin_fmodl(f,f);
// NO__ERRNO-NOT: .fmod
// NO__ERRNO-NOT: @fmod
// HAS_ERRNO-NOT: .fmod
// HAS_ERRNO-NOT: @fmod
__builtin_frexp(f,i); __builtin_frexpf(f,i); __builtin_frexpl(f,i);
// NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]]

View File

@ -6,12 +6,21 @@
// Test attributes and builtin codegen of math library calls.
void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
f = fmod(f,f); f = fmodf(f,f); f = fmodl(f,f);
// NO__ERRNO: frem double
// NO__ERRNO: frem float
// NO__ERRNO: frem x86_fp80
// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
atan2(f,f); atan2f(f,f) ; atan2l(f, f);
// NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]]
// NO__ERRNO: declare float @atan2f(float, float) [[READNONE]]
// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]]
// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]]
// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE]]
// HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]]
@ -33,15 +42,6 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
// HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
fmod(f,f); fmodf(f,f); fmodl(f,f);
// NO__ERRNO: declare double @fmod(double, double) [[READNONE]]
// NO__ERRNO: declare float @fmodf(float, float) [[READNONE]]
// NO__ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[READNONE]]
// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE]]
// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
frexp(f,i); frexpf(f,i); frexpl(f,i);
// NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]]