[llvm] r221960 - IR: Rewrite uniquing and creation of MDString

Duncan P. N. Exon Smith dexonsmith at apple.com
Mon Nov 17 15:27:00 PST 2014


> On 2014-Nov-17, at 11:26, David Blaikie <dblaikie at gmail.com> wrote:
> 
> 
> 
> On Thu, Nov 13, 2014 at 5:17 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
> Author: dexonsmith
> Date: Thu Nov 13 19:17:09 2014
> New Revision: 221960
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=221960&view=rev
> Log:
> IR: Rewrite uniquing and creation of MDString
> 
> Stop using `Value::getName()` to get the string behind an `MDString`.
> Switch to `StringMapEntry<MDString>` so that we can find the string by
> its coallocation.
> 
> This is part of PR21532.
> 
> Modified:
>     llvm/trunk/include/llvm/IR/Metadata.h
>     llvm/trunk/lib/IR/LLVMContextImpl.cpp
>     llvm/trunk/lib/IR/LLVMContextImpl.h
>     llvm/trunk/lib/IR/Metadata.cpp
> 
> Modified: llvm/trunk/include/llvm/IR/Metadata.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=221960&r1=221959&r2=221960&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Metadata.h (original)
> +++ llvm/trunk/include/llvm/IR/Metadata.h Thu Nov 13 19:17:09 2014
> @@ -57,14 +57,15 @@ public:
>  ///
>  /// TODO: Inherit from Metadata.
>  class MDString : public Value {
> +  friend class StringMapEntry<MDString>;
> 
> 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.
>  
> +
>    virtual void anchor();
>    MDString(const MDString &) LLVM_DELETED_FUNCTION;
> 
>    explicit MDString(LLVMContext &C);
> 
> -private:
>    /// \brief Shadow Value::getName() to prevent its use.
> -  StringRef getName() const { return Value::getName(); }
> +  StringRef getName() const LLVM_DELETED_FUNCTION;
> 
>  public:
>    static MDString *get(LLVMContext &Context, StringRef Str);
> @@ -72,17 +73,17 @@ public:
>      return get(Context, Str ? StringRef(Str) : StringRef());
>    }
> 
> -  StringRef getString() const { return getName(); }
> +  StringRef getString() const;
> 
> -  unsigned getLength() const { return (unsigned)getName().size(); }
> +  unsigned getLength() const { return (unsigned)getString().size(); }
> 
>    typedef StringRef::iterator iterator;
> 
>    /// \brief Pointer to the first byte of the string.
> -  iterator begin() const { return getName().begin(); }
> +  iterator begin() const { return getString().begin(); }
> 
>    /// \brief Pointer to one byte past the end of the string.
> -  iterator end() const { return getName().end(); }
> +  iterator end() const { return getString().end(); }
> 
>    /// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
>    static bool classof(const Value *V) {
> 
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=221960&r1=221959&r2=221960&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
> +++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Thu Nov 13 19:17:09 2014
> @@ -135,7 +135,7 @@ LLVMContextImpl::~LLVMContextImpl() {
>           "Destroying all MDNodes didn't empty the Context's sets.");
> 
>    // Destroy MDStrings.
> -  DeleteContainerSeconds(MDStringCache);
> +  MDStringCache.clear();
>  }
> 
>  // ConstantsContext anchors
> 
> Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=221960&r1=221959&r2=221960&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
> +++ llvm/trunk/lib/IR/LLVMContextImpl.h Thu Nov 13 19:17:09 2014
> @@ -261,7 +261,7 @@ public:
>    FoldingSet<AttributeSetImpl> AttrsLists;
>    FoldingSet<AttributeSetNode> AttrsSetNodes;
> 
> -  StringMap<Value*> MDStringCache;
> +  StringMap<MDString> MDStringCache;
> 
>    FoldingSet<MDNode> MDNodeSet;
> 
> 
> Modified: llvm/trunk/lib/IR/Metadata.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Metadata.cpp?rev=221960&r1=221959&r2=221960&view=diff
> ==============================================================================
> --- llvm/trunk/lib/IR/Metadata.cpp (original)
> +++ llvm/trunk/lib/IR/Metadata.cpp Thu Nov 13 19:17:09 2014
> @@ -37,13 +37,21 @@ MDString::MDString(LLVMContext &C)
>    : Value(Type::getMetadataTy(C), Value::MDStringVal) {}
> 
>  MDString *MDString::get(LLVMContext &Context, StringRef Str) {
> -  LLVMContextImpl *pImpl = Context.pImpl;
> -  StringMapEntry<Value*> &Entry =
> -    pImpl->MDStringCache.GetOrCreateValue(Str);
> -  Value *&S = Entry.getValue();
> -  if (!S) S = new MDString(Context);
> -  S->setValueName(&Entry);
> -  return cast<MDString>(S);
> +  auto &Store = Context.pImpl->MDStringCache;
> +  auto I = Store.find(Str);
> +  if (I != Store.end())
> +    return &I->second;
> +
> +  auto *Entry =
> +      StringMapEntry<MDString>::Create(Str, Store.getAllocator(), Context);
> 
> 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. 
> 
> For explicit conversions the idiom seems to be to have an 'emplace' function.
> 
> I think the right API design is to add an 'emplace' to StringMap and use it something like this:
> 
> Store.insert(std::piecewise_construct, std::forward_as_tuple(Str), std::forward_as_tuple(Context));
>  

`std::forward_as_tuple()` and `std::piecewise_construct` are new to me,
thanks for suggesting it.  I see that you're using this in
LexicalScopes.cpp.

It's not clear to me how to unpack the tuple to send into a
constructor when we're not leveraging `std::pair<>`.  I had a look at
the libcxx implementation of `utility`, and it seems to use an
unexposed class called `__tuple_indices` to do the magic.

Note that `StringMap` doesn't actually use a `std::pair<>`.
`StringMapEntry` has a similar API, but is distinct.

Am I missing something obvious?

Nevertheless, StringMap is pretty simple.  We don't care about
forwarding the key, just the value.  *IF* we were allowed to use
variadic templates, it'd be easy enough to implement:

    template <class... ArgsT>
    std::pair<iterator, bool> emplace(StringRef Key, ArgsT &&...Args);

This was my original plan, but then I remembered (incorrectly?) that
MSVC doesn't support variadic templates yet, so I just hacked in
something that works.



More information about the llvm-commits mailing list