Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -96,13 +96,31 @@ StringRef Name; GlobalDecl D(FD); + static SmallDenseMap F128Builtins{ + {Builtin::BI__builtin_printf, "__printfieee128"}, + {Builtin::BI__builtin_vsnprintf, "__vsnprintfieee128"}, + {Builtin::BI__builtin_vsprintf, "__vsprintfieee128"}, + {Builtin::BI__builtin_sprintf, "__sprintfieee128"}, + {Builtin::BI__builtin_snprintf, "__snprintfieee128"}, + {Builtin::BI__builtin_fprintf, "__fprintfieee128"}, + {Builtin::BI__builtin_nexttowardf128, "__nexttowardieee128"}, + }; + // If the builtin has been declared explicitly with an assembler label, // use the mangled name. This differs from the plain label on platforms // that prefix labels. if (FD->hasAttr()) Name = getMangledName(D); - else - Name = Context.BuiltinInfo.getName(BuiltinID) + 10; + else { + // TODO: This mutation should also be applied to other targets other than + // PPC, after backend supports IEEE 128-bit style libcalls. + if (getTriple().isPPC64() && + &getTarget().getLongDoubleFormat() == &llvm::APFloat::IEEEquad() && + F128Builtins.find(BuiltinID) != F128Builtins.end()) + Name = F128Builtins[BuiltinID]; + else + Name = Context.BuiltinInfo.getName(BuiltinID) + 10; + } llvm::FunctionType *Ty = cast(getTypes().ConvertType(FD->getType())); Index: clang/test/CodeGen/math-builtins-long.c =================================================================== --- clang/test/CodeGen/math-builtins-long.c +++ clang/test/CodeGen/math-builtins-long.c @@ -307,7 +307,7 @@ // F80: call x86_fp80 @nexttowardl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) // PPC: call ppc_fp128 @nexttowardl(ppc_fp128 %{{.+}}, ppc_fp128 %{{.+}}) // X86F128: call fp128 @nexttowardl(fp128 %{{.+}}, fp128 %{{.+}}) - // PPCF128: call fp128 @nexttowardf128(fp128 %{{.+}}, fp128 %{{.+}}) + // PPCF128: call fp128 @__nexttowardieee128(fp128 %{{.+}}, fp128 %{{.+}}) __builtin_nexttowardl(f,f); // F80: call x86_fp80 @remainderl(x86_fp80 %{{.+}}, x86_fp80 %{{.+}}) Index: clang/test/CodeGen/ppc64-f128-builtins.c =================================================================== --- /dev/null +++ clang/test/CodeGen/ppc64-f128-builtins.c @@ -0,0 +1,63 @@ +// RUN: %clang_cc1 -triple powerpc64le-linux-gnu -emit-llvm -o - %s \ +// RUN: -mabi=ieeelongdouble | FileCheck --check-prefix=IEEE128 %s +// RUN: %clang_cc1 -triple powerpc64le-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck --check-prefix=PPC128 %s + +long double x; +char buf[20]; + +// IEEE128-LABEL: define dso_local void @test_printf +// IEEE128: call signext i32 (i8*, ...) @__printfieee128 +// PPC128-LABEL: define dso_local void @test_printf +// PPC128: call signext i32 (i8*, ...) @printf +void test_printf() { + __builtin_printf("%.Lf", x); +} + +// IEEE128-LABEL: define dso_local void @test_vsnprintf +// IEEE128: call signext i32 @__vsnprintfieee128 +// PPC128-LABEL: define dso_local void @test_vsnprintf +// PPC128: call signext i32 @vsnprintf +void test_vsnprintf(int n, ...) { + __builtin_va_list va; + __builtin_va_start(va, n); + __builtin_vsnprintf(buf, 20, "%.Lf", va); + __builtin_va_end(va); +} + +// IEEE128-LABEL: define dso_local void @test_vsprintf +// IEEE128: call signext i32 @__vsprintfieee128 +// PPC128-LABEL: define dso_local void @test_vsprintf +// PPC128: call signext i32 @vsprintf +void test_vsprintf(int n, ...) { + __builtin_va_list va; + __builtin_va_start(va, n); + __builtin_vsprintf(buf, "%.Lf", va); + __builtin_va_end(va); +} + +// IEEE128-LABEL: define dso_local void @test_sprintf +// IEEE128: call signext i32 (i8*, i8*, ...) @__sprintfieee128 +// PPC128-LABEL: define dso_local void @test_sprintf +// PPC128: call signext i32 (i8*, i8*, ...) @sprintf +void test_sprintf() { + __builtin_sprintf(buf, "%.Lf", x); +} + +// IEEE128-LABEL: define dso_local void @test_snprintf +// IEEE128: call signext i32 (i8*, i64, i8*, ...) @__snprintfieee128 +// PPC128-LABEL: define dso_local void @test_snprintf +// PPC128: call signext i32 (i8*, i64, i8*, ...) @snprintf +void test_snprintf() { + __builtin_snprintf(buf, 20, "%.Lf", x); +} + +// GLIBC has special handling of 'nexttoward' + +// IEEE128-LABEL: define dso_local fp128 @test_nexttoward +// IEEE128: call fp128 @__nexttowardieee128 +// PPC128-LABEL: define dso_local ppc_fp128 @test_nexttoward +// PPC128: call ppc_fp128 @nexttowardl +long double test_nexttoward(long double a, long double b) { + return __builtin_nexttowardl(a, b); +}