This is an archive of the discontinued LLVM Phabricator instance.

[SelectionDAG][DebugInfo] Use entry-values to recover variables values
AcceptedPublic

Authored by djtodoro on Sep 9 2020, 2:55 AM.

Details

Summary

Use the entry values to salvage some params dbg.values. It is based on D87233.

Diff Detail

Event Timeline

djtodoro created this revision.Sep 9 2020, 2:55 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 9 2020, 2:55 AM
djtodoro requested review of this revision.Sep 9 2020, 2:55 AM

I think this looks mostly good.

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
710

Can you add a comment that explains what's happening here?

718

Would ValueMap.lookup() work here?

@aprantl thanks for your comments.

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
710

Sure.

718

It'd work, thanks.

djtodoro updated this revision to Diff 293096.Sep 21 2020, 1:42 AM
djtodoro edited the summary of this revision. (Show Details)
  • addressing comments
  • refactoring
  • fixing tests
  • adding RegState::Debug to the Reg from the dbg_value
aprantl accepted this revision.Sep 22 2020, 9:15 AM
aprantl added inline comments.
llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
80

Nit: remove ArgValueMap -. This used to be part of the comment style, but is completely redundant in non-ancient versions of Doxygen.

This revision is now accepted and ready to land.Sep 22 2020, 9:15 AM
Orlando added inline comments.
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

I think this we should only be doing this for immutable parameters (and mutable parameters which are never assigned to), right?

I.e. the entry_value of a parameter register is only a valid location for a parameter variable if that variable is never assigned another value.

djtodoro added inline comments.Sep 22 2020, 10:18 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

We are expressing the modification in terms of its entry value here.

StephenTozer added inline comments.
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

As far as I understand, we want to recover variables by describing them in relation to the initial values of the parameters. In that case, it only makes sense to consider variables whose values can be expressed in relation to that; this may include variables that aren't parameters themselves, and may exclude dbg.values for parameters. For example:

void foo(int param) {
  int x = param + 2;
  param = SomeInt();
  ...
}

In this example it should be possible to describe x in terms of param's initial value, while param itself could not be described by an entry value after its assignment within the function. In that case, I believe it would make more sense to look for dbg.values that use a parameter Value, or can be expressed in terms of one, rather than using DILocalVariable::isParameter. Does that seem correct, or have I misunderstood the work or the purpose of this block?

djtodoro added inline comments.Sep 23 2020, 2:56 AM
llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
80

Thanks, sure.

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Hi @StephenTozer.
Yes, but is a more complex use case, so we do not cover it (yet). There is a TODO marker within the findEntryValue() for that.
The debug entry values feature is complex, relying on various things, so we've initially implemented the support for simple registers locations as entry values of *unmodified* parameters *only*, during the LiveDebugValues phase. Currently, we are extending the support onto IR level, for some (simple) cases, but there is space for improvements for sure, since the potential goes beyond the current usage.

718

I think this we should only be doing this for immutable parameters (and mutable parameters which are never assigned to), right?

I.e. the entry_value of a parameter register is only a valid location for a parameter variable if that variable is never assigned another value.

Hi @Orlando.
I might have needed to add some more context here. You are right, and all of that has been already checked within the main debug-entry-values place of the production, within LiveDebugValues. We perform analysis there, and at the moment, use entry values for unmodified params (since it is the basic case). There is space for improvements, by using the entry values for describing/expressing the modification in terms of its entry value, but we do not support it (yet), there.

On the IR level, at the moment, we are trying to extend this support for unused arguments, since it seems to be safe/simple use case. First place for that is the DeadArgElimination pass, and we are working on sorting out all the pieces for that purpose (but it takes some additional magic in order to get it working for both callee and caller sides). The next spot this could be used is here, where we also have unused parameters, that are not being copied into any register, so the SelectionDAG marks them as invalid/unable to track it location anymore. Please comment on this, since I might have missed something.

djtodoro updated this revision to Diff 293681.Sep 23 2020, 3:00 AM
  • addressing comment
StephenTozer added inline comments.Sep 23 2020, 3:38 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Not handling the x case is fine then, since it will be much easier to get the basic change completed and then extend it to cover more cases later. I'm still not sure how this new extension avoids the second case however. Because we only use the variable to determine what entry value (if any) to produce, this code would still produce entry value DBG_VALUEs for a parameter even after an assignment to that parameter. Is there anything I've missed that would prevent us producing invalid entry values right here, such as for param's post-assignment value in the example code above?

djtodoro added inline comments.Sep 23 2020, 3:54 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Probably we need some additional/stronger statements here. Can you please share the test case, so I can reproduce it?

djtodoro added inline comments.Sep 23 2020, 3:56 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

statements -- in the code/extension implementation terms

Orlando added inline comments.Sep 23 2020, 4:12 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Hi @Orlando.
I might have needed to add some more context here. You are right, and all of that has been already checked within the main debug-entry-values place of the production, within LiveDebugValues. We perform analysis there, and at the moment, use entry values for unmodified params (since it is the basic case). There is space for improvements, by using the entry values for describing/expressing the modification in terms of its entry value, but we do not support it (yet), there.

On the IR level, at the moment, we are trying to extend this support for unused arguments, since it seems to be safe/simple use case. First place for that is the DeadArgElimination pass, and we are working on sorting out all the pieces for that purpose (but it takes some additional magic in order to get it working for both callee and caller sides). The next spot this could be used is here, where we also have unused parameters, that are not being copied into any register, so the SelectionDAG marks them as invalid/unable to track it location anymore. Please comment on this, since I might have missed something.

Thank you for this explanation, it has helped me understand.

The significance of ArgValueMap - in filtering the invalidated SDDbgValues for parameter variables down to just those using argument values - hadn't quite hit me until now, but looking again this all makes sense to me now.

I'm not really familiar with how LiveDebugValues handles entry_values currently. I'll take a close look soon as I can though as I'm interested in keeping up with this work!

djtodoro added inline comments.Sep 23 2020, 4:44 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

No problem, thanks for your comments!

I've described the intention of this patch, but I might have missed some pieces, so I think we'll cover that with more tests (e.g. with the one @StephenTozer will provide).

dstenb added inline comments.Sep 23 2020, 6:25 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

I don't want to derail this discussion, but I just wanted to add that when I played around with this patch I encountered cases where we incorrectly emit entry values, even after the parameter has been modified, on trunk without this patch. I wrote a PR for that: https://bugs.llvm.org/show_bug.cgi?id=47628.

StephenTozer added inline comments.Sep 23 2020, 7:51 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Here is a test case which demonstrates the behaviour I'm talking about. I think the easiest way to summarize the underlying issue is that you're using the DILocalVariable to determine what entry value we should emit, if any. This is incorrect: it makes no fundamental difference whether or not the variable we're describing is a parameter, what matters is whether we use one of the SSA parameters. It might make more sense to track this information in the SDDbgValue directly, but in any case we can't rely on the variable to give us that information.

Full disclosure, I've also discussed this with Orlando directly, and he retracts his comment about ArgValueMap solving the issue; since EntryValue is equal to the parameter value for the variable rather than the current dbg.value.

djtodoro added inline comments.Sep 23 2020, 8:34 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

Oh... it makes sense to me. Thanks! I've tried a few tests, and it all seemed to be working fine...

I'll try to propose a solution for this. I think it would be nice if we can make it working outside of the SelectionDAG (like a general solution for IR), and that is why I thought the variable would be enough/nice way to implement it, but it may not be sufficient...

djtodoro planned changes to this revision.Sep 23 2020, 8:35 AM
StephenTozer added inline comments.Sep 23 2020, 9:50 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

My suggestion would be to use the SSA values. The properties of SSA form ensure that whenever we have a reference to an SSA value %param that is a parameter to a function, that value will be available as an entry value. This information should be readily available throughout IR. Once we get to ISel it gets a bit more complicated, but since each dbg.value is associated with a SDDbgValue it should be possible to store some identifying information in the SDDbgValue that can be referred back to here.

My naive thought is that you could simply store a Value* or Value Handle pointing to the original instruction, and use that instead of findEntryValue. If this doesn't work, it may be possible to store some information externally, as with ArgValueMap, that can be combined with the identifier to find the corresponding Entry Value (if any).

djtodoro added inline comments.Sep 24 2020, 1:41 AM
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
718

At first, I proposed/thought extending the instructions with some kind of a pointer to the Value, but it seemed to be too much work (since there would be handling of such info throughout the pipeline, etc.).
Let me think about it, and there might be some combination of this approach and the ideas shared that potentially could solve the problem.

djtodoro updated this revision to Diff 296163.Oct 5 2020, 5:36 AM
  • Use 2 extra arguments from llvm.dbg.value()
  • Handle modified params
This revision is now accepted and ready to land.Oct 5 2020, 5:36 AM
This revision now requires review to proceed.Oct 5 2020, 5:36 AM

This needs to be tested more (so it is not for the final commit (yet)). I believe this triggers some asserts, but (at least) we are covering the cases we want.

ecnelises resigned from this revision.Oct 16 2020, 12:01 AM
This revision is now accepted and ready to land.Oct 16 2020, 12:01 AM
djtodoro requested review of this revision.Oct 16 2020, 12:02 AM
StephenTozer accepted this revision.Oct 19 2020, 6:09 AM

LGTM, this new approach looks solid. As per usual, wait for further approval from someone with more authority in this area.

llvm/include/llvm/CodeGen/SelectionDAG.h
1477–1478

Nit, I think the "v" should be uppercase.

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
710–726

Minor: Comment could do with a small rewrite, something like "must generate an undef" -> "must generate a DBG_VALUE that is either undef, or an entry value if one is available"

711

Double semi-colon here.

llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
68–69

Nit, this can be put in the initializer list.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
5491–5493

Perhaps instead of simply making this a condition, there should be an assert here that V doesn't already exist in ArgValueMap? I can't think of any case where it would already be there that wouldn't be an error, since I don't think we would ever call this twice for the same Value.

llvm/test/DebugInfo/X86/entry-val-invalidated-node-modifed-param-with-add.ll
2–4

Personally I think it'd probably be best to specify the DWARF version in this, so that this test doesn't break if the default becomes 5 (or already is in a clone repo). It might be better to simply update the test if/when that happens though, I don't have especially strong opinions about it. Alternatively you could simply regex it as DW_OP{{(_GNU)?}}_entry_value; also not sure whether or not this approach would be preferred.

llvm/test/DebugInfo/X86/entry-values-for-isel-invalidated-nodes.ll
2–5

Repeat of above comment about DWARF version.

This revision is now accepted and ready to land.Oct 19 2020, 6:09 AM

@StephenTozer Thanks for your comments. I'll address them and refactor the patch a bit, as soon as I catch some time to address some issues with the first patch from the stack.

djtodoro updated this revision to Diff 308051.Nov 27 2020, 7:15 AM
djtodoro retitled this revision from [SelectionDAG][DebugInfo] Use entry-values to recover parameters values to [SelectionDAG][DebugInfo] Use entry-values to recover variables values.
  • Use the entry values for local vars as well