This is an archive of the discontinued LLVM Phabricator instance.

[InstrProf] Add support for dead_strip+live_support functionality
ClosedPublic

Authored by vsk on Oct 10 2016, 5:32 PM.

Details

Summary

On Darwin, marking a section as "regular,live_support" means that a
symbol in the section should only be kept live if it has a reference to
something that is live. Otherwise, the linker is free to dead-strip it.

Turn this functionality on for the __llvm_prf_data section.

This means that counters, names, and data associated with dead functions
will be removed from dead-stripped binaries. This will result in smaller
profiles and binaries, and should speed up profile collection.

Tested with check-profile, llvm-lit test/tools/llvm-{cov,profdata}, and
check-llvm.

Diff Detail

Repository
rL LLVM

Event Timeline

vsk updated this revision to Diff 74191.Oct 10 2016, 5:32 PM
vsk retitled this revision from to [InstrProf] Add support for dead_strip+live_support functionality.
vsk updated this object.
vsk added reviewers: davidxl, mehdi_amini.
vsk added a subscriber: llvm-commits.
mehdi_amini accepted this revision.Oct 10 2016, 9:04 PM
mehdi_amini edited edge metadata.

LGTM.

Are these symbols already in the "llvm.compiler_used" list?

This revision is now accepted and ready to land.Oct 10 2016, 9:04 PM
davidxl added inline comments.Oct 10 2016, 9:36 PM
include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

What is the exact meaning of this attribute? Does it mark the section 'not' the root of the reference graph (which allows symbols just referenced from this section to be GCed)?

Garbage collection for dead function (with profile instrumentation) is currently also broken on Linux because -fdata-sections is not honored by for prof data symbols.

mehdi_amini added inline comments.Oct 10 2016, 9:40 PM
include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

I see this section as "reversing" the edges in the dead-strip algorithm: if a symbol foo is in the live_support section, the linker will keep it alive if the symbols *referenced by* foo are live.
(Nothing is expected to reference foo).

vsk added a comment.Oct 10 2016, 9:49 PM

Are these symbols already in the "llvm.compiler_used" list?

No, contents of __llvm_prf_data are in llvm.used, which is a bit stricter. Actually, this is very unexpected.. is dead-stripping of live_support sections supposed to kick in for symbols in the llvm.used list? I only expect this to happen for the llvm.compiler_used list.

include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

This is better than my explanation, thanks Mehdi :).

It's true that symbols referenced by data in a "live_support" section may be GC'd, but it's only interesting the other way: if we could GC a symbol by not treating "live_support" uses as "critical", then we GC the symbol and its uses.

In D25456#566952, @vsk wrote:

Are these symbols already in the "llvm.compiler_used" list?

No, contents of __llvm_prf_data are in llvm.used, which is a bit stricter. Actually, this is very unexpected.. is dead-stripping of live_support sections supposed to kick in for symbols in the llvm.used list? I only expect this to happen for the llvm.compiler_used list.

Well, in theory we should use llvm.compiler_used, but by "chance" ld64 ignore the "no dead strip" attribute (that results from llvm.used) when doing the special processing for "live_support"

davidxl added inline comments.Oct 10 2016, 10:21 PM
include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

The reversing edge is a good way to explain it -- which has two effects:

  1. the references from the section is ignored
  2. if the section ends up referencing non or only dead symbols, it is dead too.

Note that all per-function prof data are put in the same section -- so the second effect won't kick in unless fdata-sections is effective too.

mehdi_amini added inline comments.Oct 10 2016, 10:26 PM
include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

On MachO, -fdata-sections -ffunction-sections can't be turned off (AFAIK) :)
Every symbol is an "atom", i.e. a node in the graph formed by all the symbols (nodes) in the program and their references (edges).

davidxl added inline comments.Oct 10 2016, 10:28 PM
include/llvm/ProfileData/InstrProf.h
58 ↗(On Diff #74191)

That is a nice feature.

davidxl accepted this revision.Oct 11 2016, 8:17 AM
davidxl edited edge metadata.

lgtm

This revision was automatically updated to reflect the committed changes.
MaskRay added subscribers: thakis, MaskRay.EditedMay 29 2021, 3:36 PM

I've made ELF GC work in https://reviews.llvm.org/D97585 and am trying D103372 which will make (to a large extent) Windows GC work.

My question is whether S_ATTR_LIVE_SUPPORT suppresses N_NO_DEAD_STRIP on Darwin.

% cat a.ll
@bar = external global void ()*, align 8

define void @foo() {
entry:
  %tmp = load void ()*, void ()** @bar, align 8
  call void %tmp()
  ret void
}
% opt -mtriple=x86_64-apple-darwin -passes=pgo-instr-gen,instrprof -S < a.ll | llc -mtriple=x86_64-apple-darwin -filetype=obj -function-sections -o a.o

l___profd_foo has N_NO_DEAD_STRIP (due to llvm.used) while its section has S_ATTR_LIVE_SUPPORT. Is N_NO_DEAD_STRIP ignored in this case?
If not the GC doesn't kick in.
@thakis may be interested in this for the ld64.lld -dead_strip implementation (D103324).

Herald added a project: Restricted Project. · View Herald TranscriptMay 29 2021, 3:36 PM

I've made ELF GC work in https://reviews.llvm.org/D97585 and am trying D103372 which will make (to a large extent) Windows GC work.

My question is whether S_ATTR_LIVE_SUPPORT suppresses N_NO_DEAD_STRIP on Darwin.

I thought I read somewhere that ld64 happens to ignore it…oh it was right here on this review: https://reviews.llvm.org/D25456#566954

lld doesn't ignore it in my implementation as that seems more semantically correct: Mach-O has a hierarchy of segment->section->"subsection" where the latter is associated with a symbol. N_NO_DEAD_STRIP is set on a symbol, so it feels like it's a more local concept that should win over the more global S_ATTR_LIVE_SUPPORT.

l___profd_foo has N_NO_DEAD_STRIP (due to llvm.used) while its section has S_ATTR_LIVE_SUPPORT. Is N_NO_DEAD_STRIP ignored in this case?
If not the GC doesn't kick in.

If we want l___profd_foo to be stripped, maybe we shouldn't mark it N_NO_DEAD_STRIP then?

@thakis may be interested in this for the ld64.lld -dead_strip implementation (D103324).

vsk added a comment.Jun 2 2021, 2:24 PM

If llvm stopped appending __profd_foo to llvm.compiler.used, there might not be anything left to prevent the optimizer from discarding it. The current scheme of having the linker ignore N_NO_DEAD_STRIP if S_ATTR_LIVE_SUPPORT is in effect seems like a neat way to solve the issue. Is there a tidy alternative?

In D25456#2794689, @vsk wrote:

If llvm stopped appending __profd_foo to llvm.compiler.used, there might not be anything left to prevent the optimizer from discarding it. The current scheme of having the linker ignore N_NO_DEAD_STRIP if S_ATTR_LIVE_SUPPORT is in effect seems like a neat way to solve the issue. Is there a tidy alternative?

Currently __profd_foo is in llvm.used instead of llvm.compiler.used on Mach-O.

D103372 My thought (but I don't have a device to test) is that Mach-O can use appendToCompilerUsed(*M, CompilerUsedVars); as well.

vsk added a comment.Jun 10 2021, 2:25 PM
In D25456#2794689, @vsk wrote:

If llvm stopped appending __profd_foo to llvm.compiler.used, there might not be anything left to prevent the optimizer from discarding it. The current scheme of having the linker ignore N_NO_DEAD_STRIP if S_ATTR_LIVE_SUPPORT is in effect seems like a neat way to solve the issue. Is there a tidy alternative?

Currently __profd_foo is in llvm.used instead of llvm.compiler.used on Mach-O.

D103372 My thought (but I don't have a device to test) is that Mach-O can use appendToCompilerUsed(*M, CompilerUsedVars); as well.

That's a good point: adding __profd_X to llvm.compiler.used should prevent llvm's optimizer from deleting it. But is it sufficient to guarantee that linker (ld64/lld.macho) optimizations will not delete it?