This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo] Add new metadata, DIArgList, for referencing a list of SSA values inside a debug variable intrinsic
ClosedPublic

Authored by StephenTozer on Sep 23 2020, 11:40 AM.
Tokens
"Heartbreak" token, awarded by emanuelarenda18.

Details

Summary

Continuing further with the work from the initial RFC[0], this patch is the first step to supporting variadic debug values within the IR. This patch adds a new metadata node, DIArgList, which contains a list of SSA values.

This node is in many ways similar in function to the existing ValueAsMetadata node, with the difference being that it tracks a list instead of a single value. Internally, it uses ValueAsMetadata to track the individual values, but there is also a reasonable amount of DIArgList-specific value-tracking logic on top of that. Similar to ValueAsMetadata, it is a special case in parsing and printing due to the fact that it requires a function state (as it may reference function-local values).

This patch does not add any useful functionality; it allows for DIArgLists to be parsed and printed, but debug variable intrinsics do not yet recognize them as a valid argument (outside of parsing). This functionality will come in later patches, which should be up tomorrow.

Although this approach differs from the MIR approach (which was to use a variadic set of arguments to the DBG_VALUE itself), the "variadic" approach is not suitable for an IR intrinsic: I've not been able to find any documentation or examples that make it look less complicated than adding a new metadata node; if anyone has anything to offer on that front I'm happy to take a look at it. The tracking behaviour in the DIArgList is also useful to have as it allows us to potentially respond to RAUWs that would cause a dbg.value to become undef, and cease tracking all of the listed SSA values at once, preventing us from needlessly processing and updating dbg.values that can only ever become empty DWARF locations.

[0] http://lists.llvm.org/pipermail/llvm-dev/2020-February/139376.html

Diff Detail

Event Timeline

StephenTozer created this revision.Sep 23 2020, 11:40 AM
StephenTozer requested review of this revision.Sep 23 2020, 11:40 AM
StephenTozer edited the summary of this revision. (Show Details)
aprantl added inline comments.Sep 28 2020, 8:59 AM
llvm/include/llvm/IR/DebugInfoMetadata.h
3440

Why doesn't this inherit from, e.g., MDTuple or have multiple MDOperands?

StephenTozer added inline comments.Sep 28 2020, 9:19 AM
llvm/include/llvm/IR/DebugInfoMetadata.h
3440

The short explanation is that this doesn't use the built-in MD operands at all - you'll notice that we pass None to the Ops argument in the MDNode constructor below. The baisc reason for that is that the way the MDOperands are handled has some incompatibilities with the intended use of the DIArgList arguments. I'll have to go back over my work to collect a more specific set of reasons as to why using MDOperands doesn't work for this.

Fixed a pair of bugs; 1) added DIArgList support to the ValueMapper so that DIArgList arguments are properly updated during inlining, and 2) prevented RAUW from setting DIArgList arguments to null (now uses an UndefValue instead).

Rebase onto recent master; minor non-functional changes (renamed "ParseX()" functions to "parseX()").

I think this would work. Could you base it on MDTuple and would that simplify the implementation?

llvm/include/llvm/IR/DebugInfoMetadata.h
49

Could this be MDTuple instead of MDNode?

I'm sorry, I just accidentally replied to an old mail without realizing that this question was already answered weeks ago.

Although — no that I read the reply — it looks like the MDTuple question hasn't actually been answered ;-)

StephenTozer added a comment.EditedJan 6 2021, 10:08 AM

Although — no that I read the reply — it looks like the MDTuple question hasn't actually been answered ;-)

Apologies for taking a while to get back around to answering it, I've had to do some step retracing. The short answer is that MDTuple doesn't actually contain any useful common code for DIArgList. The longer answer is that MDTuple comes with built-in functionality for an arbitrary tuple of metadata, which is similar to what we want. However, what it isn't innately equipped to handle is LocalAsMetadata, which is unique among the many types of metadata in LLVM as being the only kind that needs a function context to be parsed. Therefore, all the rules around parsing and printing LocalAsMetadata entries are special-case; the same is also true of RAUW, which works by default for normal Values but uses a separate map and code path to handle ValueAsMetadata and MetadataAsValue (and now DIArgList).

In terms of parsing, processing, and printing, DIArgList is much closer to LocalAsMetadata than it is to MDTuple, and most of the "new" code for handling DIArgList is side-by-side with the LocalAsMetadata code, and directly derived from it. Because of this, even though we could technically base DIArgList off of MDTuple, we wouldn't be able to use most of the existing code; at best, we would be moving all of the code unique for DIArgLists into the parseMDTuple function. If anything, DIArgList might not actually need to be an MDNode at all, but just plain Metadata - I started with an implementation similar to DIExpression, which is based on MDNode, but I haven't confirmed that it's necessary.

As a drive-by comment, I'll add that MDTuple was originally meant to be a final version of MDNode, as in if isa<MDTuple> returns true then you know you have a standard metadata tuple, and not some other special type. Inheriting from MDNode sounds more in line with the original intent to me. (I'm not sure it's important to maintain that as an invariant, but thought I'd mention it.)

aprantl accepted this revision.Jan 6 2021, 2:37 PM
This revision is now accepted and ready to land.Jan 6 2021, 2:37 PM

Rebased onto recent master, minor change to Args storage (std::vector -> SmallVector) and added args_begin() and args_end().

This revision was landed with ongoing or failed builds.Mar 5 2021, 9:02 AM
This revision was automatically updated to reflect the committed changes.
tejohnson added inline comments.
llvm/lib/IR/DebugInfoMetadata.cpp
1526

I tracked down some non-deterministic compiler behavior to DIArgList handling, and in particular, to this custom handleChangedOperand behavior. The normal MDNode::handleChangedOperand implementation takes care to update the store for the md type, and any necessary re-uniquing. That isn't being done here which appears to leave the DIArgLists DenseSet store on the context in an inconsistent state.

I've sent a tentative fix for review in D108968.