This is an archive of the discontinued LLVM Phabricator instance.

[SelectionDAG] Improve selection of DBG_VALUE using a PHI node result
ClosedPublic

Authored by bjope on Apr 26 2018, 9:16 AM.

Details

Summary

When building the selection DAG at ISel all PHI nodes are
selected and lowered to Machine Instruction PHI nodes before
we start to create any SDNodes. So there are no SDNodes for
values produced by the PHI nodes.

In the past when selecting a dbg.value intrinsic that uses
the value produced by a PHI node we have been handling such
dbg.value intrinsics as "dangling debug info". I.e. we have
not created a SDDbgValue node directly, because there is
no existing SDNode for the PHI result, instead we deferred
the creationg of a SDDbgValue until we found the first use
of the PHI result.

The old solution had a couple of flaws. The position of the
selected DBG_VALUE instruction would end up quite late in a
basic block, and for example not directly after the PHI node
as in the LLVM IR input. And in case there were no use at all
in the basic block the dbg.value could be dropped completely.

This patch introduces a new VREG kind of SDDbgValue nodes.
It is similar to a SDNODE kind of node, but it refers directly
to a virtual register and not a SDNode. When we do selection
for a dbg.value that is using the result of a PHI node we
can do a lookup of the virtual register directly (as it already
is determined for the PHI node) and create a SDDbgValue node
immediately instead of delaying the selection until we find a
use.

This should fix a problem with losing debug info at ISel
as seen in PR37234 (https://bugs.llvm.org/show_bug.cgi?id=37234).
It does not resolve PR37234 completely, because the debug info
is dropped later on in the BranchFolder instead.

Diff Detail

Repository
rL LLVM

Event Timeline

bjope created this revision.Apr 26 2018, 9:16 AM
bjope added inline comments.Apr 26 2018, 9:22 AM
test/DebugInfo/X86/sdag-dbgvalue-phi-use-2.ll
47 ↗(On Diff #144135)

This new test case actually expose another problem. It seems like the DBG_VALUE instructions sometimes are inserted before instead of after the SDNode that it is being associated with when building the selection DAG (at least for constants and these new phi-related nodes).

I'm thinking about looking into that later in a separate commit. This patch at least resurrects some earlier lost DBG_VALUE instructions, and puts them closer to their original position in the LLVM IR (even if they sometimes still are "off by one").

aprantl added inline comments.Apr 26 2018, 9:29 AM
lib/CodeGen/SelectionDAG/InstrEmitter.cpp
724 ↗(On Diff #144135)

Just to be sure: this does *not* allocate a new vreg, right?

test/DebugInfo/COFF/pieces.ll
46 ↗(On Diff #144135)

I'm having a hard time interpreting the assembler comment. Does this mean that the range of the DBG_VALUE get's immediately terminated by the assignment to edi, or does that mean "starting with the assignment"?

bjope added inline comments.Apr 26 2018, 12:08 PM
test/DebugInfo/COFF/pieces.ll
46 ↗(On Diff #144135)

The original loop in C looks like this (at least according to the comment in the test case, I've not regenerated it from C since it is an old test case):

;   for (i = 0; i < n; i++) {
;     o.x = g(o.x);
;     o.y = g(o.y);
;   }
;   return o.x + o.y;

Without the patch we get this kind of structure in the loop body:

ox_start:
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi
  o.x = g(o.x);
oy_start:
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi
  o.y = g(o.y);
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi
oy_end:

after the patch we get

ox_oy_start:
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi
  o.x = g(o.x);
ox_start:
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 0 32] $edi
  o.y = g(o.y);
oy_start:
  #DEBUG_VALUE: loop_csr:o <- [DW_OP_LLVM_fragment 32 32] $esi
oy_end:

So the difference is basically that we now track "o.y" also for the first part of the loop body. That should be an improvement!

Perhaps I should rename ox_start as ox_restart, and oy_start as oy_restart, to indicate that those labels indicate where a new live range starts for the DEBUG_VALUEs (after the updates of o.x and o.y)? Or we could just call them LBL1, LBL2, LBL3 and LBL4.

aprantl accepted this revision.Apr 26 2018, 12:44 PM

Thanks for the explanation!

lib/CodeGen/SelectionDAG/SelectionDAG.cpp
7313 ↗(On Diff #144135)

dangling comment?

This revision is now accepted and ready to land.Apr 26 2018, 12:44 PM
rnk added a subscriber: rnk.Apr 26 2018, 4:31 PM
rnk added inline comments.
test/DebugInfo/COFF/pieces.ll
46 ↗(On Diff #144135)

I believe your analysis is correct! This is great, I was really annoyed that we didn't track o.y for the first part of the loop when I wrote this test case initially. I used it for a demo and I had to carefully put my breakpoint on the loop backedge so that both parts would show up in the debugger.

bjope edited the summary of this revision. (Show Details)Apr 27 2018, 5:12 AM
bjope added inline comments.Apr 27 2018, 6:29 AM
lib/CodeGen/SelectionDAG/InstrEmitter.cpp
724 ↗(On Diff #144135)

No, we are just using the "unsigned" value for the register that was saved when creating the SDDbgValue.

Note that for this to work we must no change the vreg destination for the PHI node during SelectionDAG build/opt.
Since the PHI nodes aren't part of the SelectionDAG any "normal" use of the vreg would result in a CopyFromReg node that maps the PHI result to a SDValue. But since debug-info aren't supposed to affect code generation we can't create SDNodes for the debug-use. But I also assume that this means that the vreg defined by the already lowered PHI node will stay intact during the SelectionDAG build/opt.

An alternative approach that I considered was to save the Value*, for the PHI node in LLVM IR, similar to how we save a Value* when creating the SDDbgValue::CONST kind of nodes. And then we could use the FunctionLoweringInfo::ValueMap to do the translation into a vreg here in the InstrEmitter. However, then we need to expose the FunctionLoweringInfo to the InstrEmitter and pass that around while emitting things to be able to use it here. I'm not sure that it will make any difference really, and the current patch is smaller.

lib/CodeGen/SelectionDAG/SelectionDAG.cpp
7313 ↗(On Diff #144135)

Thanks, I'll fix that.

7320 ↗(On Diff #144135)

Line longer than 80 columns, will be wrapped before landing this patch.

This revision was automatically updated to reflect the committed changes.