This is an archive of the discontinued LLVM Phabricator instance.

[InstrProf] Add Correlator class to read debug info
ClosedPublic

Authored by ellis on Nov 24 2021, 2:13 PM.

Details

Summary

Extend llvm-profdata to read in a .proflite file and also a debug info file to generate a normal .profdata profile. This reduces the binary size by 8.4% when building an instrumented Clang binary without value profiling (164 MB vs 179 MB).

This work is part of the "lightweight instrumentation" RFC: https://groups.google.com/g/llvm-dev/c/r03Z6JoN7d4

Diff Detail

Event Timeline

ellis created this revision.Nov 24 2021, 2:13 PM
ellis updated this revision to Diff 389625.Nov 24 2021, 3:06 PM

Fix build error.

ellis edited the summary of this revision. (Show Details)Nov 24 2021, 3:09 PM
ellis edited the summary of this revision. (Show Details)Nov 29 2021, 4:19 PM
ellis published this revision for review.Nov 29 2021, 5:06 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptNov 29 2021, 5:06 PM
Herald added subscribers: llvm-commits, Restricted Project. · View Herald Transcript
kyulee added inline comments.Nov 30 2021, 10:12 AM
llvm/lib/ProfileData/InstrProfCorrelator.cpp
91

It's nor blocking but it might be a more relevant error message when it fails for COFF -- not yet implemented or supported case.

155

It's concise to have it here but should we check this outside so that we don't need to come here after creating unnecessary DWARFDie?

162

IIRC, this die is attached to a function, so we try to get the function address from its parent?

183

My understanding is that FunctionName, CFGHash, and NumCounters are attached to this correlated die always under this flag.
Should we assert them instead? If they are null, I wonder what situation we might run into.

ellis updated this revision to Diff 390856.Nov 30 2021, 4:41 PM

Rebase.

ellis added inline comments.Nov 30 2021, 5:07 PM
llvm/lib/ProfileData/InstrProfCorrelator.cpp
155

I'm not sure how I would move this since it needs a DWARFDie to read the variable name.

162

The DIE we are looking at is assumed to be for a static variable (the probe). The parent DIE should be the function that owns the variable and that is the address we want.

183

isDIEOfProbe() only checks if the variable name starts with __profc_, so it's not unlikely that we run into this case. We could add the artificial flag or other attributes that make it more likely that this is a probe, then we could change this to an assert.

ellis updated this revision to Diff 390870.Nov 30 2021, 5:26 PM

Add more checks to isDIEOfProbe().

ellis updated this revision to Diff 391499.Dec 2 2021, 4:55 PM

Fix MachO case.

ellis planned changes to this revision.Dec 2 2021, 4:56 PM

I'm planning to improve MachO support by expanding .dSYMs. I also want to first refactor readRawCounts() in a separate diff.

(While I am happy to study/review lightweight instrumentation, I am out of town til Dec 11, so would not have time reading the patches. No need to wait for me :) )

ellis updated this revision to Diff 391781.Dec 3 2021, 5:00 PM

Expand .dSYM paths to their objects and add a separate test for MachO. Also a bit of refactoring.

Thanks for fixing MachO.
It appears there is still an issue but it seems in dwarflinker (dsymutil). As below with clang -g -mllvm -disable-vp=true -mllvm -debug-info-correlate=true -fprofile-generate -Oz -mllvm -disable-preinline, when the function is fully inlined, dsymutil seems to optimize this static data in the final dSYM.
I was trying to use -keep-function-for-static to keep this, but still has a missing location info (DW_AT_location) at dSYM, and thus we cannot correlate foo and thus miss the coverage for it.
But I think missing location info for the function static variables seems a known issue in dsymutil, and we may follow this up. cc @clayborg

static 
int foo() {
 return 1;
}
int main() {
 return foo();
}
llvm/lib/ProfileData/InstrProfCorrelator.cpp
37

Hmm. This code seems repeated 3 times in dwarfdump and gsymutil, and now here.
I think this helper might be moved to some dsym related support file. But certainly this can be followed up.

206

Die or ParentDie are references. Can they be null?

220

Can you add a high-level (example) dwarf layout for this function to match as the comment?

228

Can we use getLowAndHighPC or make one getLow?
I think 0 address (no existent of function address) is a valid case when the function is completely inlined (and thus the body is elided) -- only this static profile data remains.

llvm/lib/ProfileData/InstrProfReader.cpp
435

Can we set these value for Correlator once instead of overwriting them, which may be out-of-bound or invalid?
I guess DataSize and NameSize etc are 0, and we can assert these values under this flag.

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
956

I was thinking whether we need another INSTR_PROF_DATA or a similar one for DebugInfoCorrelate in the header and include them in order so that we can ensure sync these data in order in both a writer, here and a reader, correlateProfileDataImpl.

llvm/tools/llvm-profdata/llvm-profdata.cpp
151

Why is this moved? Is this relevant to this change?

ellis marked 8 inline comments as done.Dec 7 2021, 1:39 PM
ellis added inline comments.
llvm/lib/ProfileData/InstrProfCorrelator.cpp
37

Absolutely! I'll follow up in a separate diff.

206

DWARFDie has a bool operator that just calls .isValid(). It's probably safer and more clear to call .isValid() directly.

220

Good idea. I've added a comment in the header.

228

IIUC FunctionPtr is only used for value profiling to match callsite dispatches to their callees. If the function is completely inlined then there won't be value profiling for that callee.

I've changed this so that if we can't find an address then we emit a warning so we can investigate and possible fixup debug info. So for the .profdata file, an address of 0 means either "we can't find the address" or "the function is not concrete (it is inlined)".

llvm/lib/ProfileData/InstrProfReader.cpp
435

Yeah I've change this up a bit to only set them once. It's confusing because DataSize is zero but there is actual data in the Correlator.

llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
956

I don't think adding a macro in InstrProfData.inc is the right solution because it makes it unnecessary complicated and hard to read. IIUC the worry is that someone may change the writer and forget to change the reader. If this code is changed without the right reader change then the compiler-rt test will break and hopefully the change won't land. I would like to leave this how it is, but I'm open to discussion.

ellis updated this revision to Diff 392521.Dec 7 2021, 1:39 PM
ellis marked 4 inline comments as done.

Add requested changes.

This looks good to me. Given this works for ELF while having a minor issue with the fully inlined case for MachO, could you file a bug to follow this up?
I also let other folks review this code.

ellis added a comment.Dec 13 2021, 2:28 PM

This looks good to me. Given this works for ELF while having a minor issue with the fully inlined case for MachO, could you file a bug to follow this up?
I also let other folks review this code.

I believe the MachO bug is fixed by https://reviews.llvm.org/D115565
I'm not currently aware of any more bugs, but I'll file a bug report if I find them.

kyulee accepted this revision.Dec 13 2021, 2:31 PM
This revision is now accepted and ready to land.Dec 13 2021, 2:31 PM
ellis updated this revision to Diff 394098.Dec 13 2021, 5:43 PM

Rebase and test.

ellis updated this revision to Diff 394984.Dec 16 2021, 1:41 PM

Use findDsymObjectMembers() that was added in https://reviews.llvm.org/D115418

This revision was landed with ongoing or failed builds.Dec 16 2021, 3:18 PM
This revision was automatically updated to reflect the committed changes.