Index: include/llvm/Analysis/TargetLibraryInfo.def =================================================================== --- include/llvm/Analysis/TargetLibraryInfo.def +++ include/llvm/Analysis/TargetLibraryInfo.def @@ -738,6 +738,9 @@ /// int fprintf(FILE *stream, const char *format, ...); TLI_DEFINE_ENUM_INTERNAL(fprintf) TLI_DEFINE_STRING_INTERNAL("fprintf") +/// int fprintf_no_Lf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(fprintf_no_Lf) +TLI_DEFINE_STRING_INTERNAL("fprintf_no_Lf") /// int fputc(int c, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(fputc) TLI_DEFINE_STRING_INTERNAL("fputc") @@ -1030,6 +1033,9 @@ /// int printf(const char *format, ...); TLI_DEFINE_ENUM_INTERNAL(printf) TLI_DEFINE_STRING_INTERNAL("printf") +/// int printf_no_Lf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(printf_no_Lf) +TLI_DEFINE_STRING_INTERNAL("printf_no_Lf") /// int putc(int c, FILE *stream); TLI_DEFINE_ENUM_INTERNAL(putc) TLI_DEFINE_STRING_INTERNAL("putc") @@ -1137,6 +1143,9 @@ /// int sprintf(char *str, const char *format, ...); TLI_DEFINE_ENUM_INTERNAL(sprintf) TLI_DEFINE_STRING_INTERNAL("sprintf") +/// int sprintf_no_Lf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(sprintf_no_Lf) +TLI_DEFINE_STRING_INTERNAL("sprintf_no_Lf") /// double sqrt(double x); TLI_DEFINE_ENUM_INTERNAL(sqrt) TLI_DEFINE_STRING_INTERNAL("sqrt") Index: lib/Analysis/TargetLibraryInfo.cpp =================================================================== --- lib/Analysis/TargetLibraryInfo.cpp +++ lib/Analysis/TargetLibraryInfo.cpp @@ -152,13 +152,21 @@ TLI.setAvailableWithName(LibFunc_fputs, "fputs$UNIX2003"); } - // iprintf and friends are only available on XCore and TCE. - if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce) { + // iprintf and friends are only available on XCore, TCE, and WASI. + if (T.getArch() != Triple::xcore && T.getArch() != Triple::tce && + T.getOS() != Triple::WASI) { TLI.setUnavailable(LibFunc_iprintf); TLI.setUnavailable(LibFunc_siprintf); TLI.setUnavailable(LibFunc_fiprintf); } + // printf_no_Lf and friends are only available on WASI. + if (T.getOS() != Triple::WASI) { + TLI.setUnavailable(LibFunc_printf_no_Lf); + TLI.setUnavailable(LibFunc_sprintf_no_Lf); + TLI.setUnavailable(LibFunc_fprintf_no_Lf); + } + if (T.isOSWindows() && !T.isOSCygMing()) { // Win32 does not support long double TLI.setUnavailable(LibFunc_acosl); @@ -738,6 +746,7 @@ case LibFunc_stat: case LibFunc_statvfs: case LibFunc_siprintf: + case LibFunc_sprintf_no_Lf: case LibFunc_sprintf: return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isPointerTy() && @@ -835,6 +844,7 @@ case LibFunc_getenv: case LibFunc_getpwnam: case LibFunc_iprintf: + case LibFunc_printf_no_Lf: case LibFunc_pclose: case LibFunc_perror: case LibFunc_printf: @@ -914,6 +924,7 @@ FTy.getParamType(1)->isPointerTy()); case LibFunc_fscanf: case LibFunc_fiprintf: + case LibFunc_fprintf_no_Lf: case LibFunc_fprintf: return (NumParams >= 2 && FTy.getReturnType()->isIntegerTy() && FTy.getParamType(0)->isPointerTy() && Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -104,6 +104,12 @@ }); } +static bool callHasFP128Argument(const CallInst *CI) { + return any_of(CI->operands(), [](const Use &OI) { + return OI->getType()->isFP128Ty(); + }); +} + static Value *convertStrToNumber(CallInst *CI, StringRef &Str, int64_t Base) { if (Base < 2 || Base > 36) // handle special zero base @@ -2025,12 +2031,27 @@ if (TLI->has(LibFunc_iprintf) && !callHasFloatingPointArgument(CI)) { Module *M = B.GetInsertBlock()->getParent()->getParent(); FunctionCallee IPrintFFn = - M->getOrInsertFunction("iprintf", FT, Callee->getAttributes()); + M->getOrInsertFunction(TLI->getName(LibFunc_iprintf), + FT, Callee->getAttributes()); CallInst *New = cast(CI->clone()); New->setCalledFunction(IPrintFFn); B.Insert(New); return New; } + + // printf(format, ...) -> printf_no_Lf(format, ...) if no 128-bit floating point + // arguments. + if (TLI->has(LibFunc_printf) && !callHasFP128Argument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + auto PrintFNoLfFn = + M->getOrInsertFunction(TLI->getName(LibFunc_printf_no_Lf), + FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(PrintFNoLfFn); + B.Insert(New); + return New; + } + return nullptr; } @@ -2110,6 +2131,19 @@ B.Insert(New); return New; } + + // sprintf(str, format, ...) -> sprintf_no_Lf(str, format, ...) if no 128-bit + // floating point arguments. + if (TLI->has(LibFunc_sprintf_no_Lf) && !callHasFP128Argument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + auto SPrintFNoLfFn = + M->getOrInsertFunction("sprintf_no_Lf", FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(SPrintFNoLfFn); + B.Insert(New); + return New; + } + return nullptr; } @@ -2267,6 +2301,19 @@ B.Insert(New); return New; } + + // fprintf(stream, format, ...) -> fprintf_no_Lf(stream, format, ...) if no + // 128-bit floating point arguments. + if (TLI->has(LibFunc_fprintf_no_Lf) && !callHasFP128Argument(CI)) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + auto FPrintFNoLfFn = + M->getOrInsertFunction("fprintf_no_Lf", FT, Callee->getAttributes()); + CallInst *New = cast(CI->clone()); + New->setCalledFunction(FPrintFNoLfFn); + B.Insert(New); + return New; + } + return nullptr; } Index: unittests/Analysis/TargetLibraryInfoTest.cpp =================================================================== --- unittests/Analysis/TargetLibraryInfoTest.cpp +++ unittests/Analysis/TargetLibraryInfoTest.cpp @@ -493,6 +493,9 @@ "declare i32 @fiprintf(%struct*, i8*, ...)\n" "declare i32 @iprintf(i8*, ...)\n" "declare i32 @siprintf(i8*, i8*, ...)\n" + "declare i32 @fprintf_no_Lf(%struct*, i8*, ...)\n" + "declare i32 @printf_no_Lf(i8*, ...)\n" + "declare i32 @sprintf_no_Lf(i8*, i8*, ...)\n" "declare i32 @htonl(i32)\n" "declare i16 @htons(i16)\n"