diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -589,7 +589,7 @@ void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) { assert(MO.isGlobal() && "caller should check MO.isGlobal"); - getSymbol(MO.getGlobal())->print(OS, MAI); + getSymbolPreferLocal(*MO.getGlobal())->print(OS, MAI); printOffset(MO.getOffset(), OS); } diff --git a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp --- a/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp +++ b/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp @@ -39,7 +39,7 @@ unsigned TargetFlags = MO.getTargetFlags(); const Triple &TheTriple = Printer.TM.getTargetTriple(); if (!TheTriple.isOSBinFormatCOFF()) - return Printer.getSymbol(GV); + return Printer.getSymbolPreferLocal(*GV); assert(TheTriple.isOSWindows() && "Windows is the only supported COFF target"); diff --git a/llvm/test/CodeGen/AArch64/basic-pic.ll b/llvm/test/CodeGen/AArch64/basic-pic.ll --- a/llvm/test/CodeGen/AArch64/basic-pic.ll +++ b/llvm/test/CodeGen/AArch64/basic-pic.ll @@ -22,33 +22,3 @@ ret i32* @var } - -@hiddenvar = hidden global i32 0 - -define i32 @get_hiddenvar() { -; CHECK-LABEL: get_hiddenvar: - - %val = load i32, i32* @hiddenvar -; CHECK: adrp x[[HI:[0-9]+]], hiddenvar -; CHECK: ldr w0, [x[[HI]], :lo12:hiddenvar] - - ret i32 %val -} - -define i32* @get_hiddenvaraddr() { -; CHECK-LABEL: get_hiddenvaraddr: - - %val = load i32, i32* @hiddenvar -; CHECK: adrp [[HI:x[0-9]+]], hiddenvar -; CHECK: add x0, [[HI]], :lo12:hiddenvar - - ret i32* @hiddenvar -} - -define void()* @get_func() { -; CHECK-LABEL: get_func: - - ret void()* bitcast(void()*()* @get_func to void()*) -; CHECK: adrp x[[GOTHI:[0-9]+]], :got:get_func -; CHECK: ldr x0, [x[[GOTHI]], :got_lo12:get_func] -} diff --git a/llvm/test/CodeGen/AArch64/elf-globals-static.ll b/llvm/test/CodeGen/AArch64/elf-globals-static.ll --- a/llvm/test/CodeGen/AArch64/elf-globals-static.ll +++ b/llvm/test/CodeGen/AArch64/elf-globals-static.ll @@ -78,16 +78,6 @@ ; CHECK-FAST: add x0, [[HIREG]], :lo12:var64 } -@hiddenvar = hidden global i32 0, align 4 -@protectedvar = protected global i32 0, align 4 - -define i32 @test_vis() { - %lhs = load i32, i32* @hiddenvar, align 4 - %rhs = load i32, i32* @protectedvar, align 4 - %ret = add i32 %lhs, %rhs - ret i32 %ret -} - @var_default = external dso_local global [2 x i32] define i32 @test_default_align() { diff --git a/llvm/test/CodeGen/AArch64/elf-preemption.ll b/llvm/test/CodeGen/AArch64/elf-preemption.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/elf-preemption.ll @@ -0,0 +1,114 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64 -relocation-model=static < %s | FileCheck %s --check-prefixes=CHECK,STATIC +; RUN: llc -mtriple=aarch64 -relocation-model=pic < %s | FileCheck %s --check-prefixes=CHECK,PIC + +@preemptable_var = dso_preemptable global i32 42 +define i32* @get_preemptable_var() nounwind { +; CHECK-LABEL: get_preemptable_var: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, :got:preemptable_var +; CHECK-NEXT: ldr x0, [x0, :got_lo12:preemptable_var] +; CHECK-NEXT: ret + ret i32* @preemptable_var +} + +@dsolocal_var = dso_local global i32 42 +define i32* @get_dsolocal_var() nounwind { +; STATIC-LABEL: get_dsolocal_var: +; STATIC: // %bb.0: +; STATIC-NEXT: adrp x0, dsolocal_var +; STATIC-NEXT: add x0, x0, :lo12:dsolocal_var +; STATIC-NEXT: ret +; +; PIC-LABEL: get_dsolocal_var: +; PIC: // %bb.0: +; PIC-NEXT: adrp x0, .Ldsolocal_var$local +; PIC-NEXT: add x0, x0, :lo12:.Ldsolocal_var$local +; PIC-NEXT: ret + ret i32* @dsolocal_var +} + +@weak_dsolocal_var = weak dso_local global i32 42 +define i32* @get_weak_dsolocal_var() nounwind { +; CHECK-LABEL: get_weak_dsolocal_var: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, weak_dsolocal_var +; CHECK-NEXT: add x0, x0, :lo12:weak_dsolocal_var +; CHECK-NEXT: ret + ret i32* @weak_dsolocal_var +} + +@hidden_var = hidden global i32 42 +define i32* @get_hidden_var() nounwind { +; CHECK-LABEL: get_hidden_var: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, hidden_var +; CHECK-NEXT: add x0, x0, :lo12:hidden_var +; CHECK-NEXT: ret + ret i32* @hidden_var +} + +@protected_var = protected global i32 42 +define i32* @get_protected_var() nounwind { +; CHECK-LABEL: get_protected_var: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, protected_var +; CHECK-NEXT: add x0, x0, :lo12:protected_var +; CHECK-NEXT: ret + ret i32* @protected_var +} + +define dso_preemptable void()* @preemptable_func() nounwind { +; CHECK-LABEL: preemptable_func: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, :got:preemptable_func +; CHECK-NEXT: ldr x0, [x0, :got_lo12:preemptable_func] +; CHECK-NEXT: ret + ret void()* bitcast(void()*()* @preemptable_func to void()*) +} + +define dso_local void()* @dsolocal_func() nounwind { +; STATIC-LABEL: dsolocal_func: +; STATIC: // %bb.0: +; STATIC-NEXT: adrp x0, dsolocal_func +; STATIC-NEXT: add x0, x0, :lo12:dsolocal_func +; STATIC-NEXT: ret +; +; PIC-LABEL: dsolocal_func: +; PIC: .Ldsolocal_func$local: +; PIC-NEXT: // %bb.0: +; PIC-NEXT: adrp x0, .Ldsolocal_func$local +; PIC-NEXT: add x0, x0, :lo12:.Ldsolocal_func$local +; PIC-NEXT: ret + ret void()* bitcast(void()*()* @dsolocal_func to void()*) +} + +define weak dso_local void()* @weak_dsolocal_func() nounwind { +; CHECK-LABEL: weak_dsolocal_func: +; CHECK: // %bb.0: +; CHECK-NEXT: adrp x0, weak_dsolocal_func +; CHECK-NEXT: add x0, x0, :lo12:weak_dsolocal_func +; CHECK-NEXT: ret + ret void()* bitcast(void()*()* @weak_dsolocal_func to void()*) +} + +;; bl .Ldsolocal_func$local either resolves to a constant at assembly time +;; or produces a relocation which can potentially cause a veneer. +define dso_local void @call_dsolocal_func() nounwind { +; STATIC-LABEL: call_dsolocal_func: +; STATIC: // %bb.0: +; STATIC-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; STATIC-NEXT: bl dsolocal_func +; STATIC-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; STATIC-NEXT: ret +; +; PIC-LABEL: call_dsolocal_func: +; PIC: .Lcall_dsolocal_func$local: +; PIC-NEXT: // %bb.0: +; PIC-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PIC-NEXT: bl .Ldsolocal_func$local +; PIC-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PIC-NEXT: ret + call void()* @dsolocal_func() + ret void +} diff --git a/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll b/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/semantic-interposition-asm.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64 -relocation-model=pic < %s | FileCheck %s + +;; Test that we use the local alias for dso_local globals in inline assembly. + +@gv0 = dso_local global i32 0 +@gv1 = dso_preemptable global i32 1 + +define i32 @load() nounwind { +; CHECK-LABEL: load: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: //APP +; CHECK-NEXT: adrp x0, .Lgv0$local +; CHECK-NEXT: ldr w0, [x0, :lo12:.Lgv0$local] +; CHECK-NEXT: adrp x8, gv1 +; CHECK-NEXT: ldr w8, [x8, :lo12:gv1] +; CHECK-NEXT: add x0, x8, x0 +; CHECK-NEXT: //NO_APP +; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 asm "adrp $0, $1\0Aldr ${0:w}, [$0, :lo12:$1]\0Aadrp x8, $2\0Aldr w8, [x8, :lo12:$2]\0Aadd $0,x8,$0", "=r,S,S,~{x8}"(i32* nonnull @gv0, i32* nonnull @gv1) + %conv = trunc i64 %0 to i32 + ret i32 %conv +}