Use shouldAssumeDSOLocal on AArch64.

This reduces code duplication and now AArch64 also handles PIE.

llvm-svn: 270844
This commit is contained in:
Rafael Espindola 2016-05-26 12:42:55 +00:00
parent 8437bb70fd
commit a224de06bc
5 changed files with 69 additions and 62 deletions

View File

@ -17,10 +17,12 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/CodeGen.h"
namespace llvm {
class GlobalValue;
@ -118,6 +120,9 @@ bool returnTypeIsEligibleForTailCall(const Function *F,
// or we are in LTO.
bool canBeOmittedFromSymbolTable(const GlobalValue *GV);
bool shouldAssumeDSOLocal(Reloc::Model RM, const Triple &TT, const Module &M,
const GlobalValue *GV);
DenseMap<const MachineBasicBlock *, int>
getFuncletMembership(const MachineFunction &MF);

View File

@ -650,6 +650,49 @@ bool llvm::canBeOmittedFromSymbolTable(const GlobalValue *GV) {
return !GS.IsCompared;
}
// FIXME: make this a proper option
static bool CanUseCopyRelocWithPIE = false;
bool llvm::shouldAssumeDSOLocal(Reloc::Model RM, const Triple &TT,
const Module &M, const GlobalValue *GV) {
// DLLImport explicitly marks the GV as external.
if (GV && GV->hasDLLImportStorageClass())
return false;
// Every other GV is local on COFF
if (TT.isOSBinFormatCOFF())
return true;
if (RM == Reloc::Static)
return true;
if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility()))
return true;
if (TT.isOSBinFormatELF()) {
assert(RM != Reloc::DynamicNoPIC);
// Some linkers can use copy relocations with pie executables.
if (M.getPIELevel() != PIELevel::Default) {
if (CanUseCopyRelocWithPIE)
return true;
// If the symbol is defined, it cannot be preempted.
if (GV && !GV->isDeclarationForLinker())
return true;
return false;
}
// ELF supports preemption of other symbols.
return false;
}
assert(TT.isOSBinFormatMachO());
if (GV && GV->isStrongDefinitionForLinker())
return true;
return false;
}
static void collectFuncletMembers(
DenseMap<const MachineBasicBlock *, int> &FuncletMembership, int Funclet,
const MachineBasicBlock *MBB) {

View File

@ -14,6 +14,7 @@
#include "AArch64Subtarget.h"
#include "AArch64InstrInfo.h"
#include "AArch64PBQPRegAlloc.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/TargetRegistry.h"
@ -73,39 +74,25 @@ const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const {
unsigned char
AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
const TargetMachine &TM) const {
bool isDef = GV->isStrongDefinitionForLinker();
// MachO large model always goes via a GOT, simply to get a single 8-byte
// absolute relocation on all global addresses.
if (TM.getCodeModel() == CodeModel::Large && isTargetMachO())
return AArch64II::MO_GOT;
Reloc::Model RM = TM.getRelocationModel();
if (!shouldAssumeDSOLocal(RM, TargetTriple, *GV->getParent(), GV))
return AArch64II::MO_GOT;
// The small code mode's direct accesses use ADRP, which cannot necessarily
// produce the value 0 (if the code is above 4GB).
if (TM.getCodeModel() == CodeModel::Small && GV->hasExternalWeakLinkage()) {
// In PIC mode use the GOT, but in absolute mode use a constant pool load.
if (TM.getRelocationModel() == Reloc::Static)
if (RM == Reloc::Static)
return AArch64II::MO_CONSTPOOL;
else
return AArch64II::MO_GOT;
}
// If symbol visibility is hidden, the extra load is not needed if
// the symbol is definitely defined in the current translation unit.
// The handling of non-hidden symbols in PIC mode is rather target-dependent:
// + On MachO, if the symbol is defined in this module the GOT can be
// skipped.
// + On ELF, the R_AARCH64_COPY relocation means that even symbols actually
// defined could end up in unexpected places. Use a GOT.
if (TM.getRelocationModel() != Reloc::Static && GV->hasDefaultVisibility()) {
if (isTargetMachO())
return isDef ? AArch64II::MO_NO_FLAG : AArch64II::MO_GOT;
else
// No need to go through the GOT for local symbols on ELF.
return GV->hasLocalLinkage() ? AArch64II::MO_NO_FLAG : AArch64II::MO_GOT;
}
return AArch64II::MO_NO_FLAG;
}

View File

@ -14,6 +14,7 @@
#include "X86Subtarget.h"
#include "X86InstrInfo.h"
#include "X86TargetMachine.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
@ -50,49 +51,6 @@ unsigned char X86Subtarget::classifyBlockAddressReference() const {
return classifyLocalReference(nullptr);
}
// FIXME: make this a proper option
static bool CanUseCopyRelocWithPIE = false;
static bool shouldAssumeDSOLocal(Reloc::Model RM, const Triple &TT,
const Module &M, const GlobalValue *GV) {
// DLLImport explicitly marks the GV as external.
if (GV && GV->hasDLLImportStorageClass())
return false;
// Every other GV is local on COFF
if (TT.isOSBinFormatCOFF())
return true;
if (RM == Reloc::Static)
return true;
if (GV && (GV->hasLocalLinkage() || !GV->hasDefaultVisibility()))
return true;
if (TT.isOSBinFormatELF()) {
assert(RM != Reloc::DynamicNoPIC);
// Some linkers can use copy relocations with pie executables.
if (M.getPIELevel() != PIELevel::Default) {
if (CanUseCopyRelocWithPIE)
return true;
// If the symbol is defined, it cannot be preempted.
if (GV && !GV->isDeclarationForLinker())
return true;
return false;
}
// ELF supports preemption of other symbols.
return false;
}
assert(TT.isOSBinFormatMachO());
if (GV && GV->isStrongDefinitionForLinker())
return true;
return false;
}
/// Classify a global variable reference for the current subtarget according to
/// how we should reference it in a non-pcrel context.
unsigned char

View File

@ -0,0 +1,14 @@
; RUN: llc -mtriple aarch64-pc-linux -relocation-model=pic < %s | FileCheck %s
@g1 = global i32 42
define i32* @get_g1() {
; CHECK: get_g1:
; CHECK: adrp x0, g1
; CHECK-NEXT: add x0, x0, :lo12:g1
ret i32* @g1
}
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"PIE Level", i32 2}