Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -838,6 +838,13 @@ Metadata *getProfileSummary(); /// @} + /// Returns true if PLT should be avoided for RTLib calls. + bool getRtLibUseGOT() const; + + /// Set that PLT should be avoid for RTLib calls. + void setRtLibUseGOT(); + + /// Take ownership of the given memory buffer. void setOwnedMemoryBuffer(std::unique_ptr MB); }; Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ lib/IR/Module.cpp @@ -510,6 +510,15 @@ OwnedMemoryBuffer = std::move(MB); } +bool Module::getRtLibUseGOT() const { + auto *Val = cast_or_null(getModuleFlag("RtLibUseGOT")); + return Val && (cast(Val->getValue())->getZExtValue() > 0); +} + +void Module::setRtLibUseGOT() { + addModuleFlag(ModFlagBehavior::Max, "RtLibUseGOT", 1); +} + GlobalVariable *llvm::collectUsedGlobalVariables( const Module &M, SmallPtrSetImpl &Set, bool CompilerUsed) { const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used"; Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -3761,6 +3761,14 @@ Callee = DAG.getTargetExternalSymbol( S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags); + + if (OpFlags == X86II::MO_GOTPCREL) { + Callee = DAG.getNode(X86ISD::WrapperRIP, dl, + getPointerTy(DAG.getDataLayout()), Callee); + Callee = DAG.getLoad( + getPointerTy(DAG.getDataLayout()), dl, DAG.getEntryNode(), Callee, + MachinePointerInfo::getGOT(DAG.getMachineFunction())); + } } else if (Subtarget.isTarget64BitILP32() && Callee->getValueType(0) == MVT::i32) { // Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI Index: lib/Target/X86/X86Subtarget.cpp =================================================================== --- lib/Target/X86/X86Subtarget.cpp +++ lib/Target/X86/X86Subtarget.cpp @@ -157,8 +157,11 @@ // In Regcall calling convention those registers are used for passing // parameters. Thus we need to prevent lazy binding in Regcall. return X86II::MO_GOTPCREL; - if (F && F->hasFnAttribute(Attribute::NonLazyBind) && is64Bit()) - return X86II::MO_GOTPCREL; + // If PLT must be avoided then the call should be via GOTPCREL. + if (((F && F->hasFnAttribute(Attribute::NonLazyBind)) || + (!F && M.getRtLibUseGOT())) && + is64Bit()) + return X86II::MO_GOTPCREL; return X86II::MO_PLT; } Index: test/CodeGen/X86/no-plt.ll =================================================================== --- test/CodeGen/X86/no-plt.ll +++ test/CodeGen/X86/no-plt.ll @@ -3,28 +3,41 @@ ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \ ; RUN: | FileCheck -check-prefix=X64 %s -define i32 @main() #0 { -; X64: callq *_Z3foov@GOTPCREL(%rip) -; X64: callq _Z3barv -; X64: callq _Z3bazv +; Function Attrs: noinline nounwind uwtable +define void @memset_call(i8* nocapture %a, i8 %c, i32 %n) local_unnamed_addr #0 { +; X64: callq *memset@GOTPCREL(%rip) +entry: + call void @llvm.memset.p0i8.i32(i8* %a, i8 %c, i32 %n, i1 false) + ret void +} + +; Function Attrs: noinline nounwind uwtable +define void @memcpy_call(i8* nocapture %a, i8* nocapture readonly %b, i64 %n) local_unnamed_addr #0 { +; X64: callq *memcpy@GOTPCREL(%rip) +entry: + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 %n, i32 1, i1 false) + ret void +} + +define i32 @main() #1 { +; X64: callq *foo@GOTPCREL(%rip) +; X64: callq bar +; X64: callq baz entry: %retval = alloca i32, align 4 store i32 0, i32* %retval, align 4 - %call1 = call i32 @_Z3foov() - %call2 = call i32 @_Z3barv() - %call3 = call i32 @_Z3bazv() + %call1 = call i32 @foo() + %call2 = call i32 @bar() + %call3 = call i32 @baz() ret i32 0 } -; Function Attrs: nonlazybind -declare i32 @_Z3foov() #1 - -declare i32 @_Z3barv() #2 - -; Function Attrs: nonlazybind -declare hidden i32 @_Z3bazv() #3 - +declare i32 @foo() nonlazybind +declare i32 @bar() +declare hidden i32 @baz() nonlazybind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) -attributes #1 = { nonlazybind } -attributes #3 = { nonlazybind } +!llvm.module.flags = !{!1} +!1 = !{i32 7, !"RtLibUseGOT", i32 1}