forked from OSchip/llvm-project
AArch64: support nonlazybind
It's almost certainly not a good idea to actually use it in most cases (there's a pretty large code size overhead on AArch64), but we can't do those experiments until it's supported. llvm-svn: 300462
This commit is contained in:
parent
0a0c033295
commit
879a0b2e1b
|
@ -3239,30 +3239,26 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
|
|||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
||||
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
|
||||
// node so that legalize doesn't hack it.
|
||||
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
|
||||
Subtarget->isTargetMachO()) {
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
auto GV = G->getGlobal();
|
||||
if (Subtarget->classifyGlobalFunctionReference(GV, getTargetMachine()) ==
|
||||
AArch64II::MO_GOT) {
|
||||
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_GOT);
|
||||
Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
|
||||
} else {
|
||||
const GlobalValue *GV = G->getGlobal();
|
||||
bool InternalLinkage = GV->hasInternalLinkage();
|
||||
if (InternalLinkage)
|
||||
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
|
||||
else {
|
||||
Callee =
|
||||
DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_GOT);
|
||||
Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
|
||||
}
|
||||
} else if (ExternalSymbolSDNode *S =
|
||||
dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
|
||||
}
|
||||
} else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
|
||||
Subtarget->isTargetMachO()) {
|
||||
const char *Sym = S->getSymbol();
|
||||
Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, AArch64II::MO_GOT);
|
||||
Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
|
||||
} else {
|
||||
const char *Sym = S->getSymbol();
|
||||
Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
|
||||
}
|
||||
} else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
const GlobalValue *GV = G->getGlobal();
|
||||
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
|
||||
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
const char *Sym = S->getSymbol();
|
||||
Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
|
||||
}
|
||||
|
||||
// We don't usually want to end the call-sequence here because we would tidy
|
||||
|
|
|
@ -155,6 +155,23 @@ AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
|
|||
return AArch64II::MO_NO_FLAG;
|
||||
}
|
||||
|
||||
unsigned char AArch64Subtarget::classifyGlobalFunctionReference(
|
||||
const GlobalValue *GV, const TargetMachine &TM) const {
|
||||
// MachO large model always goes via a GOT, because we don't have the
|
||||
// relocations available to do anything else..
|
||||
if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() &&
|
||||
!GV->hasInternalLinkage())
|
||||
return AArch64II::MO_GOT;
|
||||
|
||||
// NonLazyBind goes via GOT unless we know it's available locally.
|
||||
auto *F = dyn_cast<Function>(GV);
|
||||
if (F && F->hasFnAttribute(Attribute::NonLazyBind) &&
|
||||
!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
|
||||
return AArch64II::MO_GOT;
|
||||
|
||||
return AArch64II::MO_NO_FLAG;
|
||||
}
|
||||
|
||||
/// This function returns the name of a function which has an interface
|
||||
/// like the non-standard bzero function, if such a function exists on
|
||||
/// the current subtarget and it is considered prefereable over
|
||||
|
|
|
@ -271,6 +271,9 @@ public:
|
|||
unsigned char ClassifyGlobalReference(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
unsigned char classifyGlobalFunctionReference(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
/// This function returns the name of a function which has an interface
|
||||
/// like the non-standard bzero function, if such a function exists on
|
||||
/// the current subtarget and it is considered prefereable over
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
; RUN: llc -mtriple=aarch64-apple-ios %s -o - | FileCheck %s
|
||||
|
||||
define void @local() nonlazybind {
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @nonlocal() nonlazybind
|
||||
|
||||
define void @test_laziness() {
|
||||
; CHECK-LABEL: test_laziness:
|
||||
|
||||
; CHECK: bl _local
|
||||
|
||||
; CHECK: adrp x[[TMP:[0-9]+]], _nonlocal@GOTPAGE
|
||||
; CHECK: ldr [[FUNC:x[0-9]+]], [x[[TMP]], _nonlocal@GOTPAGEOFF]
|
||||
; CHECK: blr [[FUNC]]
|
||||
|
||||
call void @local()
|
||||
call void @nonlocal()
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_laziness_tail() {
|
||||
; CHECK-LABEL: test_laziness_tail:
|
||||
|
||||
; CHECK: adrp x[[TMP:[0-9]+]], _nonlocal@GOTPAGE
|
||||
; CHECK: ldr [[FUNC:x[0-9]+]], [x[[TMP]], _nonlocal@GOTPAGEOFF]
|
||||
; CHECK: br [[FUNC]]
|
||||
|
||||
tail call void @nonlocal()
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue