Index: include/llvm/Transforms/Utils/BuildLibCalls.h =================================================================== --- include/llvm/Transforms/Utils/BuildLibCalls.h +++ include/llvm/Transforms/Utils/BuildLibCalls.h @@ -28,7 +28,7 @@ /// If the library function is unavailable, this doesn't modify it. /// /// Returns true if any attributes were set and false otherwise. - bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI); + bool inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI, Module *M); /// Check whether the overloaded unary floating point function /// corresponding to \a Ty is available. Index: lib/Transforms/IPO/InferFunctionAttrs.cpp =================================================================== --- lib/Transforms/IPO/InferFunctionAttrs.cpp +++ lib/Transforms/IPO/InferFunctionAttrs.cpp @@ -27,7 +27,7 @@ // We only infer things using the prototype and the name; we don't need // definitions. if (F.isDeclaration() && !F.hasFnAttribute((Attribute::OptimizeNone))) - Changed |= inferLibFuncAttributes(F, TLI); + Changed |= inferLibFuncAttributes(F, TLI, &M); return Changed; } Index: lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -923,7 +923,7 @@ Value *MSP = M->getOrInsertFunction("memset_pattern16", Builder.getVoidTy(), Int8PtrTy, Int8PtrTy, IntPtr); - inferLibFuncAttributes(*M->getFunction("memset_pattern16"), *TLI); + inferLibFuncAttributes(*M->getFunction("memset_pattern16"), *TLI, M); // Otherwise we should form a memset_pattern16. PatternValue is known to be // an constant array of 16-bytes. Plop the value into a mergable global. Index: lib/Transforms/Utils/BuildLibCalls.cpp =================================================================== --- lib/Transforms/Utils/BuildLibCalls.cpp +++ lib/Transforms/Utils/BuildLibCalls.cpp @@ -105,12 +105,24 @@ return true; } -bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) { +static bool setNonLazyBind(Function &F) { + if (F.hasFnAttribute(Attribute::NonLazyBind)) + return false; + F.addFnAttr(Attribute::NonLazyBind); + return true; +} + +bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI, + Module *M) { LibFunc TheLibFunc; if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc))) return false; bool Changed = false; + + if (M != nullptr && M->getRtLibUseGOT()) + Changed |= setNonLazyBind(F); + switch (TheLibFunc) { case LibFunc_strlen: case LibFunc_wcslen: @@ -738,7 +750,7 @@ LLVMContext &Context = B.GetInsertBlock()->getContext(); Constant *StrLen = M->getOrInsertFunction("strlen", DL.getIntPtrType(Context), B.getInt8PtrTy()); - inferLibFuncAttributes(*M->getFunction("strlen"), *TLI); + inferLibFuncAttributes(*M->getFunction("strlen"), *TLI, M); CallInst *CI = B.CreateCall(StrLen, castToCStr(Ptr, B), "strlen"); if (const Function *F = dyn_cast(StrLen->stripPointerCasts())) CI->setCallingConv(F->getCallingConv()); @@ -756,7 +768,7 @@ Type *I32Ty = B.getInt32Ty(); Constant *StrChr = M->getOrInsertFunction("strchr", I8Ptr, I8Ptr, I32Ty); - inferLibFuncAttributes(*M->getFunction("strchr"), *TLI); + inferLibFuncAttributes(*M->getFunction("strchr"), *TLI, M); CallInst *CI = B.CreateCall( StrChr, {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, "strchr"); if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) @@ -774,7 +786,7 @@ Value *StrNCmp = M->getOrInsertFunction("strncmp", B.getInt32Ty(), B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)); - inferLibFuncAttributes(*M->getFunction("strncmp"), *TLI); + inferLibFuncAttributes(*M->getFunction("strncmp"), *TLI, M); CallInst *CI = B.CreateCall( StrNCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, "strncmp"); @@ -792,7 +804,7 @@ Module *M = B.GetInsertBlock()->getModule(); Type *I8Ptr = B.getInt8PtrTy(); Value *StrCpy = M->getOrInsertFunction(Name, I8Ptr, I8Ptr, I8Ptr); - inferLibFuncAttributes(*M->getFunction(Name), *TLI); + inferLibFuncAttributes(*M->getFunction(Name), *TLI, M); CallInst *CI = B.CreateCall(StrCpy, {castToCStr(Dst, B), castToCStr(Src, B)}, Name); if (const Function *F = dyn_cast(StrCpy->stripPointerCasts())) @@ -809,7 +821,7 @@ Type *I8Ptr = B.getInt8PtrTy(); Value *StrNCpy = M->getOrInsertFunction(Name, I8Ptr, I8Ptr, I8Ptr, Len->getType()); - inferLibFuncAttributes(*M->getFunction(Name), *TLI); + inferLibFuncAttributes(*M->getFunction(Name), *TLI, M); CallInst *CI = B.CreateCall( StrNCpy, {castToCStr(Dst, B), castToCStr(Src, B), Len}, "strncpy"); if (const Function *F = dyn_cast(StrNCpy->stripPointerCasts())) @@ -850,7 +862,7 @@ Value *MemChr = M->getOrInsertFunction("memchr", B.getInt8PtrTy(), B.getInt8PtrTy(), B.getInt32Ty(), DL.getIntPtrType(Context)); - inferLibFuncAttributes(*M->getFunction("memchr"), *TLI); + inferLibFuncAttributes(*M->getFunction("memchr"), *TLI, M); CallInst *CI = B.CreateCall(MemChr, {castToCStr(Ptr, B), Val, Len}, "memchr"); if (const Function *F = dyn_cast(MemChr->stripPointerCasts())) @@ -869,7 +881,7 @@ Value *MemCmp = M->getOrInsertFunction("memcmp", B.getInt32Ty(), B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context)); - inferLibFuncAttributes(*M->getFunction("memcmp"), *TLI); + inferLibFuncAttributes(*M->getFunction("memcmp"), *TLI, M); CallInst *CI = B.CreateCall( MemCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, "memcmp"); @@ -939,7 +951,7 @@ Module *M = B.GetInsertBlock()->getModule(); Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(), B.getInt32Ty()); - inferLibFuncAttributes(*M->getFunction("putchar"), *TLI); + inferLibFuncAttributes(*M->getFunction("putchar"), *TLI, M); CallInst *CI = B.CreateCall(PutChar, B.CreateIntCast(Char, B.getInt32Ty(), @@ -960,7 +972,7 @@ Module *M = B.GetInsertBlock()->getModule(); Value *PutS = M->getOrInsertFunction("puts", B.getInt32Ty(), B.getInt8PtrTy()); - inferLibFuncAttributes(*M->getFunction("puts"), *TLI); + inferLibFuncAttributes(*M->getFunction("puts"), *TLI, M); CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), "puts"); if (const Function *F = dyn_cast(PutS->stripPointerCasts())) CI->setCallingConv(F->getCallingConv()); @@ -976,7 +988,7 @@ Constant *F = M->getOrInsertFunction("fputc", B.getInt32Ty(), B.getInt32Ty(), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(*M->getFunction("fputc"), *TLI); + inferLibFuncAttributes(*M->getFunction("fputc"), *TLI, M); Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true, "chari"); CallInst *CI = B.CreateCall(F, {Char, File}, "fputc"); @@ -996,7 +1008,7 @@ Constant *F = M->getOrInsertFunction( FPutsName, B.getInt32Ty(), B.getInt8PtrTy(), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(*M->getFunction(FPutsName), *TLI); + inferLibFuncAttributes(*M->getFunction(FPutsName), *TLI, M); CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, "fputs"); if (const Function *Fn = dyn_cast(F->stripPointerCasts())) @@ -1017,7 +1029,7 @@ DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType()); if (File->getType()->isPointerTy()) - inferLibFuncAttributes(*M->getFunction(FWriteName), *TLI); + inferLibFuncAttributes(*M->getFunction(FWriteName), *TLI, M); CallInst *CI = B.CreateCall(F, {castToCStr(Ptr, B), Size, ConstantInt::get(DL.getIntPtrType(Context), 1), File}); Index: test/CodeGen/X86/no-plt-libcalls.ll =================================================================== --- test/CodeGen/X86/no-plt-libcalls.ll +++ test/CodeGen/X86/no-plt-libcalls.ll @@ -0,0 +1,19 @@ +; Check if "RtLibUseGOT" works correctly when lib calls are simplified. +; RUN: opt < %s -instcombine -S | FileCheck %s + +@percent_s = constant [4 x i8] c"%s\0A\00" +@hello_world = constant [13 x i8] c"hello world\0A\00" +declare i32 @printf(i8*, ...) +define void @printf_call() { + %fmt = getelementptr [4 x i8], [4 x i8]* @percent_s, i32 0, i32 0 + %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 + call i32 (i8*, ...) @printf(i8* %fmt, i8* %str) +; CHECK: call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i64 0, i64 0)) + ret void +} + +; CHECK: Function Attrs: nounwind nonlazybind +; CHECK-NEXT: declare i32 @puts(i8* nocapture readonly) + +!llvm.module.flags = !{!0} +!0 = !{i32 7, !"RtLibUseGOT", i32 1}