[llvm] r255909 - [ThinLTO] Metadata linking for imported functions
Duncan P. N. Exon Smith via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 4 13:19:15 PST 2016
> On 2015-Dec-29, at 18:00, Teresa Johnson <tejohnson at google.com> wrote:
>
> On Wed, Dec 23, 2015 at 8:34 AM, Duncan P. N. Exon Smith
> <dexonsmith at apple.com> wrote:
>>
>>> On 2015-Dec-17, at 12:14, Teresa Johnson via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>>>
>>> Author: tejohnson
>>> Date: Thu Dec 17 11:14:09 2015
>>> New Revision: 255909
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=255909&view=rev
>>> Log:
>>> [ThinLTO] Metadata linking for imported functions
>>>
>>> Summary:
>>> Second patch split out from http://reviews.llvm.org/D14752.
>>>
>>> Maps metadata as a post-pass from each module when importing complete,
>>> suturing up final metadata to the temporary metadata left on the
>>> imported instructions.
>>>
>>> This entails saving the mapping from bitcode value id to temporary
>>> metadata in the importing pass, and from bitcode value id to final
>>> metadata during the metadata linking postpass.
>>>
>>> Depends on D14825.
>>>
>>> Reviewers: dexonsmith, joker.eph
>>>
>>> Subscribers: davidxl, llvm-commits, joker.eph
>>>
>>> Differential Revision: http://reviews.llvm.org/D14838
>>>
>>> Added:
>>> llvm/trunk/test/Linker/Inputs/thinlto_funcimport_debug.ll
>>> llvm/trunk/test/Linker/thinlto_funcimport_debug.ll
>>> llvm/trunk/test/Transforms/FunctionImport/Inputs/funcimport_debug.ll
>>> llvm/trunk/test/Transforms/FunctionImport/funcimport_debug.ll
>>> Modified:
>>> llvm/trunk/include/llvm/IR/GVMaterializer.h
>>> llvm/trunk/include/llvm/IR/Metadata.h
>>> llvm/trunk/include/llvm/IRReader/IRReader.h
>>> llvm/trunk/include/llvm/Linker/IRMover.h
>>> llvm/trunk/include/llvm/Linker/Linker.h
>>> llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h
>>> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>>> llvm/trunk/lib/IR/Metadata.cpp
>>> llvm/trunk/lib/IRReader/IRReader.cpp
>>> llvm/trunk/lib/Linker/IRMover.cpp
>>> llvm/trunk/lib/Linker/LinkModules.cpp
>>> llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
>>> llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
>>> llvm/trunk/tools/llvm-link/llvm-link.cpp
>>>
>>>
>>> Modified: llvm/trunk/include/llvm/IR/Metadata.h
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=255909&r1=255908&r2=255909&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/IR/Metadata.h (original)
>>> +++ llvm/trunk/include/llvm/IR/Metadata.h Thu Dec 17 11:14:09 2015
>>> @@ -832,10 +832,11 @@ public:
>>> /// \brief Resolve cycles.
>>> ///
>>> /// Once all forward declarations have been resolved, force cycles to be
>>> - /// resolved.
>>> + /// resolved. If \p MDMaterialized is true, then any temporary metadata
>>> + /// is ignored, otherwise it asserts when encountering temporary metadata.
>>
>> Please expand a little on the semantic difference between `true` and
>> `false` here. In the `false` case, you're blocking identical `MDNode`s
>> from getting uniqued together.
>
> Looks like I got the comment backwards. We ignore temp metadata when
> MDMaterialized==false, otherwise we assert when seeing temp metadata
> here (the default behavior). I don't think there is any other semantic
> difference - the flag only affects temporary MD, which we shouldn't
> normally see (which is why the default is the old behavior of
> asserting on temp metadata).
It's subtle, but I think it's important. Consider the following.
--
The LLVMContext has:
!1 = !{!2}
!2 = !{}
a.bc contains:
!1 = !{!2}
!2 = !{}
--
The full-loader would read this in, and merge !1 and !2 together.
--
Let's say the lazy-loader chooses *only* to read !1 from a.bc,
leaving !2 as a temporary. Now LLVMContext has:
!1 = !{!2}
!2 = !{}
!3 = unresolved !{!4} // !1 from a.bc (with RAUW support)
!4 = temporary !{} // !2 from a.bc
Lazy-loader calls !3->resolveCycles(), giving:
!1 = !{!2}
!2 = !{}
!3 = !{!4} // !1 from a.bc (no RAUW support)
!4 = temporary !{} // !2 from a.bc
Eventually, we read in !4. !3 hits a uniquing collision, but
doesn't have RAUW support (since `resolveCycles()` dropped it).
End result:
!1 = !{!2}
!2 = !{}
!3 = distinct !{!2} // !1 from a.bc
--
If `resolveCycles()` hadn't been called, we'd end up with:
!1 = !{!2}
!2 = !{}
since !3 could resolve the uniquing collision using RAUW.
--
The new operation completely violates the spirit of
`resolveCycles()`, which (before your patch) was saying:
"I promise there are no more temporaries, so remaining
unresolved nodes must be part of a cycle."
The `assert()` confirms that everything is in a cycle.
With your new flag set, this has changed to:
"I don't care about uniquing the remaining nodes, so drop
RAUW support for them."
Maybe something like this would make sense:
--
void resolveCycles()
{ resolveRecursivelyImpl(/* AllowTemps */ false); }
void resolveNonTemporaries()
{ resolveRecursivelyImpl(/* AllowTemps */ true); }
private:
// Old resolveCycles() implementation.
void resolveRecursivelyImpl(bool AllowTemps);
--
(Do you have a better name for `resolveNonTemporaries()`?)
With the API split it might be easier to document the semantic
differences (just by describing the use case for each).
For `resolveCycles()`, please make clear (if it isn't already?)
that we're promising there aren't any temporaries, and thus
unresolved nodes are part of cycles and no longer need RAUW
support.
For `resolveNonTemporaries()`, please make clear that this is a
destructive operation that blocks uniquing of metadata nodes.
More information about the llvm-commits
mailing list