Paul Kirth f2916becc5 Reland [pgo] Avoid introducing relocations by using private alias
In many cases, we can use an alias to avoid a symbolic relocations,
instead of using the public, interposable symbol. When the instrumented
function is in a COMDAT, we can use a hidden alias, and still avoid
references to discarded sections.

Previous versions of this patch allowed the compiler to name the
generated alias, but that would only be valid when the functions were
local. Since the alias may be used across TUs we use a more
deterministic naming convention, and add a ".local" suffix to the alias
name just as we do for relative vtables aliases.

https://reviews.llvm.org/rG20894a478da224bdd69c91a22a5175b28bc08ed9
removed an incorrect assertion on Mach-O which caused assertion failures in LLD.

We prevent duplicate symbols under ThinLTO + PGO + CFI by disabling
alias generation when the target function has MD_type metadata used in
CFI.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D137982
2023-01-25 22:19:19 +00:00

61 lines
3.1 KiB
LLVM

;; Test comdat functions.
; RUN: opt < %s -mtriple=x86_64-linux -passes=pgo-instr-gen,instrprof -S | FileCheck %s --check-prefixes=ELF
; RUN: opt < %s -mtriple=x86_64-windows -passes=pgo-instr-gen,instrprof -S | FileCheck %s --check-prefixes=COFF
$linkonceodr = comdat any
$weakodr = comdat any
$weak = comdat any
$linkonce = comdat any
;; profc/profd have hash suffixes. This definition doesn't have value profiling,
;; so definitions with the same name in other modules must have the same CFG and
;; cannot have value profiling, either. profd can be made private for ELF.
; ELF: @__profc_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8
; ELF: @__profd_linkonceodr.[[#]] = private global {{.*}} comdat($__profc_linkonceodr.[[#]]), align 8
; COFF: @__profc_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8
; COFF: @__profd_linkonceodr.[[#]] = linkonce_odr hidden global {{.*}} comdat, align 8
define linkonce_odr void @linkonceodr() comdat {
ret void
}
;; weakodr in a comdat is not renamed. There is no guarantee that definitions in
;; other modules don't have value profiling. profd should be conservatively
;; non-private to prevent a caller from referencing a non-prevailing profd,
;; causing a linker error.
; ELF: @__profc_weakodr = weak_odr hidden global {{.*}} comdat, align 8
; ELF: @__profd_weakodr = weak_odr hidden global {{.*}} comdat($__profc_weakodr), align 8
; COFF: @__profc_weakodr = weak_odr hidden global {{.*}} comdat, align 8
; COFF: @__profd_weakodr = weak_odr hidden global {{.*}} comdat, align 8
define weak_odr void @weakodr() comdat {
ret void
}
;; weak in a comdat is not renamed. There is no guarantee that definitions in
;; other modules don't have value profiling. profd should be conservatively
;; non-private to prevent a caller from referencing a non-prevailing profd,
;; causing a linker error.
; ELF: @__profc_weak = weak hidden global {{.*}} comdat, align 8
; ELF: @__profd_weak = weak hidden global {{.*}} comdat($__profc_weak), align 8
; COFF: @__profc_weak = weak hidden global {{.*}} comdat, align 8
; COFF: @__profd_weak = weak hidden global {{.*}} comdat, align 8
define weak void @weak() comdat {
ret void
}
;; profc/profd have hash suffixes. This definition doesn't have value profiling,
;; so definitions with the same name in other modules must have the same CFG and
;; cannot have value profiling, either. profd can be made private for ELF.
; ELF: @__profc_linkonce.[[#]] = linkonce hidden global {{.*}} comdat, align 8
; ELF: @__profd_linkonce.[[#]] = private global {{.*}} comdat($__profc_linkonce.[[#]]), align 8
; COFF: @__profc_linkonce.[[#]] = linkonce hidden global {{.*}} comdat, align 8
; COFF: @__profd_linkonce.[[#]] = linkonce hidden global {{.*}} comdat, align 8
define linkonce void @linkonce() comdat {
ret void
}
; Check that comdat aliases are hidden for all linkage types
; ELF: @linkonceodr.local = linkonce_odr hidden alias void (), ptr @linkonceodr
; ELF: @weakodr.local = weak_odr hidden alias void (), ptr @weakodr
; ELF: @weak.local = weak hidden alias void (), ptr @weak
; ELF: @linkonce.local = linkonce hidden alias void (), ptr @linkonce