[llvm] [LLVM][DWARF] Make some effort to avoid duplicates in .debug_ranges. (PR #106614)
David Blaikie via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 30 10:47:56 PDT 2024
dwblaikie wrote:
OOh, I'm with you now. I thought you meant repetition within a range list, but I see you mean two range lists with identical entries - because one instruction remaining after inlining is 3 inlines deep, so each of the inlines share the same list of instructions (ie: f1 calls inline f2 calls inline f3 calls f4 - but f2 doesn't have any unique instructions, its own instructions are those in the inlined f3).
Yeah, not too hard to reproduce - but requires a small amount of manual IR editing (or requires more quirks in the test case to force instruction reordering - honestly it's probably easier/clearer with the manual IR editing).
eg:
```
void f1();
inline void f2() {
f1();
f1();
}
inline void f3() {
f2();
}
void f4() {
f3();
f1();
}
```
Compile that with debug info and optimizations to IR (so all the inlining has already happened), then move the second `f1` call after the 3rd, causing the inlining to be split into ranges.
The resulting DWARF looks something like this:
```
0x00000031: DW_TAG_subprogram
DW_AT_low_pc (0x0000000000000000)
DW_AT_high_pc (0x0000000000000011)
DW_AT_frame_base (DW_OP_reg7 RSP)
DW_AT_call_all_calls (true)
DW_AT_linkage_name ("_Z2f4v")
DW_AT_name ("f4")
DW_AT_decl_file ("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_decl_line (9)
DW_AT_external (true)
0x0000003d: DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x0000002c "_Z2f3v")
DW_AT_ranges (indexed (0x0) rangelist = 0x00000014
[0x0000000000000001, 0x0000000000000006)
[0x000000000000000b, 0x0000000000000011))
DW_AT_call_file ("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_call_line (10)
DW_AT_call_column (3)
0x00000046: DW_TAG_inlined_subroutine
DW_AT_abstract_origin (0x00000027 "_Z2f2v")
DW_AT_ranges (indexed (0x1) rangelist = 0x0000001b
[0x0000000000000001, 0x0000000000000006)
[0x000000000000000b, 0x0000000000000011))
DW_AT_call_file ("/usr/local/google/home/blaikie/dev/scratch/test.cpp")
DW_AT_call_line (7)
DW_AT_call_column (3)
0x0000004f: NULL
```
And, yes, it'd be nice if the range lists could be shared rather than duplicated.
Not sure how I feel about special casing "just the last one" - yeah, I get that it's pretty effective/unlikely to miss much, but doesn't feel great/general/robust.
That said, down at this level, we're missing the context that these lists basically won't be reused between functions - we could try to deduplicate only at the function level, so we wouldn't have a map full of range lists that would never be used again.
The place to initialize/clear this list would probably be in DwarfCompileUnit::constructSubprogramScopeDIE - then it could be checked/inserted into in addScopeRangeList, maybe. (or maybe we'd want a version of that function that does the map lookup/etc and a version that doesn't (for use with CU ranges only... hmm, actually, I guess there's no reason they couldn't be reused too - if the CU had only one function, but that function used BB sections, then you could end up with a range list at the CU, subprogram, and inlined subroutine ranges that all could be shared))
Hrm :/ I guess then it'd still be a subprogram-local map, and maybe just a special case for the CU that could handle just that one case (does the CU contain a single range-located subprogram, if so, use that range list). So probably not worth trying to make that work - since it'd be such a special case and it likely wouldn't account for much debug info anyway.
So I'd guess having a map that's initialized at constructSubprogramScopeDIE and cleared at the end of it would probably be adequate.
Open to other ideas, though - perhaps other folks agree it's not worth the effort to build something that general when basically the only way this happens is as we're walking the tree (hmm, which way does this happen - on the way down the tree of scopes, or the way up? does that impact how effective the "last scope matches" technique is? perhaps not... )
You mentioned this technique eliminates "99.99% of the duplicates" - is that an actual number, or a rough estimate? Do you have an example where this technique doesn't catch a duplicate?
https://github.com/llvm/llvm-project/pull/106614
More information about the llvm-commits
mailing list