summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/IR/Module.h7
-rw-r--r--llvm/lib/IR/Module.cpp9
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp8
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.cpp7
-rw-r--r--llvm/test/CodeGen/X86/no-plt.ll17
5 files changed, 46 insertions, 2 deletions
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 196e32e3615..58e4bc4494f 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -838,6 +838,13 @@ public:
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<MemoryBuffer> MB);
};
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index c230a50044c..9f1e6096932 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -510,6 +510,15 @@ void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
OwnedMemoryBuffer = std::move(MB);
}
+bool Module::getRtLibUseGOT() const {
+ auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("RtLibUseGOT"));
+ return Val && (cast<ConstantInt>(Val->getValue())->getZExtValue() > 0);
+}
+
+void Module::setRtLibUseGOT() {
+ addModuleFlag(ModFlagBehavior::Max, "RtLibUseGOT", 1);
+}
+
GlobalVariable *llvm::collectUsedGlobalVariables(
const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) {
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 956de5539d9..537434f5cba 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -3779,6 +3779,14 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
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
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 0a6eda7e243..c6ebaef587d 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -157,8 +157,11 @@ X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
// 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;
}
diff --git a/llvm/test/CodeGen/X86/no-plt.ll b/llvm/test/CodeGen/X86/no-plt.ll
index 9688a2e6f5b..8aa60f60169 100644
--- a/llvm/test/CodeGen/X86/no-plt.ll
+++ b/llvm/test/CodeGen/X86/no-plt.ll
@@ -3,6 +3,18 @@
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \
; RUN: | FileCheck -check-prefix=X64 --check-prefix=STATIC %s
+define void @memset_call(i8* nocapture %a, i8 %c, i32 %n) {
+; X64: callq *memset@GOTPCREL(%rip)
+ call void @llvm.memset.p0i8.i32(i8* %a, i8 %c, i32 %n, i1 false)
+ ret void
+}
+
+define void @memcpy_call(i8* nocapture %a, i8* nocapture readonly %b, i64 %n) {
+; X64: callq *memcpy@GOTPCREL(%rip)
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 %n, i32 1, i1 false)
+ ret void
+}
+
define i32 @main() {
; X64: callq *foo@GOTPCREL(%rip)
; PIC: callq bar@PLT
@@ -20,3 +32,8 @@ define i32 @main() {
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)
+
+!llvm.module.flags = !{!1}
+!1 = !{i32 7, !"RtLibUseGOT", i32 1}
OpenPOWER on IntegriCloud