Use the entry values to salvage some params dbg.values. It is based on D87233.
Diff Detail
Event Timeline
- addressing comments
- refactoring
- fixing tests
- adding RegState::Debug to the Reg from the dbg_value
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. |
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. |
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | ||
---|---|---|
718 | We are expressing the modification in terms of its entry value here. |
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? |
llvm/include/llvm/CodeGen/FunctionLoweringInfo.h | ||
---|---|---|
80 | Thanks, sure. | |
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | ||
718 | Hi @StephenTozer. | |
718 |
Hi @Orlando. 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. |
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? |
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? |
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | ||
---|---|---|
718 | statements -- in the code/extension implementation terms |
llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp | ||
---|---|---|
718 |
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! |
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). |
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. |
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. |
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... |
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). |
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.). |
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.
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. |
@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.
Nit: remove ArgValueMap -. This used to be part of the comment style, but is completely redundant in non-ancient versions of Doxygen.