[PATCH] D70121: [DebugInfo][LDV] Teach LDV how to identify source variables and handle fragments

Orlando Cazalet-Hyams via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 30 08:23:18 PST 2020


Orlando added a comment.

@vsk this is the situation as far as I understand it. I appreciate that this is
a lot of text; there is a summary at the end. I hope this helps.

> Apologies, I'm not up-to-date on this patch and would appreciate some
>  clarification / a few short examples of what overlapping fragments are.  Is it
>  when you have adjacent dbg.value / DBG_VALUEs, s.t. there is some overlap in
>  the bits they describe?

Yes, except adjacency is not part of that relationship.

  Example 5
  DBG_VALUE %0, $noreg, "x", DIExpression() ; DV1
  ...
  DBG_VALUE %0, $noreg, "y", DIExpression(DW_OP_LLVM_fragment 0 16) ; DV2
  ...
  DBG_VALUE %1, $noreg, "x", DIExpression() ; DV3 
  ...
  DBG_VALUE %0, $noreg, "y", DIExpression(DW_OP_LLVM_fragment 8 8)  ; DV4

DV1, DV3, have fully overlapping fragments.  DV2 and DV4 have partially
overlapping fragments.

So, in your example 4 the first and last DBG_VALUEs partially overlap.

> are these valid examples?



  Example 1: Correct - I will explicitly state "full overlap" if I must refer
             to this case.  
  Example 2: Correct.
  Example 3: Correct.
  Example 4: Not quite, that's still a partial overlap. See above.

> I'm fuzzy on the definition here so apologies for the probably naive question,
>  but: why are overlaps a problem?

Having to consider fragment overlaps complicates value liveness queries for any
particular bits of a source variable. 'value' here refers to the combination of
a location (e.g. vreg, const) and DIExpression (because this may add a modifier
to the location).

> Would you mind following up on the review for D71478 <https://reviews.llvm.org/D71478> describing what it's
>  missing?

Ah, looking closely at D71478 <https://reviews.llvm.org/D71478> the pass will never produce wrong debuginfo. It
doesn't remove any dbg.values which _may overlap_ by ignoring the fragment part.
It takes a conservative approach, but this has no effect on the final debuginfo
so it turns out it isn't a very compelling example.

In the Example 6 below it would be safe to remove DV3, but the pass
implemented in D71478 <https://reviews.llvm.org/D71478> will not currently do so because DV3 and DV2 _may
overlap_.

  Example 6
  dbg.value %1, "x", Fragment(0, 16) ; DV1
  ...
  dbg.value %2, "x", Fragment(16, 16) ; DV2
  ...
  dbg.value %1, "x", Fragment(0, 16) ; DV3

> why are overlaps a problem? (continued)

LiveDebugVariables (LDV) removes DBG_VALUEs before regalloc and reinserts after.
It cannot afford to be so conservative because this reduces coverage. Before I
explain this I have to show you what is wrong with LDV currently.

LDV uses interval maps to explicitly represent the intervals that the removed
DBG_VALUEs implicitly described. The DBG_VALUEs are filtered into an interval
map based on their { Source Variable, DIExpression }. The interval map will
coalesce adjacent entries that use the same location.

Consider (interval maps before coalescing on the left):

  Example 7
  +------------DBG_VALUE %0, $noreg, "x", DIExpression() ; DV1
  |            ...
  |       +----DBG_VALUE %1, $noreg, "x", DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value) ; DV2
  |       |    ...    
  +-------|----DBG_VALUE %0, $noreg, "x", DIExpression() ; DV3
  |       |
  DV1(%0) DV2(%1)
  DV3(%0)

This approach generates incorrect debuginfo. The interval map coalesces DV3 into
DV1 because they use the same location.

Taking the same approach as D71478 <https://reviews.llvm.org/D71478> and filtering only on { Source Variable }
would fix the bug described above but also may greatly reduce coverage. For
example:

  Example 8
  +----DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 8) ; DV1
  |    ...
  +----DBG_VALUE %1, "x", (DW_OP_LLVM_fragment 8 8) ; DV2
  |  
  +----DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 8) ; DV3
  |
  DV1(%0)
  DV2(%1)
  DV3(%0)

In Example 8 DV3 is not coalesced into DV1. Imagine that regalloc wants to
spill %0:

  Example 9
  +----DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 8) ; DV1
  |    ...
  +----DBG_VALUE %1, "x", (DW_OP_LLVM_fragment 8 8) ; DV2
  |    <SPILL %0 into STACK0>
  +----DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 8) ; DV3
  |
  DV1(%0)
  DV2(%1) <----| %0 is not used in this interval in this map.
  DV3(%0)      | Really, DV2 should not be in this map.

Because the spill range isn't represented in the interval map we just lose that
coverage.

Patch D66415 <https://reviews.llvm.org/D66415> changes this so that the DBG_VALUEs are filtered into interval maps
based on { Source Variable, Fragment } and will coalesce adjacent entries that
use the same { Location, DIExpression }.

This method correctly handles fully overlapping fragments and non-overlapping
fragments of the same Source Variable and fixes case [0] and [1]. However, it
still produces incorrect debuginfo when presented with partially overlapping
fragments in much the same way:

  Example 10
  +-------------------DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 16) ; DV1
  |                   ...
  |              +----DBG_VALUE %1, "x", (DW_OP_LLVM_fragment 0 8)  ; DV2
  |              |    ...
  +--------------|----DBG_VALUE %0, "x", (DW_OP_LLVM_fragment 0 16) ; DV3
  |              |
  DV1(%0, Expr0) DV2(%1, Expr1)
  DV3(%0, Expr0)

DV2 will get filtered into a separate interval map and therefore DV3 and DV1
will be incorrectly coalesced.

So, the patch D66415 <https://reviews.llvm.org/D66415> may cause incorrect debuginfo, but in practice it is should
cause much less than the current implementation because we are more building more
accurate intervals for any given bits.

> ^ Sorry, I didn't quite parse this definition.

TL;DR The upper bound of DBG_VALUEs coming into LDV with partially overlapping
fragments in a clang 3.4 RelWithDebInfo build is around 0.00005%.

Summary and questions
---------------------

Partially overlapping fragments (between DBG_VALUEs) are allowed in IR and MIR
but they are not handled everywhere.  For a large C++ codebase I saw a
negligible number of partial overlaps coming into LiveDebugVariablesq.

This patch (in theory) fixes the problem of overlapping fragments for LDV. But
it is large and difficult to review, so:

1. Please can we accept a patch that looks like D66415 <https://reviews.llvm.org/D66415> (plus FIXME: overlaps)? It will produce incorrect debuginfo given partially overlapping fragments, but it is still strictly an improvement on the current implementation, fixes [0] and [1], and is far simpler than this patch which does handle partial overlaps.

My numbers are only anecdotal and there may be languages / situations which
necessitate partially overlapping fragments (e.g. C allows much more type
punning than C++). With this in mind:

2. It seems difficult to actually get clang to produce these pesky overlaps. Do you know of any cases where overlapping fragments in either IR or MIR are _required_ to produce correct debuginfo? Hypothetically, if it were feasible to ban partial overlaps, then D66415 <https://reviews.llvm.org/D66415> would be fully correct and it would be very easy to make D71478 <https://reviews.llvm.org/D71478> optimal.

Thanks,
Orlando

[0] https://bugs.llvm.org/show_bug.cgi?id=41992
[1] https://bugs.llvm.org/show_bug.cgi?id=43957


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70121/new/

https://reviews.llvm.org/D70121





More information about the llvm-commits mailing list