diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -247,6 +247,11 @@ MCSymbol *getSymbol(const GlobalValue *GV) const; + /// Similar to getSymbol() but preferred for references. On ELF, this uses a + /// local symbol if a reference to GV is guaranteed to be resolved to the + /// definition in the same module. + MCSymbol *getSymbolPreferLocal(const GlobalValue &GV) const; + //===------------------------------------------------------------------===// // XRay instrumentation implementation. //===------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -450,6 +450,21 @@ return TM.getSymbol(GV); } +MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { + // On ELF, use .Lfoo$local if GV is a non-interposable GlobalObject with an + // exact definion (intersection of GlobalValue::hasExactDefinition() and + // !isInterposable()). These linkages include: external, appending, internal, + // private. It may be profitable to use a local alias for external. The + // assembler would otherwise be conservative and assume a global default + // visibility symbol can be interposable, even if the code generator already + // assumed it. + if (TM.getTargetTriple().isOSBinFormatELF() && + GlobalObject::isExternalLinkage(GV.getLinkage()) && GV.isDSOLocal() && + !GV.isDeclaration() && isa(GV)) + return getSymbolWithGlobalValueBase(&GV, "$local"); + return TM.getSymbol(&GV); +} + /// EmitGlobalVariable - Emit the specified global variable to the .s file. void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal(); @@ -631,6 +646,9 @@ EmitAlignment(Alignment, GV); OutStreamer->EmitLabel(EmittedInitSym); + MCSymbol *LocalAlias = getSymbolPreferLocal(*GV); + if (LocalAlias != EmittedInitSym) + OutStreamer->EmitLabel(LocalAlias); EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); @@ -767,7 +785,13 @@ report_fatal_error("'" + Twine(CurrentFnSym->getName()) + "' label emitted multiple times to assembly file"); - return OutStreamer->EmitLabel(CurrentFnSym); + OutStreamer->EmitLabel(CurrentFnSym); + + if (TM.getTargetTriple().isOSBinFormatELF()) { + MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction()); + if (Sym != CurrentFnSym) + OutStreamer->EmitLabel(Sym); + } } /// emitComments - Pretty-print comments for instructions. diff --git a/llvm/test/CodeGen/AArch64/emutls.ll b/llvm/test/CodeGen/AArch64/emutls.ll --- a/llvm/test/CodeGen/AArch64/emutls.ll +++ b/llvm/test/CodeGen/AArch64/emutls.ll @@ -155,6 +155,7 @@ ; ARM64: .data{{$}} ; ARM64: .globl __emutls_v.i4 ; ARM64-LABEL: __emutls_v.i4: +; ARM64-NEXT: .L__emutls_v.i4$local: ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 4 ; ARM64-NEXT: .xword 0 @@ -162,6 +163,7 @@ ; ARM64: .section .rodata, ; ARM64-LABEL: __emutls_t.i4: +; ARM64-NEXT: .L__emutls_t.i4$local: ; ARM64-NEXT: .word 15 ; ARM64-NOT: __emutls_v.i5: diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.ll b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.ll --- a/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.ll +++ b/llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.ll @@ -4,6 +4,7 @@ @v = common dso_local global i32* null, align 8 ; CHECK-LABEL: foo: // @foo +; CHECK-NEXT: .Lfoo$local: ; CHECK-NEXT: // %bb.0: // %entry ; CHECK-NEXT: paciasp ; CHECK-NOT: OUTLINED_FUNCTION_ @@ -22,6 +23,7 @@ } ; CHECK-LABEL: bar: // @bar +; CHECK-NEXT: .Lbar$local: ; CHECK-NEXT: // %bb.0: // %entry ; CHECK-NEXT: paciasp ; CHECK-NOT: OUTLINED_FUNCTION_ diff --git a/llvm/test/CodeGen/ARM/emutls.ll b/llvm/test/CodeGen/ARM/emutls.ll --- a/llvm/test/CodeGen/ARM/emutls.ll +++ b/llvm/test/CodeGen/ARM/emutls.ll @@ -238,6 +238,7 @@ ; ARM32: .data{{$}} ; ARM32: .globl __emutls_v.i4 ; ARM32-LABEL: __emutls_v.i4: +; ARM32-NEXT: .L__emutls_v.i4$local: ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 4 ; ARM32-NEXT: .long 0 @@ -245,6 +246,7 @@ ; ARM32: .section .rodata, ; ARM32-LABEL: __emutls_t.i4: +; ARM32-NEXT: .L__emutls_t.i4$local: ; ARM32-NEXT: .long 15 ; ARM32-NOT: __emutls_v.i5: diff --git a/llvm/test/CodeGen/X86/emutls.ll b/llvm/test/CodeGen/X86/emutls.ll --- a/llvm/test/CodeGen/X86/emutls.ll +++ b/llvm/test/CodeGen/X86/emutls.ll @@ -275,6 +275,7 @@ ; X32 .section .data.rel.local, ; X32-LABEL: __emutls_v.i4: +; X32-NEXT: .L__emutls_v.i4$local: ; X32-NEXT: .long 4 ; X32-NEXT: .long 4 ; X32-NEXT: .long 0 @@ -282,6 +283,7 @@ ; X32 .section .rodata, ; X32-LABEL: __emutls_t.i4: +; X32-NEXT: .L__emutls_t.i4$local: ; X32-NEXT: .long 15 ; X32-NOT: __emutls_v.i5: @@ -336,6 +338,7 @@ ; X64 .section .data.rel.local, ; X64-LABEL: __emutls_v.i4: +; X64-NEXT: .L__emutls_v.i4$local: ; X64-NEXT: .quad 4 ; X64-NEXT: .quad 4 ; X64-NEXT: .quad 0 @@ -343,6 +346,7 @@ ; X64 .section .rodata, ; X64-LABEL: __emutls_t.i4: +; X64-NEXT: .L__emutls_t.i4$local: ; X64-NEXT: .long 15 ; X64-NOT: __emutls_v.i5: diff --git a/llvm/test/CodeGen/X86/linux-preemption.ll b/llvm/test/CodeGen/X86/linux-preemption.ll --- a/llvm/test/CodeGen/X86/linux-preemption.ll +++ b/llvm/test/CodeGen/X86/linux-preemption.ll @@ -1,9 +1,9 @@ -; RUN: llc -mtriple x86_64-pc-linux \ -; RUN: -relocation-model=static < %s | FileCheck --check-prefix=STATIC %s -; RUN: llc -mtriple x86_64-pc-linux \ -; RUN: -relocation-model=pic < %s | FileCheck %s -; RUN: llc -mtriple x86_64-pc-linux \ -; RUN: -relocation-model=dynamic-no-pic < %s | FileCheck %s +; RUN: llc -mtriple x86_64-pc-linux -relocation-model=static < %s | \ +; RUN: FileCheck --check-prefixes=COMMON,STATIC %s +; RUN: llc -mtriple x86_64-pc-linux -relocation-model=pic < %s | \ +; RUN: FileCheck --check-prefixes=COMMON,CHECK %s +; RUN: llc -mtriple x86_64-pc-linux -relocation-model=dynamic-no-pic < %s | \ +; RUN: FileCheck --check-prefixes=COMMON,CHECK %s ; 32 bits @@ -173,6 +173,8 @@ define void()* @get_strong_local_function() { ret void()* @strong_local_function } +; COMMON: {{^}}strong_local_function: +; COMMON-NEXT .Lstrong_local_function: ; CHECK: leaq strong_local_function(%rip), %rax ; STATIC: movl $strong_local_function, %eax ; CHECK32: leal strong_local_function@GOTOFF(%eax), %eax @@ -223,3 +225,6 @@ ; CHECK: movq external_preemptable_function@GOTPCREL(%rip), %rax ; STATIC: movl $external_preemptable_function, %eax ; CHECK32: movl external_preemptable_function@GOT(%eax), %eax + +; COMMON: {{^}}strong_local_global: +; COMMON-NEXT .Lstrong_local_global: