1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[InstrProfiling] Use !associated metadata for counters, data and values

C identifier name input sections such as __llvm_prf_* are GC roots so
they cannot be discarded. In LLD, the SHF_LINK_ORDER flag overrides the
C identifier name semantics.

The !associated metadata may be attached to a global object declaration
with a single argument that references another global object, and it
gets lowered to SHF_LINK_ORDER flag. When a function symbol is discarded
by the linker, setting up !associated metadata allows linker to discard
counters, data and values associated with that function symbol.

Note that !associated metadata is only supported by ELF, it does not have
any effect on non-ELF targets.

Differential Revision: https://reviews.llvm.org/D76802
This commit is contained in:
Petr Hosek 2019-07-13 14:02:07 -07:00
parent 019e9907bd
commit 62cf2a8725
8 changed files with 78 additions and 2 deletions

View File

@ -132,6 +132,9 @@ struct InstrProfOptions {
// Use BFI to guide register promotion
bool UseBFIInPromotion = false;
// Use !associated metadata to enable linker GC
bool CounterLinkOrder = false;
// Name of the profile file to use as output
std::string InstrProfileOutput;

View File

@ -83,6 +83,9 @@ private:
/// Returns true if profile counter update register promotion is enabled.
bool isCounterPromotionEnabled() const;
/// Returns true if the use of !associated metadata is enabled.
bool isCounterLinkOrderEnabled() const;
/// Count the number of instrumented value sites for the function.
void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins);

View File

@ -69,6 +69,11 @@ cl::opt<bool> RuntimeCounterRelocation(
cl::desc("Enable relocating counters at runtime."),
cl::init(false));
cl::opt<bool> CounterLinkOrder(
"counter-link-order",
cl::desc("Set counter associated metadata to enable garbage collection at link time."),
cl::init(false));
cl::opt<bool> ValueProfileStaticAlloc(
"vp-static-alloc",
cl::desc("Do static counter allocation for value profiler"),
@ -479,6 +484,13 @@ bool InstrProfiling::isCounterPromotionEnabled() const {
return Options.DoCounterPromotion;
}
bool InstrProfiling::isCounterLinkOrderEnabled() const {
if (CounterLinkOrder.getNumOccurrences() > 0)
return CounterLinkOrder;
return Options.CounterLinkOrder;
}
void InstrProfiling::promoteCounterLoadStores(Function *F) {
if (!isCounterPromotionEnabled())
return;
@ -850,6 +862,12 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
CounterPtr->setAlignment(Align(8));
MaybeSetComdat(CounterPtr);
CounterPtr->setLinkage(Linkage);
// We need a self-link for the counter variable because the ELF section name
// (that is __llvm_prf_cnts) is a C identifier and considered a GC root in the
// absence of the SHF_LINK_ORDER flag.
if (isCounterLinkOrderEnabled())
CounterPtr->setMetadata(LLVMContext::MD_associated,
MDNode::get(Ctx, ValueAsMetadata::get(Fn)));
auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
// Allocate statically the array of pointers to value profile nodes for
@ -871,6 +889,10 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
ValuesVar->setAlignment(Align(8));
MaybeSetComdat(ValuesVar);
if (isCounterLinkOrderEnabled())
ValuesVar->setMetadata(
LLVMContext::MD_associated,
MDNode::get(Ctx, ValueAsMetadata::get(CounterPtr)));
ValuesPtrExpr =
ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
}
@ -905,6 +927,9 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
Data->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT));
MaybeSetComdat(Data);
Data->setLinkage(Linkage);
if (isCounterLinkOrderEnabled())
Data->setMetadata(LLVMContext::MD_associated,
MDNode::get(Ctx, ValueAsMetadata::get(CounterPtr)));
PD.RegionCounters = CounterPtr;
PD.DataVar = Data;

View File

@ -11,6 +11,7 @@
; RUN: opt < %s -mtriple=mips64-unknown-linux -instrprof -vp-static-alloc=true -S | FileCheck %s --check-prefix=STATIC-SEXT
; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -vp-static-alloc=false -instrprof -S | FileCheck %s --check-prefix=DYN
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -vp-static-alloc=false -S | FileCheck %s --check-prefix=DYN
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -counter-link-order -vp-static-alloc=true -S | FileCheck %s --check-prefix=METADATA
@__profn_foo = private constant [3 x i8] c"foo"
@ -57,3 +58,12 @@ attributes #0 = { nounwind }
; STATIC: declare void @__llvm_profile_instrument_target(i64, i8*, i32)
; STATIC-EXT: declare void @__llvm_profile_instrument_target(i64, i8*, i32 zeroext)
; STATIC-SEXT: declare void @__llvm_profile_instrument_target(i64, i8*, i32 signext)
; METADATA: @__profc_foo = private global [1 x i64] zeroinitializer, section "{{[^"]+}}", align 8, !associated !0
; METADATA: @__profvp_foo = private global [1 x i64] zeroinitializer, section "{{[^"]+}}", align 8, !associated !1
; METADATA: @__profc_bar = private global [1 x i64] zeroinitializer, section "{{[^"]+}}", comdat($__profd_bar), align 8, !associated !2
; METADATA: @__profvp_bar = private global [1 x i64] zeroinitializer, section "{{[^"]+}}", comdat($__profd_bar), align 8, !associated !3
; METADATA: !0 = !{i32 (i32 ()*)* @foo}
; METADATA: !1 = !{[1 x i64]* @__profc_foo}
; METADATA: !2 = !{i32 (i32 ()*)* @bar}
; METADATA: !3 = !{[1 x i64]* @__profc_bar}

View File

@ -8,6 +8,8 @@
; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -S | FileCheck %s --check-prefixes=POSIX,LINUX
; RUN: opt < %s -mtriple=x86_64-unknown-fuchsia -passes=instrprof -S | FileCheck %s --check-prefixes=POSIX,LINUX
; RUN: opt < %s -mtriple=x86_64-pc-win32-coff -passes=instrprof -S | FileCheck %s --check-prefixes=COFF
; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -counter-link-order -S | FileCheck %s --check-prefixes=LINUX,POSIX,METADATA
; RUN: opt < %s -mtriple=x86_64-unknown-linux -passes=instrprof -counter-link-order -S | FileCheck %s --check-prefixes=LINUX,POSIX,METADATA
; MACHO: @__llvm_profile_runtime = external global i32
; LINUX-NOT: @__llvm_profile_runtime = external global i32
@ -19,7 +21,9 @@
@__profn_foo_extern = linkonce_odr hidden constant [10 x i8] c"foo_extern"
; POSIX: @__profc_foo = hidden global
; METADATA-SAME: !associated !0
; POSIX: @__profd_foo = hidden global
; METADATA-SAME: !associated !1
; COFF: @__profc_foo = internal global
; COFF-NOT: comdat
; COFF: @__profd_foo = internal global
@ -29,7 +33,9 @@ define void @foo() {
}
; POSIX: @__profc_foo_weak = weak hidden global
; METADATA: !associated !2
; POSIX: @__profd_foo_weak = weak hidden global
; METADATA: !associated !3
; COFF: @__profc_foo_weak = internal global
; COFF: @__profd_foo_weak = internal global
define weak void @foo_weak() {
@ -38,7 +44,9 @@ define weak void @foo_weak() {
}
; POSIX: @"__profc_linkage.ll:foo_internal" = internal global
; METADATA-SAME: !associated !4
; POSIX: @"__profd_linkage.ll:foo_internal" = internal global
; METADATA-SAME: !associated !5
; COFF: @"__profc_linkage.ll:foo_internal" = internal global
; COFF: @"__profd_linkage.ll:foo_internal" = internal global
define internal void @foo_internal() {
@ -47,7 +55,9 @@ define internal void @foo_internal() {
}
; POSIX: @__profc_foo_inline = linkonce_odr hidden global
; METADATA-SAME: !associated !6
; POSIX: @__profd_foo_inline = linkonce_odr hidden global
; METADATA-SAME: !associated !7
; COFF: @__profc_foo_inline = internal global{{.*}} section ".lprfc$M", align 8
; COFF: @__profd_foo_inline = internal global{{.*}} section ".lprfd$M", align 8
define linkonce_odr void @foo_inline() {
@ -56,7 +66,9 @@ define linkonce_odr void @foo_inline() {
}
; LINUX: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_cnts", comdat($__profd_foo_extern), align 8
; METADATA-SAME: !associated !8
; LINUX: @__profd_foo_extern = linkonce_odr hidden global {{.*}}section "__llvm_prf_data", comdat, align 8
; METADATA-SAME: !associated !9
; MACHO: @__profc_foo_extern = linkonce_odr hidden global
; MACHO: @__profd_foo_extern = linkonce_odr hidden global
; COFF: @__profc_foo_extern = linkonce_odr hidden global {{.*}}section ".lprfc$M", comdat, align 8
@ -75,3 +87,14 @@ declare void @llvm.instrprof.increment(i8*, i64, i32, i32)
; COFF: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} comdat {
; LINUX-NOT: define linkonce_odr hidden i32 @__llvm_profile_runtime_user() {{.*}} {
; LINUX-NOT: %[[REG:.*]] = load i32, i32* @__llvm_profile_runtime
; METADATA: !0 = !{void ()* @foo}
; METADATA: !1 = !{[1 x i64]* @__profc_foo}
; METADATA: !2 = !{void ()* @foo_weak}
; METADATA: !3 = !{[1 x i64]* @__profc_foo_weak}
; METADATA: !4 = !{void ()* @foo_internal}
; METADATA: !5 = !{[1 x i64]* @"__profc_linkage.ll:foo_internal"}
; METADATA: !6 = !{void ()* @foo_inline}
; METADATA: !7 = !{[1 x i64]* @__profc_foo_inline}
; METADATA: !8 = !{void ()* @foo_extern}
; METADATA: !9 = !{[1 x i64]* @__profc_foo_extern}

View File

@ -0,0 +1,12 @@
; RUN: opt < %s -pgo-instr-gen -instrprof -counter-link-order -S | FileCheck %s
; RUN: opt < %s -passes=pgo-instr-gen,instrprof -counter-link-order -S | FileCheck %s
; CHECK: @__profc_foo = private global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8, !associated !0
; CHECK: @__profd_foo = private global {{.*}}, section "__llvm_prf_data", align 8, !associated !1
define void @foo() {
ret void
}
; CHECK: !0 = !{void ()* @foo}
; CHECK: !1 = !{[1 x i64]* @__profc_foo}

View File

@ -60,7 +60,7 @@ bb12: ; preds = %bb9
; ATOMIC_PROMO: atomicrmw add {{.*}} @__profc_foo{{.*}}0), i64 %[[LIVEOUT1]] seq_cst
; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}1), i64 %[[LIVEOUT2]] seq_cst
; ATOMIC_PROMO-NEXT: atomicrmw add {{.*}} @__profc_foo{{.*}}2), i64 %[[LIVEOUT3]] seq_cst
; PROMO-NOT: @__profc_foo
; PROMO-NOT: @__profc_foo{{.*}})
}

View File

@ -69,7 +69,7 @@ bb15_0: ; preds = %bb11
; PROMO-NEXT: %pgocount{{.*}} = load {{.*}} @__profc_foo{{.*}} 4)
; PROMO-NEXT: add
; PROMO-NEXT: store {{.*}}@__profc_foo{{.*}}4)
; PROMO-NOT: @__profc_foo
; PROMO-NOT: @__profc_foo{{.*}})
bb15: ; preds = %bb14, %bb4