<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 17, 2014 at 3:27 PM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
> On 2014-Nov-17, at 11:26, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
><br>
><br>
><br>
> On Thu, Nov 13, 2014 at 5:17 PM, Duncan P. N. Exon Smith <<a href="mailto:dexonsmith@apple.com">dexonsmith@apple.com</a>> wrote:<br>
> Author: dexonsmith<br>
> Date: Thu Nov 13 19:17:09 2014<br>
> New Revision: 221960<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=221960&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=221960&view=rev</a><br>
> Log:<br>
> IR: Rewrite uniquing and creation of MDString<br>
><br>
> Stop using `Value::getName()` to get the string behind an `MDString`.<br>
> Switch to `StringMapEntry<MDString>` so that we can find the string by<br>
> its coallocation.<br>
><br>
> This is part of PR21532.<br>
><br>
> Modified:<br>
> llvm/trunk/include/llvm/IR/Metadata.h<br>
> llvm/trunk/lib/IR/LLVMContextImpl.cpp<br>
> llvm/trunk/lib/IR/LLVMContextImpl.h<br>
> llvm/trunk/lib/IR/Metadata.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/IR/Metadata.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=221960&r1=221959&r2=221960&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=221960&r1=221959&r2=221960&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/IR/Metadata.h (original)<br>
> +++ llvm/trunk/include/llvm/IR/Metadata.h Thu Nov 13 19:17:09 2014<br>
> @@ -57,14 +57,15 @@ public:<br>
> ///<br>
> /// TODO: Inherit from Metadata.<br>
> class MDString : public Value {<br>
> + friend class StringMapEntry<MDString>;<br>
><br>
> This seems annoyingly tied to the implementation details of StringMap (exactly where in the stack the constructor is called, etc)... I wonder if there's a better answer, but none springs immediately to mind.<br>
><br>
> +<br>
> virtual void anchor();<br>
> MDString(const MDString &) LLVM_DELETED_FUNCTION;<br>
><br>
> explicit MDString(LLVMContext &C);<br>
><br>
> -private:<br>
> /// \brief Shadow Value::getName() to prevent its use.<br>
> - StringRef getName() const { return Value::getName(); }<br>
> + StringRef getName() const LLVM_DELETED_FUNCTION;<br>
><br>
> public:<br>
> static MDString *get(LLVMContext &Context, StringRef Str);<br>
> @@ -72,17 +73,17 @@ public:<br>
> return get(Context, Str ? StringRef(Str) : StringRef());<br>
> }<br>
><br>
> - StringRef getString() const { return getName(); }<br>
> + StringRef getString() const;<br>
><br>
> - unsigned getLength() const { return (unsigned)getName().size(); }<br>
> + unsigned getLength() const { return (unsigned)getString().size(); }<br>
><br>
> typedef StringRef::iterator iterator;<br>
><br>
> /// \brief Pointer to the first byte of the string.<br>
> - iterator begin() const { return getName().begin(); }<br>
> + iterator begin() const { return getString().begin(); }<br>
><br>
> /// \brief Pointer to one byte past the end of the string.<br>
> - iterator end() const { return getName().end(); }<br>
> + iterator end() const { return getString().end(); }<br>
><br>
> /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.<br>
> static bool classof(const Value *V) {<br>
><br>
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=221960&r1=221959&r2=221960&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=221960&r1=221959&r2=221960&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)<br>
> +++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Thu Nov 13 19:17:09 2014<br>
> @@ -135,7 +135,7 @@ LLVMContextImpl::~LLVMContextImpl() {<br>
> "Destroying all MDNodes didn't empty the Context's sets.");<br>
><br>
> // Destroy MDStrings.<br>
> - DeleteContainerSeconds(MDStringCache);<br>
> + MDStringCache.clear();<br>
> }<br>
><br>
> // ConstantsContext anchors<br>
><br>
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=221960&r1=221959&r2=221960&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=221960&r1=221959&r2=221960&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/IR/LLVMContextImpl.h (original)<br>
> +++ llvm/trunk/lib/IR/LLVMContextImpl.h Thu Nov 13 19:17:09 2014<br>
> @@ -261,7 +261,7 @@ public:<br>
> FoldingSet<AttributeSetImpl> AttrsLists;<br>
> FoldingSet<AttributeSetNode> AttrsSetNodes;<br>
><br>
> - StringMap<Value*> MDStringCache;<br>
> + StringMap<MDString> MDStringCache;<br>
><br>
> FoldingSet<MDNode> MDNodeSet;<br>
><br>
><br>
> Modified: llvm/trunk/lib/IR/Metadata.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=221960&r1=221959&r2=221960&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=221960&r1=221959&r2=221960&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/IR/Metadata.cpp (original)<br>
> +++ llvm/trunk/lib/IR/Metadata.cpp Thu Nov 13 19:17:09 2014<br>
> @@ -37,13 +37,21 @@ MDString::MDString(LLVMContext &C)<br>
> : Value(Type::getMetadataTy(C), Value::MDStringVal) {}<br>
><br>
> MDString *MDString::get(LLVMContext &Context, StringRef Str) {<br>
> - LLVMContextImpl *pImpl = Context.pImpl;<br>
> - StringMapEntry<Value*> &Entry =<br>
> - pImpl->MDStringCache.GetOrCreateValue(Str);<br>
> - Value *&S = Entry.getValue();<br>
> - if (!S) S = new MDString(Context);<br>
> - S->setValueName(&Entry);<br>
> - return cast<MDString>(S);<br>
> + auto &Store = Context.pImpl->MDStringCache;<br>
> + auto I = Store.find(Str);<br>
> + if (I != Store.end())<br>
> + return &I->second;<br>
> +<br>
> + auto *Entry =<br>
> + StringMapEntry<MDString>::Create(Str, Store.getAllocator(), Context);<br>
><br>
> This seems like it's the wrong API design - forwarding a single argument and calling an explicit constructor doesn't seem right. APIs (such as push_back) generally do perfect forwarding of a single argument where the argument is implicitly convertible to the underlying type, but not for explicit conversions.<br>
><br>
> For explicit conversions the idiom seems to be to have an 'emplace' function.<br>
><br>
> I think the right API design is to add an 'emplace' to StringMap and use it something like this:<br>
><br>
> Store.insert(std::piecewise_construct, std::forward_as_tuple(Str), std::forward_as_tuple(Context));<br>
><br>
<br>
</div></div>`std::forward_as_tuple()` and `std::piecewise_construct` are new to me,<br>
thanks for suggesting it. I see that you're using this in<br>
LexicalScopes.cpp.<br>
<br>
It's not clear to me how to unpack the tuple to send into a<br>
constructor when we're not leveraging `std::pair<>`. I had a look at<br>
the libcxx implementation of `utility`, and it seems to use an<br>
unexposed class called `__tuple_indices` to do the magic.<br></blockquote><div><br></div><div>Unexposed, but not magic - it can be implemented in LLVM as it is in libc++. A few of these utilities are a bit of a pain to write, but they're generic enough not to need to be written very often.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Note that `StringMap` doesn't actually use a `std::pair<>`.<br>
`StringMapEntry` has a similar API, but is distinct.<br>
<br>
Am I missing something obvious?<br></blockquote><div><br>StringMap still exposes an Associative Container interface in many places (like its insert(std::pair<StringRef, ValueTy>) rather than insert(StringRef, ValueTy)) so it seems reasonable to provide an emplace with a similar API.<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Nevertheless, StringMap is pretty simple. We don't care about<br>
forwarding the key, just the value. *IF* we were allowed to use<br>
variadic templates, it'd be easy enough to implement:<br>
<br>
template <class... ArgsT><br>
std::pair<iterator, bool> emplace(StringRef Key, ArgsT &&...Args);<br>
<br>
This was my original plan, but then I remembered (incorrectly?) that<br>
MSVC doesn't support variadic templates yet, so I just hacked in<br>
something that works.</blockquote><div><br>MSVC doesn't support variadic templates in the minimum version of MSVC we support, so we fake out variadics whenever we need to (see the existing uses of LLVM_HAS_VARIADIC_TEMPLATES in LLVM).<br> </div></div><br></div></div>