Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -838,6 +838,16 @@ Metadata *getProfileSummary(); /// @} + /// @name Utility functions for querying and setting if PLT must be avoided. + + /// \brief Returns true if PLT should be avoided for RTLib calls. + bool getRtLibUseGOT() const; + + /// \brief 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,19 @@ OwnedMemoryBuffer = std::move(MB); } +bool Module::getRtLibUseGOT() const { + auto *Val = cast_or_null(getModuleFlag("RtLibUseGOT")); + + if (Val && (cast(Val->getValue())->getZExtValue() > 0)) + return true; + + return false; +} + +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 @@ -3756,11 +3756,23 @@ } } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { const Module *Mod = DAG.getMachineFunction().getFunction().getParent(); - unsigned char OpFlags = - Subtarget.classifyGlobalFunctionReference(nullptr, *Mod); + // If PLT must be avoided then the call should be via GOTPCREL. + unsigned char OpFlags = X86II::MO_GOTPCREL; + + if (!Mod->getRtLibUseGOT()) { + OpFlags = Subtarget.classifyGlobalFunctionReference(nullptr, *Mod); + } 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: test/CodeGen/X86/no-plt.ll =================================================================== --- test/CodeGen/X86/no-plt.ll +++ test/CodeGen/X86/no-plt.ll @@ -3,7 +3,23 @@ ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \ ; RUN: | FileCheck -check-prefix=X64 %s -define i32 @main() #0 { +; 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 *_Z3foov@GOTPCREL(%rip) ; X64: callq _Z3barv ; X64: callq _Z3bazv @@ -18,13 +34,21 @@ } ; Function Attrs: nonlazybind -declare i32 @_Z3foov() #1 +declare i32 @_Z3foov() #2 -declare i32 @_Z3barv() #2 +declare i32 @_Z3barv() #3 ; Function Attrs: nonlazybind -declare hidden i32 @_Z3bazv() #3 +declare hidden i32 @_Z3bazv() #4 + +; Function Attrs: argmemonly nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) +; Function Attrs: argmemonly nounwind +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) #0 + +attributes #2 = { nonlazybind } +attributes #4 = { nonlazybind } -attributes #1 = { nonlazybind } -attributes #3 = { nonlazybind } +!llvm.module.flags = !{!1} +!1 = !{i32 7, !"RtLibUseGOT", i32 1}