This is an archive of the discontinued LLVM Phabricator instance.

[DebugInfo] Fix incorrect updating of SDNode dependencies for variadic debug values
ClosedPublic

Authored by StephenTozer on Mar 26 2021, 9:50 AM.

Details

Summary

This patch fixes an issue observed upon applying D91722 to current main (previously contained in another patch, but now separated out here):

SelectionDAG::transferDebugValues incorrectly updates the SDDbgValue's dependencies list. Specifically, this class maintains two closely related lists; the list of SDDbgOperands(which, for nodes, consist of an SDNode and a result number, (Node, ResNo)), and the list of SDNodes that it depends on (this list contains duplicates, which is important here). The latter list is derived from the former (this isn't true for all SDDbgValues, but it is true for all variadic cases), so we can expect each node operand to have a corresponding dependency. When we transfer debug values, currently we replace each operand that matches the (Node, ResNo) with the target node and result number, but we then replace every dependency of Node with the target node as well. This is incorrect if we have operands [(Node1, 0), (Node1, 1)], as the dependencies will be [Node1, Node1], so when we want to replace (Node1, 0) with (Node2, 0), we end up with operands [(Node2, 0), (Node1, 1)] (correct), and dependencies [Node2, Node2] (incorrect).

My current approach to fixing this is to change the dependency handling in SDDbgValue so that we derive the dependencies from the operands where possible. This is done by keeping a list of AdditionalDependencies, which contains all of the debug value's dependencies that aren't used directly as operands. When we fetch the list of dependencies, we fetch a combination of the nodes used by location operands and the additional dependencies; this means that we can freely update the debug operands without worrying about keeping the dependencies array in sync. Technically this approach could be taken further, as all the additional dependencies actually come from frame index location operands, but this kind of tracking isn't handled even for the existing cases; as this is currently holding up the main variadic patch, it seemed prudent to stick to the simple case for now.

Diff Detail

Event Timeline

StephenTozer created this revision.Mar 26 2021, 9:50 AM
StephenTozer requested review of this revision.Mar 26 2021, 9:50 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 26 2021, 9:50 AM

LGTM overall (as @jmorse pointed out, if possible, I'd like to see a test case)

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
1345

so this is relevant for stack objects only?

StephenTozer added inline comments.Mar 29 2021, 9:26 AM
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
1345

Correct; when calculating dependencies for an SDDbgValue, this patch will automatically include any SDNodes that are used directly as operands, so we no longer need to add (and should not add) the SDNodes as dependencies for every argument; because frame index operands do not hold a direct reference the SDNode they depend on, we manually add it for those operands and only those operands.

Added simple test case, which triggers a build error without the fix (so no use of FileCheck).

djtodoro accepted this revision.Apr 7 2021, 12:10 AM
This revision is now accepted and ready to land.Apr 7 2021, 12:10 AM

Sanitizer builds were failing due to memory leaks; these were caused by the fact that SDDbgValues are allocated under a BumpPtrAllocator, which does not call destructors. SDDbgValues contained SmallVectors which did not use this allocator, so when the SDDbgValues were cleared they would not call the SmallVector destructor.

This has been resolved by replacing each SmallVector with a std::shared_ptr that uses the BumpPtrAllocator, so there will be no memory allocated outside of this allocator and hence no leaks.

StephenTozer reopened this revision.Apr 9 2021, 6:42 AM

Reopening review, as non-trivial changes have been added following buildbot failure (see comment above for details).

This revision is now accepted and ready to land.Apr 9 2021, 6:42 AM

Sanitizer builds were failing due to memory leaks; these were caused by the fact that SDDbgValues are allocated under a BumpPtrAllocator, which does not call destructors. SDDbgValues contained SmallVectors which did not use this allocator, so when the SDDbgValues were cleared they would not call the SmallVector destructor.

This has been resolved by replacing each SmallVector with a std::shared_ptr that uses the BumpPtrAllocator, so there will be no memory allocated outside of this allocator and hence no leaks.

Nice! imo it would be nice to have a comment somewhere explaining this, otherwise LGTM but please wait for someone else to +1 it.

Fixed deletion lambdas in shared_ptrs, which were previously missing the size of the array.

StephenTozer requested review of this revision.Apr 9 2021, 7:26 AM
Orlando added inline comments.Apr 9 2021, 7:38 AM
llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
166

I don't think you should call Deallocate when using a BumpPtrAllocator?

include/llvm/Support/Allocator.h

210   // Bump pointer allocators are expected to never free their storage; and
211   // clients expect pointers to remain valid for non-dereferencing uses even
212   // after deallocation.
213   void Deallocate(const void *Ptr, size_t Size, size_t /*Alignment*/) {
214     __asan_poison_memory_region(Ptr, Size);
215   }

IIUC the memory will be freed by the BumpPtrAllocator with everything else all at once.

Replace shared_ptr usage with raw pointers, as neither a copy constructor nor the destructor for SDDbgValue are ever called, making memory management a non-issue.

Orlando added inline comments.Apr 9 2021, 8:26 AM
llvm/lib/CodeGen/SelectionDAG/SDNodeDbgValue.h
166

I totally misunderstood what __asan_poison_memory_region(Ptr, Size); was doing here, ignore my comment above. Sorry for the noise!

Small update: explicitly deleted the copy constructors and destructor for SDDbgValue with an explanatory comment, to ensure that if we ever start copy constructing or destroying instances of SDDbgValue there will be notice that the raw pointers need to be managed.

jmorse accepted this revision.Apr 9 2021, 9:29 AM

LGTM with latest memory jiggery pokery.

This revision is now accepted and ready to land.Apr 9 2021, 9:29 AM
StephenTozer closed this revision.May 10 2021, 7:40 AM

The updated patch was reapplied in aa3e78a59fdf.