<div dir="ltr">I'm a bit confused by some of the stuff in this thread, but rather than trying to puzzle all of that out, it might be simpler/more agreeable for me to say this:<br><br>We should never produce DWARF like this:<br><br>      DW_TAG_formal_parameter<br>             DW_AT_abstract_origin       (0x0000005a "bar")<br><br>(as Paul quoted from the DWARF spec - this should not be necessary/seems just like wasted bytes)<br><br>And locstats/dwarfdump statistics should not produce different results if it reads DWARF like that compared to DWARF missing this inlined instance entirely.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jan 27, 2021 at 7:26 AM Jeremy Morse <<a href="mailto:jeremy.morse.llvm@gmail.com">jeremy.morse.llvm@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
This was "[llvm-dev] [DebugInfo] The current status of debug values<br>
using multiple machine locations" but I don't want to de-rail Stephens<br>
thread,<br>
<br>
Paul wrote:<br>
> I'm not actually sure what causes variables to be dropped from the DWARF<br>
> entirely, as opposed to them existing but having an unknown location for<br>
> their entire scope; however, outside of our desire to use dwarfdump to<br>
> analyze our debug info it's simply more efficient to omit variables with no<br>
> location, since they inflate the debug info size and I don't believe<br>
> there's any practical value in having them.<br>
<br>
David wrote:<br>
> When does this ^ happen? In optimized builds we include all local variables<br>
> in a "variables" attachment to the DISubprogram, so we shouldn't be losing<br>
> variables entirely.<br>
> [...]<br>
> I think it's pretty important that we keep them. It helps a user understand<br>
> that they've not mistyped the name of a variable, etc [...]<br>
<br>
This is something that's bothered me for a while, as it messes with<br>
our statistics when changing how variable locations are tracked. Take<br>
this completely contrived C file:<br>
<br>
    int foo(int bar) {<br>
      int baz = 12 + bar;<br>
      return baz;<br>
    }<br>
<br>
    int qux(int quux) {<br>
      int xyzzy = foo(quux);<br>
      return xyzzy;<br>
    }<br>
<br>
Using clang ef0dcb50630 and options "-O3 -g -c", llvm-locstats reports<br>
the object file has five variables in it. If you emit LLVM-IR, and<br>
replace the first operand of all "llvm.dbg.value" intrinsic<br>
invocations with "undef" and compile the IR with llc, then<br>
llvm-locstats still reports five variables. However: if you instead<br>
/delete/ all the invocations of "llvm.dbg.value", four variables are<br>
reported by llvm-locstats. This indicates there's an observable<br>
difference in the way we represent optimised-out variables in DWARF.<br>
<br>
The difference between the object files is the way they represent the<br>
inlined copy of "foo", here's the output with undef dbg.values,<br>
followed by the output when I delete all the dbg.value intrinsics:<br>
<br>
     DW_TAG_inlined_subroutine<br>
       DW_AT_abstract_origin (0x0000004e "foo")<br>
       DW_AT_low_pc  (0x0000000000000010)<br>
       DW_AT_high_pc (0x0000000000000013)<br>
       DW_AT_call_file       ("/tmp/test.c")<br>
       DW_AT_call_line       (7)<br>
       DW_AT_call_column     (0x0f)<br>
<br>
       DW_TAG_formal_parameter<br>
             DW_AT_abstract_origin       (0x0000005a "bar")<br>
<br>
      NULL<br>
<br>
and:<br>
<br>
     DW_TAG_inlined_subroutine<br>
       DW_AT_abstract_origin (0x00000048 "foo")<br>
       DW_AT_low_pc  (0x0000000000000010)<br>
       DW_AT_high_pc (0x0000000000000013)<br>
       DW_AT_call_file       ("/tmp/test.c")<br>
       DW_AT_call_line       (7)<br>
       DW_AT_call_column     (0x0f)<br>
<br>
     NULL<br>
<br>
When there are dbg.value intrinsics present, then the inlined<br>
subroutine gets an empty DW_TAG_format_parameter that links back to<br>
the abstract origin. If there are no dbg.value intrinsics present, it<br>
does not. As far as I understand it, consumers can still determine<br>
that "bar" exists in the inlined subroutine by looking at the inlined<br>
subroutines abstract origin. This is what the "retained nodes"<br>
collection preserves.<br>
<br>
llvm-locstats / llvm-dwarfdump --statistics should probably be taught<br>
to look at the inlined subroutines abstract origin to find all<br>
variables, however, it seems unwise to have internal compiler state<br>
reflected in the output file in the way it is above. The cause of the<br>
empty DW_TAG_formal_parameter being created in<br>
DwarfDebug::collectEntityInfo [0] -- it distinguishes between a<br>
variable that has no location intrinsics, and a variable that has only<br>
empty location intrinsics. Putting a filter in to skip variables with<br>
only empty locations avoids the difference in output, and reduce the<br>
size of .debug_info on a stage2reldeb clang build by about 20Mb, or<br>
~1%.<br>
<br>
To ensure this email contains a question: would there be any<br>
objections to adding that filter, and obliging consumers to look in<br>
the inlined subroutines abstract origin to find optimised-out<br>
variables, instead of giving them a list per-inlined-instance?<br>
<br>
[0] <a href="https://github.com/llvm/llvm-project/blob/70e251497c4e26f8cfd85e745459afff97c909ce/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp#L1779" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/blob/70e251497c4e26f8cfd85e745459afff97c909ce/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp#L1779</a><br>
<br>
--<br>
Thanks,<br>
Jeremy<br>
</blockquote></div>