[llvm] 8903e61 - [AsmPrinter][ELF] Define local aliases (.Lfoo$local) for GlobalObjects

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 29 10:58:56 PST 2020


Author: Fangrui Song
Date: 2020-01-29T10:58:43-08:00
New Revision: 8903e61b66112941513449e32e65a7ea85ea31fc

URL: https://github.com/llvm/llvm-project/commit/8903e61b66112941513449e32e65a7ea85ea31fc
DIFF: https://github.com/llvm/llvm-project/commit/8903e61b66112941513449e32e65a7ea85ea31fc.diff

LOG: [AsmPrinter][ELF] Define local aliases (.Lfoo$local) for GlobalObjects

For `MC_GlobalAddress` operands referencing **certain** GlobalObjects,
we can lower them to STB_LOCAL aliases to avoid costs brought by
assembler/linker's conservative decisions about symbol interposition:

* An assembler conservatively assumes a global default visibility symbol interposable (ELF
  semantics). So relocations in object files are needed even if the code generator assumed
  the definition exact and non-interposable.
* The relocations can cause the creation of PLT entries on some targets for -shared links.
  A linker conservatively assumes a global default visibility symbol interposable (if not
  otherwise constrained by -Bsymbolic/--dynamic-list/VER_NDX_LOCAL/etc).

"certain" refers to GlobalObjects in the intersection of
`hasExactDefinition() and !isInterposable()`: `external`, `appending`, `internal`, `private`.
Local linkages (`internal` and `private`) cannot be interposed. `appending` is for very
few objects LLVM interpret specially.  So the set just includes `external`.

This patch emits STB_LOCAL aliases (.Lfoo$local) for such GlobalObjects, so that targets can lower
MC_GlobalAddress operands to STB_LOCAL aliases if applicable.
We may extend the scope and include GlobalAlias in the future.

LLVM's existing -fno-semantic-interposition behaviors give us license to do such optimizations:

* Various optimizations (ipconstprop, inliner, sccp, sroa, etc) treat normal ExternalLinkage
  GlobalObjects as non-interposable.
* Before D72197, MC resolved a PC-relative VK_None fixup to a non-local symbol at assembly time (no
  outstanding relocation), if the target is defined in the same section. Put it simply, even if IR
  optimizations failed to optimize and allowed interposition for the function call in
  `void foo() {} void bar() { foo(); }`, the assembler would disallow it.

This patch sets up AsmPrinter infrastructure to make -fno-semantic-interposition more so.
With and without the patch, the object file output should be identical:
`.Lfoo$local` does not take a symbol table entry.

Reviewed By: sfertile

Differential Revision: https://reviews.llvm.org/D73228

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/AsmPrinter.h
    llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
    llvm/test/CodeGen/AArch64/emutls.ll
    llvm/test/CodeGen/AArch64/machine-outliner-retaddr-sign-sp-mod.ll
    llvm/test/CodeGen/ARM/emutls.ll
    llvm/test/CodeGen/X86/emutls.ll
    llvm/test/CodeGen/X86/linux-preemption.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 2cd407b1ab6e..b48f9fa0ad2d 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -247,6 +247,11 @@ class AsmPrinter : public MachineFunctionPass {
 
   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
index 6793b7a4d8dc..98163f4d83bb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -450,6 +450,21 @@ MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
   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<GlobalObject>(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 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
   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 @@ void AsmPrinter::EmitFunctionEntryLabel() {
     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
index 25be391bbfaa..85d2c1a3b315 100644
--- a/llvm/test/CodeGen/AArch64/emutls.ll
+++ b/llvm/test/CodeGen/AArch64/emutls.ll
@@ -155,6 +155,7 @@ entry:
 ; 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 @@ entry:
 
 ; 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
index 8fd152869b23..46355b35d0de 100644
--- 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 @@ entry:
 }
 
 ; 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
index 48ea96f9a0b6..2488dca1fc02 100644
--- a/llvm/test/CodeGen/ARM/emutls.ll
+++ b/llvm/test/CodeGen/ARM/emutls.ll
@@ -238,6 +238,7 @@ entry:
 ; 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 @@ entry:
 
 ; 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
index 75d45c074791..fecf8fdba4b7 100644
--- a/llvm/test/CodeGen/X86/emutls.ll
+++ b/llvm/test/CodeGen/X86/emutls.ll
@@ -275,6 +275,7 @@ entry:
 
 ; 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 @@ entry:
 
 ; 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 @@ entry:
 
 ; 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 @@ entry:
 
 ; 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
index ab1ac2f27bc8..5305b7a1f534 100644
--- 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 dso_local void @strong_local_function() {
 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 at GOTOFF(%eax), %eax
@@ -223,3 +225,6 @@ define void()* @get_external_preemptable_function() {
 ; CHECK: movq external_preemptable_function at GOTPCREL(%rip), %rax
 ; STATIC: movl $external_preemptable_function, %eax
 ; CHECK32: movl external_preemptable_function at GOT(%eax), %eax
+
+; COMMON:     {{^}}strong_local_global:
+; COMMON-NEXT .Lstrong_local_global:


        


More information about the llvm-commits mailing list