Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -945,12 +945,26 @@ Result.Val.getFloat())); } + bool EmitMathIntrinsic = true; + const Triple& Triple = getTarget().getTriple(); + if (Triple.isWindowsGNUEnvironment() && + Triple.getArch() == llvm::Triple::x86_64) { + // On x86_64 mingw, the calling convention handles long doubles as + // structs. This detail is normally handled within clang, but + // intrinsics lowered into libcalls in LLVM don't handle this. + // For these cases, skip emitting an intrinsic and emit a normal + // function call with the right calling convention instead. + const char *TypeStr = getContext().BuiltinInfo.getTypeString(BuiltinID); + if (strstr(TypeStr, "Ld")) // long double + EmitMathIntrinsic = false; + } + // 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()) { + if (FD->hasAttr() && EmitMathIntrinsic) { switch (BuiltinID) { case Builtin::BIceil: case Builtin::BIceilf: Index: test/CodeGen/mingw-x86_64-long-double-builtins.c =================================================================== --- /dev/null +++ test/CodeGen/mingw-x86_64-long-double-builtins.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple x86_64-mingw32 -emit-llvm -o - %s | FileCheck %s + +// Check that long double math functions are emitted as direct function +// calls instead of as intrinsics. + +long double floorl(long double); + +long double foo(long double a) { + return floorl(a); +// CHECK: call void @floorl(x86_fp80* sret {{.*}}, x86_fp80* {{.*}}) +}