This is an archive of the discontinued LLVM Phabricator instance.

[IR] Add llvm.dbg.addr, a control-dependent version of llvm.dbg.declare
ClosedPublic

Authored by rnk on Sep 12 2017, 1:48 PM.

Details

Summary

This implements the design discussed on llvm-dev for better tracking of
variables that live in memory through optimizations:

http://lists.llvm.org/pipermail/llvm-dev/2017-September/117222.html

This is tracked as PR34136

llvm.dbg.addr is intended to be produced and used in almost precisely
the same way as llvm.dbg.declare is today, with the exception that it is
control-dependent. That means that dbg.addr should always have a
position in the instruction stream, and it will allow passes that
optimize memory operations on local variables to insert llvm.dbg.value
calls to reflect deleted stores. See SourceLevelDebugging.rst for more
details.

The main drawback to generating DBG_VALUE machine instrs is that they
usually cause LLVM to emit a location list for DW_AT_location. The next
step will be to teach DwarfDebug.cpp how to recognize more DBG_VALUE
ranges as not needing a location list, and possibly start setting
DW_AT_start_offset for variables whose lifetimes begin mid-scope.

Event Timeline

rnk created this revision.Sep 12 2017, 1:48 PM
aprantl added inline comments.Sep 12 2017, 2:16 PM
llvm/docs/SourceLevelDebugging.rst
202

please add a DILocation (!dbg !4), since it actually is an integral part of the intrinsic.

205

"exactly one" ?

221

I find this somewhat confusing for the reader since the above paragraph makes it sound like there can also only be one dbg.addr.

222

control-flow-dependent?

llvm/include/llvm/IR/IntrinsicInst.h
130
/// Methods for ...
/// @{
...
/// @}
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
5144

control flow ?

llvm/lib/IR/DIBuilder.cpp
28

What would break (besides IR testcases) if we made this the default immediately?

llvm/lib/IR/Verifier.cpp
4006

that string correct?

llvm/lib/Transforms/Scalar/SROA.cpp
4105

These are no longer just dbg.declares, are they?

llvm/lib/Transforms/Utils/Local.cpp
1254

Should this be a verifier error?

llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
106

These are no longer just dbg.declares, are they?

248

These are no longer just dbg.declares, are they?

llvm/test/Transforms/SROA/dbg-addr-diamond.ll
42

strip the tbaa stuff?

rnk marked 5 inline comments as done.Sep 12 2017, 2:55 PM
rnk added inline comments.
llvm/docs/SourceLevelDebugging.rst
221

Hm, the above paragraph was meant to clarify that the frontend should generate one call, but optimizations may introduce more dbg.addrs. Hopefully now it's clear?

222

"control dependence" is a pretty common compiler concept, I think it's clearer to keep this short.

llvm/lib/IR/DIBuilder.cpp
28

Our -O0 DWARF would probably become much larger and much worse. llvm.dbg.addr always generates DBG_VALUE instructions that may be lost, and even if they survive CodeGen, they usually lead to the creation of a single entry location list, which is larger than an inline exprloc.

We could work around this by using the MF side table if there is exactly one llvm.dbg.addr and optnone is set, but I want to see what the quality degradation is first to see if it is viable to improve DwarfDebug.cpp to standardize on DBG_VALUE and eliminate the side table.

llvm/lib/IR/Verifier.cpp
4006

Oops, fixed.

llvm/lib/Transforms/Scalar/SROA.cpp
4105

The naming is inconsistent here and elsewhere. For this transition period when they can be either addrs or declares, I'd rather leave the naming alone until we flip the default and standardize on dbg.addr.

llvm/lib/Transforms/Utils/Local.cpp
1254

Actually, I think this is bug. A single alloca may hold multiple variables at different offsets. I tried to construct a unit test for this, but it was difficult and fragile so I deleted it. There's also no correctness issue with multiple variables living at the same location in memory, either.

I tried to put together a real-world test case with inalloca on windows x86:

struct NonTrivial {
  NonTrivial() : x(1) {}
  NonTrivial(const NonTrivial &) = default;
  ~NonTrivial() {}
  int x;
};
static int inalloca(NonTrivial a, int b, int c) {
  return a.x + b + c;
}
extern "C" int f() {
  return inalloca(NonTrivial(), 2, 3);
}

Clang will generate a single alloca to hold a, b, and c, and I would like it if we could inline and SROA away everything while tracking their values (1, 2, and 3). However, there are compounding issues here that move this out of scope for this patch.

rnk updated this revision to Diff 114919.Sep 12 2017, 2:57 PM
rnk marked an inline comment as done.
  • update
probinson added inline comments.Sep 12 2017, 3:26 PM
llvm/lib/IR/IntrinsicInst.cpp
27

With no other changes in the file, I'm guessing you don't actually need this?

llvm/lib/Transforms/Scalar/SROA.cpp
4141–4142

Preceding comment is no longer fully correct.

rnk marked 2 inline comments as done.Sep 13 2017, 2:08 PM
rnk updated this revision to Diff 115115.Sep 13 2017, 2:09 PM
  • rebase
  • implement Paul's comments
aprantl added inline comments.Sep 19 2017, 3:17 PM
llvm/lib/Transforms/Utils/Local.cpp
1101

llvm.dbg.decl?

Either the comment is not up to date, or the signature shouldn't change.
Side-note: the comment should also be moved into the header.

1143

ditto

1237

move comment into header
/// Finds all llvm.dbg.declare and llvm.debug.addr intrinsics describing local variables ...

llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
106

ping

948

NFC follow-up to make this into
auto AI ?

aprantl accepted this revision.Sep 19 2017, 3:17 PM

Couple of (stylistic) inline comments, but otherwise looking good!

This revision is now accepted and ready to land.Sep 19 2017, 3:17 PM
rnk marked 2 inline comments as done.Sep 20 2017, 2:43 PM
This revision was automatically updated to reflect the committed changes.