Intrinsics calls should avoid the PLT when "RtLibUseGOT" metadata is present.
Differential Revision: https://reviews.llvm.org/D42216 llvm-svn: 325962
This commit is contained in:
parent
80af005a48
commit
609f8c013c
|
@ -838,6 +838,13 @@ public:
|
||||||
Metadata *getProfileSummary();
|
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.
|
/// Take ownership of the given memory buffer.
|
||||||
void setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB);
|
void setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB);
|
||||||
};
|
};
|
||||||
|
|
|
@ -510,6 +510,15 @@ void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
|
||||||
OwnedMemoryBuffer = std::move(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(
|
GlobalVariable *llvm::collectUsedGlobalVariables(
|
||||||
const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) {
|
const Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed) {
|
||||||
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
|
const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used";
|
||||||
|
|
|
@ -3779,6 +3779,14 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||||
|
|
||||||
Callee = DAG.getTargetExternalSymbol(
|
Callee = DAG.getTargetExternalSymbol(
|
||||||
S->getSymbol(), getPointerTy(DAG.getDataLayout()), OpFlags);
|
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() &&
|
} else if (Subtarget.isTarget64BitILP32() &&
|
||||||
Callee->getValueType(0) == MVT::i32) {
|
Callee->getValueType(0) == MVT::i32) {
|
||||||
// Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
|
// Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
|
||||||
|
|
|
@ -157,8 +157,11 @@ X86Subtarget::classifyGlobalFunctionReference(const GlobalValue *GV,
|
||||||
// In Regcall calling convention those registers are used for passing
|
// In Regcall calling convention those registers are used for passing
|
||||||
// parameters. Thus we need to prevent lazy binding in Regcall.
|
// parameters. Thus we need to prevent lazy binding in Regcall.
|
||||||
return X86II::MO_GOTPCREL;
|
return X86II::MO_GOTPCREL;
|
||||||
if (F && F->hasFnAttribute(Attribute::NonLazyBind) && is64Bit())
|
// If PLT must be avoided then the call should be via GOTPCREL.
|
||||||
return X86II::MO_GOTPCREL;
|
if (((F && F->hasFnAttribute(Attribute::NonLazyBind)) ||
|
||||||
|
(!F && M.getRtLibUseGOT())) &&
|
||||||
|
is64Bit())
|
||||||
|
return X86II::MO_GOTPCREL;
|
||||||
return X86II::MO_PLT;
|
return X86II::MO_PLT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,18 @@
|
||||||
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \
|
; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \
|
||||||
; RUN: | FileCheck -check-prefix=X64 --check-prefix=STATIC %s
|
; 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() {
|
define i32 @main() {
|
||||||
; X64: callq *foo@GOTPCREL(%rip)
|
; X64: callq *foo@GOTPCREL(%rip)
|
||||||
; PIC: callq bar@PLT
|
; PIC: callq bar@PLT
|
||||||
|
@ -20,3 +32,8 @@ define i32 @main() {
|
||||||
declare i32 @foo() nonlazybind
|
declare i32 @foo() nonlazybind
|
||||||
declare i32 @bar()
|
declare i32 @bar()
|
||||||
declare hidden i32 @baz() nonlazybind
|
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}
|
||||||
|
|
Loading…
Reference in New Issue