This is an archive of the discontinued LLVM Phabricator instance.

[Assignment Tracking][6/*] Add trackAssignments function
ClosedPublic

Authored by Orlando on Aug 19 2022, 6:14 AM.

Details

Summary

The Assignment Tracking debug-info feature is outlined in this RFC. This first series of patches adds documentation, the changes necessary to start emitting and using the new metadata, and updates clang with an option to enable the feature. Working with the new metadata in the middle and back end will come later. There are still a few rough edges but I'm putting these patches up now hoping to get feedback on the design and implementation from the upstream community.


Add trackAssignments which adds assignment tracking metadata to a function for a specified set of variables. The intended callers are the inliner and the front end - those calls will be added in separate patches.

I've added a pass called declare-to-assign (AssignmentTrackingPass) that converts dbg.declare intrinsics to dbg.assigns using trackAssignments so that the function can be easily tested (see llvm/test/DebugInfo/Generic/track-assignments.ll). The pass could also be used by front ends to easily test out enabling assignment tracking.

There is still at least one TODO: trackAssignments (and the rest of the pipeline) currently only works for local variables backed by an alloca. Some local variables have their storage allocated by the calling function with the address passed in with a sret or byval parameter. I have a solution in mind for this but would like to tackle that after the core of the feature is accepted.

Diff Detail

Event Timeline

Orlando created this revision.Aug 19 2022, 6:14 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 19 2022, 6:14 AM
Orlando requested review of this revision.Aug 19 2022, 6:14 AM
Herald added a project: Restricted Project. · View Herald TranscriptAug 19 2022, 6:14 AM
Orlando updated this revision to Diff 454421.Aug 22 2022, 2:07 AM

+ Use getDebugValueLoc for dbg.declare -> dbg.assign DILocation
+ Add diff context

jmorse added a subscriber: jmorse.Sep 6 2022, 5:42 AM
jmorse added inline comments.
llvm/include/llvm/IR/DIBuilder.h
923–925

Nit: starting with "Must have..." doesn't explain it's purpose -- IMHO, better to start with "Instruction with a DIAssignID to link with this dbg.assign...".

932

\param DL as well, if we're documenting all the arguments

934

Why a reference for DILocalVariable -- convention (as I understand it) elsewhere is to pass all metadata as pointers.

llvm/include/llvm/IR/DebugInfo.h
251

\n

253

I'd say TODO rather than FIXME,

257

Possibly silly question, but does this ever get called with iterators other than begin() and end()? I don't get the feeling that a range of blocks is ever useful (is that how inlining inserts them, as a range?).

258

IMO: it's better to typedef a name for this data structure, that avoids the over-use of auto in the future.

261

"a static and size offset" doesn't parse to me, was this "a static size and offset"?

llvm/include/llvm/IR/Value.h
750–754 ↗(On Diff #454421)

I want to say that there must be something in LLVM that already does this, but I can only see things that deal with inbound geps, or constants. Could I suggest a name like "stripAllOffsets", to give the reader a strong hint that this method drops / ignores a _lot_ of information -- that'll discourage people from using it in contexts where they need to care about some of the offsets. (Renaming can be in a follow-up patch or something, no need to re-juggle the patch stack because of a name nitpick).

llvm/lib/IR/DIBuilder.cpp
976–983

Aesthetics nit -- why not make the call to MetadataAsValue::get for StoredVal and Destination in this block, then it would all be beautifully aligned? (Feel free to ignore this style comment).

llvm/lib/IR/DebugInfo.cpp
1718–1719

Just to ask the obvious question: are you able to use Value::stripAndAccumulateConstantOffsets instead of this?

1760

Is this field actually an offset as the variable name suggests? My (shallow) reading of MemIntrinsic suggests that it's the length (aka size?) of the load/store being performed, which is not an offset.

1781

The call to emitDbgAssign added in this patch dereferences a pointer to Val and Dest, then the address is taken off them again further below. Better (IMHO) to just pass in the pointer, given that insertDbgAssign takes pointers?

1794

Feels like you can just re-use the identical call to DIExpression::get from above.

1806–1808

Any need for "if Start == End return"?

1841

MemTransferInst instead? The distinction between memcpy and memmove isn't too important here.

1878–1883

This can be hoisted out of the VarRecord loop, no?

1904

To avoid extra indentation, dyn cast then "if (!DDI) continue;"?

1905
1935–1943

Not completely clear what the find is doing, comment appreciated. Promote to an assertion perhaps, or EXPENSIVE_CHECKS?

1950–1951

IMHO: we should be able to specify that all analyses are preserved. If they're not, that's a debug-info-changes-codegen bug.

Orlando updated this revision to Diff 458442.Sep 7 2022, 7:02 AM
Orlando marked 19 inline comments as done.

+ Address inline comments

llvm/include/llvm/IR/DIBuilder.h
934

Fair, not sure why I did that. Fixed.

llvm/include/llvm/IR/DebugInfo.h
253

Done and I've included this on the TODO list in the docs in D132220.

257

Yes it is because of the inliner (see D133318).

llvm/include/llvm/IR/Value.h
750–754 ↗(On Diff #454421)

It looks like this is actually just code lying around from earlier on in the prototype so I've removed it, sorry for the noise.

llvm/lib/IR/DebugInfo.cpp
1718–1719

I vaguely remember asking myself this same question. I can't remember what conclusions I came to and yet this function remains here. Nevertheless, I really can't see a reason why we can't use stripAndAccumulateConstantOffsets instead and in fact building CTMark's tramp3d-v4 with -emit-llvm results in no difference in output with and without this change (at least while AllowNonInbounds is true). Odd, but I'm happy to chalk it up to being product of coming out of the prototype stage.

1760

You're right - that's just a badly named variable. Fixed, nice catch, thanks.

1794

Expr gets re-assigned in the if block below its declaration, so they're not always identical.

1806–1808

It's not needed for correctness (that's the loop stop condition and nothing happens after the loop) and I can't imagine that it's a case common enough to warrant the early-out. Happy to do it though if you think it's worth it.

1935–1943

I've improved the comment and upgraded the if to an assert. I think it should be okay as just an assert and not wrapped in EXPENSIVE_CHECKS because typically Markers will only contain one element. I've also improved the check from DILocalVariable == DILocalVariable to include scope & fragment info by using DebugVariable. I'm using the new DebugVariable ctor added in D133286, so I've added that patch as a parent.

1950–1951

Sorry I should have mentioned that I was copying what RedundantDbgInstElimination (redundant-dbg-inst-elim) in llvm/lib/Transforms/Scalar/DCE.cpp does. Should I still change it to PreservedAnalyses::all()?

jmorse accepted this revision.Sep 8 2022, 4:57 AM

LGTM

llvm/lib/IR/DebugInfo.cpp
1806–1808

No opinion really, just curious. No need for premature optimisation.

This revision is now accepted and ready to land.Sep 8 2022, 4:57 AM
This revision was landed with ongoing or failed builds.Nov 8 2022, 8:52 AM
This revision was automatically updated to reflect the committed changes.