[llvm] r299899 - Reland "[IR] Make AttributeSetNode public, avoid temporary AttributeList copies"

Richard Smith via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 11 14:12:41 PDT 2017


This is breaking the modules buildbots by introducing a cyclic dependency
between IR/Attributes.h (which is in the set of prerequisites for building
tablegen) and IR/AttributeSetNode.h (which is listed as being in the IR
module and thus potentially including tablegen-generated headers).

Should the new header be in the intrinsics_gen module in the module map?

On 10 April 2017 at 16:31, Reid Kleckner via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: rnk
> Date: Mon Apr 10 18:31:05 2017
> New Revision: 299899
>
> URL: http://llvm.org/viewvc/llvm-project?rev=299899&view=rev
> Log:
> Reland "[IR] Make AttributeSetNode public, avoid temporary AttributeList
> copies"
>
> This re-lands r299875.
>
> I introduced a bug in Clang code responsible for replacing K&R, no
> prototype declarations with a real function definition with a prototype.
> The bug was here:
>
>        // Collect any return attributes from the call.
>   -    if (oldAttrs.hasAttributes(llvm::AttributeList::ReturnIndex))
>   -      newAttrs.push_back(llvm::AttributeList::get(newFn->getContext(),
>   -
> oldAttrs.getRetAttributes()));
>   +    newAttrs.push_back(oldAttrs.getRetAttributes());
>
> Previously getRetAttributes() carried AttributeList::ReturnIndex in its
> AttributeList. Now that we return the AttributeSetNode* directly, it no
> longer carries that index, and we call this overload with a single node:
>   AttributeList::get(LLVMContext&, ArrayRef<AttributeSetNode*>)
>
> That aborted with an assertion on x86_32 targets. I added an explicit
> triple to the test and added CHECKs to help find issues like this in the
> future sooner.
>
> Added:
>     llvm/trunk/include/llvm/IR/AttributeSetNode.h
> Removed:
>     llvm/trunk/lib/IR/AttributeSetNode.h
> Modified:
>     llvm/trunk/include/llvm/IR/Attributes.h
>     llvm/trunk/lib/AsmParser/LLParser.cpp
>     llvm/trunk/lib/AsmParser/LLParser.h
>     llvm/trunk/lib/IR/AsmWriter.cpp
>     llvm/trunk/lib/IR/AttributeImpl.h
>     llvm/trunk/lib/IR/Attributes.cpp
>     llvm/trunk/lib/IR/Core.cpp
>     llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp
>     llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
>     llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
>     llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
>     llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
>     llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp
>     llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
>
> Added: llvm/trunk/include/llvm/IR/AttributeSetNode.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/IR/AttributeSetNode.h?rev=299899&view=auto
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/IR/AttributeSetNode.h (added)
> +++ llvm/trunk/include/llvm/IR/AttributeSetNode.h Mon Apr 10 18:31:05 2017
> @@ -0,0 +1,109 @@
> +//===-- AttributeSetNode.h - AttributeList Internal Node --------*- C++
> -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===------------------------------------------------------
> ----------------===//
> +///
> +/// \file
> +/// \brief This file defines the class that represents a group of
> attributes
> +/// that apply to one element: function, return type, or parameter.
> +///
> +//===------------------------------------------------------
> ----------------===//
> +
> +#ifndef LLVM_IR_ATTRIBUTESETNODE_H
> +#define LLVM_IR_ATTRIBUTESETNODE_H
> +
> +#include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/FoldingSet.h"
> +#include "llvm/ADT/Optional.h"
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/IR/Attributes.h"
> +#include "llvm/Support/TrailingObjects.h"
> +#include <algorithm>
> +#include <climits>
> +#include <cstdint>
> +#include <string>
> +#include <utility>
> +
> +namespace llvm {
> +
> +//===------------------------------------------------------
> ----------------===//
> +/// \class
> +/// \brief This class represents a group of attributes that apply to one
> +/// element: function, return type, or parameter.
> +class AttributeSetNode final
> +    : public FoldingSetNode,
> +      private TrailingObjects<AttributeSetNode, Attribute> {
> +  friend TrailingObjects;
> +
> +  unsigned NumAttrs; ///< Number of attributes in this node.
> +  /// Bitset with a bit for each available attribute Attribute::AttrKind.
> +  uint64_t AvailableAttrs;
> +
> +  AttributeSetNode(ArrayRef<Attribute> Attrs)
> +    : NumAttrs(Attrs.size()), AvailableAttrs(0) {
> +    static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) *
> CHAR_BIT,
> +                  "Too many attributes for AvailableAttrs");
> +    // There's memory after the node where we can store the entries in.
> +    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>(
> ));
> +
> +    for (Attribute I : *this) {
> +      if (!I.isStringAttribute()) {
> +        AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
> +      }
> +    }
> +  }
> +
> +public:
> +  // AttributesSetNode is uniqued, these should not be available.
> +  AttributeSetNode(const AttributeSetNode &) = delete;
> +  AttributeSetNode &operator=(const AttributeSetNode &) = delete;
> +
> +  void operator delete(void *p) { ::operator delete(p); }
> +
> +  static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B);
> +
> +  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
> +
> +  static AttributeSetNode *get(AttributeList AS, unsigned Index) {
> +    return AS.getAttributes(Index);
> +  }
> +
> +  /// \brief Return the number of attributes this AttributeList contains.
> +  unsigned getNumAttributes() const { return NumAttrs; }
> +
> +  bool hasAttribute(Attribute::AttrKind Kind) const {
> +    return AvailableAttrs & ((uint64_t)1) << Kind;
> +  }
> +  bool hasAttribute(StringRef Kind) const;
> +  bool hasAttributes() const { return NumAttrs != 0; }
> +
> +  Attribute getAttribute(Attribute::AttrKind Kind) const;
> +  Attribute getAttribute(StringRef Kind) const;
> +
> +  unsigned getAlignment() const;
> +  unsigned getStackAlignment() const;
> +  uint64_t getDereferenceableBytes() const;
> +  uint64_t getDereferenceableOrNullBytes() const;
> +  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
> +  std::string getAsString(bool InAttrGrp) const;
> +
> +  typedef const Attribute *iterator;
> +  iterator begin() const { return getTrailingObjects<Attribute>(); }
> +  iterator end() const { return begin() + NumAttrs; }
> +
> +  void Profile(FoldingSetNodeID &ID) const {
> +    Profile(ID, makeArrayRef(begin(), end()));
> +  }
> +  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList)
> {
> +    for (const auto &Attr : AttrList)
> +      Attr.Profile(ID);
> +  }
> +};
> +
> +} // end namespace llvm
> +
> +#endif // LLVM_IR_ATTRIBUTESETNODE_H
>
> Modified: llvm/trunk/include/llvm/IR/Attributes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/
> llvm/IR/Attributes.h?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/include/llvm/IR/Attributes.h (original)
> +++ llvm/trunk/include/llvm/IR/Attributes.h Mon Apr 10 18:31:05 2017
> @@ -221,19 +221,26 @@ private:
>    /// the empty attributes list.
>    AttributeListImpl *pImpl = nullptr;
>
> -  /// \brief The attributes for the specified index are returned.
> -  AttributeSetNode *getAttributes(unsigned Index) const;
> -
> +public:
>    /// \brief Create an AttributeList with the specified parameters in it.
>    static AttributeList get(LLVMContext &C,
>                             ArrayRef<std::pair<unsigned, Attribute>>
> Attrs);
>    static AttributeList
>    get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *>>
> Attrs);
>
> +  /// \brief Create an AttributeList from a vector of AttributeSetNodes.
> The
> +  /// index of each set is implied by its position in the array \p Attrs:
> +  ///   0      : Return attributes
> +  /// 1 to n-1 : Argument attributes
> +  ///   n      : Function attributes
> +  /// Any element that has no entries should be left null.
> +  static AttributeList get(LLVMContext &C, ArrayRef<AttributeSetNode *>
> Attrs);
> +
>    static AttributeList
>    getImpl(LLVMContext &C,
>            ArrayRef<std::pair<unsigned, AttributeSetNode *>> Attrs);
>
> +private:
>    explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
>
>  public:
> @@ -272,6 +279,12 @@ public:
>    AttributeList addAttributes(LLVMContext &C, unsigned Index,
>                                AttributeList Attrs) const;
>
> +  AttributeList addAttributes(LLVMContext &C, unsigned Index,
> +                              AttributeSetNode *AS) const;
> +
> +  AttributeList addAttributes(LLVMContext &C, unsigned Index,
> +                              const AttrBuilder &B) const;
> +
>    /// \brief Remove the specified attribute at the specified index from
> this
>    /// attribute list. Because attribute lists are immutable, this returns
> the
>    /// new list.
> @@ -296,6 +309,11 @@ public:
>    AttributeList removeAttributes(LLVMContext &C, unsigned Index,
>                                   const AttrBuilder &Attrs) const;
>
> +  /// \brief Remove all attributes at the specified index from this
> +  /// attribute list. Because attribute lists are immutable, this returns
> the
> +  /// new list.
> +  AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;
> +
>    /// \brief Add the dereferenceable attribute to the attribute set at
> the given
>    /// index. Because attribute sets are immutable, this returns a new set.
>    AttributeList addDereferenceableAttr(LLVMContext &C, unsigned Index,
> @@ -321,13 +339,16 @@ public:
>    LLVMContext &getContext() const;
>
>    /// \brief The attributes for the specified index are returned.
> -  AttributeList getParamAttributes(unsigned Index) const;
> +  AttributeSetNode *getAttributes(unsigned Index) const;
> +
> +  /// \brief The attributes for the specified index are returned.
> +  AttributeSetNode *getParamAttributes(unsigned Index) const;
>
>    /// \brief The attributes for the ret value are returned.
> -  AttributeList getRetAttributes() const;
> +  AttributeSetNode *getRetAttributes() const;
>
>    /// \brief The function attributes are returned.
> -  AttributeList getFnAttributes() const;
> +  AttributeSetNode *getFnAttributes() const;
>
>    /// \brief Return true if the attribute exists at the given index.
>    bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
> @@ -462,6 +483,7 @@ public:
>      addAttribute(A);
>    }
>    AttrBuilder(AttributeList AS, unsigned Idx);
> +  AttrBuilder(AttributeSetNode *AS);
>
>    void clear();
>
> @@ -478,7 +500,7 @@ public:
>    AttrBuilder &removeAttribute(Attribute::AttrKind Val);
>
>    /// \brief Remove the attributes from the builder.
> -  AttrBuilder &removeAttributes(AttributeList A, uint64_t Index);
> +  AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
>
>    /// \brief Remove the target-dependent attribute to the builder.
>    AttrBuilder &removeAttribute(StringRef A);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> AsmParser/LLParser.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Apr 10 18:31:05 2017
> @@ -19,6 +19,7 @@
>  #include "llvm/ADT/STLExtras.h"
>  #include "llvm/AsmParser/SlotMapping.h"
>  #include "llvm/IR/Argument.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/AutoUpgrade.h"
>  #include "llvm/IR/BasicBlock.h"
>  #include "llvm/IR/CallingConv.h"
> @@ -131,9 +132,8 @@ bool LLParser::ValidateEndOfModule() {
>
>      if (Function *Fn = dyn_cast<Function>(V)) {
>        AttributeList AS = Fn->getAttributes();
> -      AttrBuilder FnAttrs(AS.getFnAttributes(),
> AttributeList::FunctionIndex);
> -      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
> -                               AS.getFnAttributes());
> +      AttrBuilder FnAttrs(AS.getFnAttributes());
> +      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
>
>        FnAttrs.merge(B);
>
> @@ -150,9 +150,8 @@ bool LLParser::ValidateEndOfModule() {
>        Fn->setAttributes(AS);
>      } else if (CallInst *CI = dyn_cast<CallInst>(V)) {
>        AttributeList AS = CI->getAttributes();
> -      AttrBuilder FnAttrs(AS.getFnAttributes(),
> AttributeList::FunctionIndex);
> -      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
> -                               AS.getFnAttributes());
> +      AttrBuilder FnAttrs(AS.getFnAttributes());
> +      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
>        FnAttrs.merge(B);
>        AS = AS.addAttributes(
>            Context, AttributeList::FunctionIndex,
> @@ -160,9 +159,8 @@ bool LLParser::ValidateEndOfModule() {
>        CI->setAttributes(AS);
>      } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) {
>        AttributeList AS = II->getAttributes();
> -      AttrBuilder FnAttrs(AS.getFnAttributes(),
> AttributeList::FunctionIndex);
> -      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
> -                               AS.getFnAttributes());
> +      AttrBuilder FnAttrs(AS.getFnAttributes());
> +      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
>        FnAttrs.merge(B);
>        AS = AS.addAttributes(
>            Context, AttributeList::FunctionIndex,
> @@ -2123,7 +2121,6 @@ bool LLParser::ParseParameterList(SmallV
>    if (ParseToken(lltok::lparen, "expected '(' in call"))
>      return true;
>
> -  unsigned AttrIndex = 1;
>    while (Lex.getKind() != lltok::rparen) {
>      // If this isn't the first argument, we need a comma.
>      if (!ArgList.empty() &&
> @@ -2158,7 +2155,7 @@ bool LLParser::ParseParameterList(SmallV
>          return true;
>      }
>      ArgList.push_back(ParamInfo(
> -        ArgLoc, V, AttributeList::get(V->getContext(), AttrIndex++,
> ArgAttrs)));
> +        ArgLoc, V, AttributeSetNode::get(V->getContext(), ArgAttrs)));
>    }
>
>    if (IsMustTailCall && InVarArgsFunc)
> @@ -2263,9 +2260,8 @@ bool LLParser::ParseArgumentList(SmallVe
>      if (!FunctionType::isValidArgumentType(ArgTy))
>        return Error(TypeLoc, "invalid type for function argument");
>
> -    unsigned AttrIndex = 1;
> -    ArgList.emplace_back(TypeLoc, ArgTy, AttributeList::get(ArgTy->
> getContext(),
> -                                                            AttrIndex++,
> Attrs),
> +    ArgList.emplace_back(TypeLoc, ArgTy,
> +                         AttributeSetNode::get(ArgTy->getContext(),
> Attrs),
>                           std::move(Name));
>
>      while (EatIfPresent(lltok::comma)) {
> @@ -2292,10 +2288,9 @@ bool LLParser::ParseArgumentList(SmallVe
>        if (!ArgTy->isFirstClassType())
>          return Error(TypeLoc, "invalid type for function argument");
>
> -      ArgList.emplace_back(
> -          TypeLoc, ArgTy,
> -          AttributeList::get(ArgTy->getContext(), AttrIndex++, Attrs),
> -          std::move(Name));
> +      ArgList.emplace_back(TypeLoc, ArgTy,
> +                           AttributeSetNode::get(ArgTy->getContext(),
> Attrs),
> +                           std::move(Name));
>      }
>    }
>
> @@ -2319,7 +2314,7 @@ bool LLParser::ParseFunctionType(Type *&
>    for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
>      if (!ArgList[i].Name.empty())
>        return Error(ArgList[i].Loc, "argument name invalid in function
> type");
> -    if (ArgList[i].Attrs.hasAttributes(i + 1))
> +    if (ArgList[i].Attrs)
>        return Error(ArgList[i].Loc,
>                     "argument attributes invalid in function type");
>    }
> @@ -4768,23 +4763,16 @@ bool LLParser::ParseFunctionHeader(Funct
>    // Okay, if we got here, the function is syntactically valid.  Convert
> types
>    // and do semantic checks.
>    std::vector<Type*> ParamTypeList;
> -  SmallVector<AttributeList, 8> Attrs;
> +  SmallVector<AttributeSetNode *, 8> Attrs;
>
> -  if (RetAttrs.hasAttributes())
> -    Attrs.push_back(AttributeList::get(RetType->getContext(),
> -                                       AttributeList::ReturnIndex,
> RetAttrs));
> +  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
>
>    for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
>      ParamTypeList.push_back(ArgList[i].Ty);
> -    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
> -      AttrBuilder B(ArgList[i].Attrs, i + 1);
> -      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1,
> B));
> -    }
> +    Attrs.push_back(ArgList[i].Attrs);
>    }
>
> -  if (FuncAttrs.hasAttributes())
> -    Attrs.push_back(AttributeList::get(
> -        RetType->getContext(), AttributeList::FunctionIndex, FuncAttrs));
> +  Attrs.push_back(AttributeSetNode::get(Context, FuncAttrs));
>
>    AttributeList PAL = AttributeList::get(Context, Attrs);
>
> @@ -5396,10 +5384,8 @@ bool LLParser::ParseInvoke(Instruction *
>      return true;
>
>    // Set up the Attribute for the function.
> -  SmallVector<AttributeList, 8> Attrs;
> -  if (RetAttrs.hasAttributes())
> -    Attrs.push_back(AttributeList::get(RetType->getContext(),
> -                                       AttributeList::ReturnIndex,
> RetAttrs));
> +  SmallVector<AttributeSetNode *, 8> Attrs;
> +  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
>
>    SmallVector<Value*, 8> Args;
>
> @@ -5419,22 +5405,16 @@ bool LLParser::ParseInvoke(Instruction *
>        return Error(ArgList[i].Loc, "argument is not of expected type '" +
>                     getTypeString(ExpectedTy) + "'");
>      Args.push_back(ArgList[i].V);
> -    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
> -      AttrBuilder B(ArgList[i].Attrs, i + 1);
> -      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1,
> B));
> -    }
> +    Attrs.push_back(ArgList[i].Attrs);
>    }
>
>    if (I != E)
>      return Error(CallLoc, "not enough parameters specified for call");
>
> -  if (FnAttrs.hasAttributes()) {
> -    if (FnAttrs.hasAlignmentAttr())
> -      return Error(CallLoc, "invoke instructions may not have an
> alignment");
> +  if (FnAttrs.hasAlignmentAttr())
> +    return Error(CallLoc, "invoke instructions may not have an
> alignment");
>
> -    Attrs.push_back(AttributeList::get(RetType->getContext(),
> -                                       AttributeList::FunctionIndex,
> FnAttrs));
> -  }
> +  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
>
>    // Finish off the Attribute and check them
>    AttributeList PAL = AttributeList::get(Context, Attrs);
> @@ -5998,10 +5978,8 @@ bool LLParser::ParseCall(Instruction *&I
>      return true;
>
>    // Set up the Attribute for the function.
> -  SmallVector<AttributeList, 8> Attrs;
> -  if (RetAttrs.hasAttributes())
> -    Attrs.push_back(AttributeList::get(RetType->getContext(),
> -                                       AttributeList::ReturnIndex,
> RetAttrs));
> +  SmallVector<AttributeSetNode *, 8> Attrs;
> +  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
>
>    SmallVector<Value*, 8> Args;
>
> @@ -6021,22 +5999,16 @@ bool LLParser::ParseCall(Instruction *&I
>        return Error(ArgList[i].Loc, "argument is not of expected type '" +
>                     getTypeString(ExpectedTy) + "'");
>      Args.push_back(ArgList[i].V);
> -    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
> -      AttrBuilder B(ArgList[i].Attrs, i + 1);
> -      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1,
> B));
> -    }
> +    Attrs.push_back(ArgList[i].Attrs);
>    }
>
>    if (I != E)
>      return Error(CallLoc, "not enough parameters specified for call");
>
> -  if (FnAttrs.hasAttributes()) {
> -    if (FnAttrs.hasAlignmentAttr())
> -      return Error(CallLoc, "call instructions may not have an
> alignment");
> +  if (FnAttrs.hasAlignmentAttr())
> +    return Error(CallLoc, "call instructions may not have an alignment");
>
> -    Attrs.push_back(AttributeList::get(RetType->getContext(),
> -                                       AttributeList::FunctionIndex,
> FnAttrs));
> -  }
> +  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
>
>    // Finish off the Attribute and check them
>    AttributeList PAL = AttributeList::get(Context, Attrs);
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> AsmParser/LLParser.h?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/AsmParser/LLParser.h (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.h Mon Apr 10 18:31:05 2017
> @@ -397,8 +397,8 @@ namespace llvm {
>      struct ParamInfo {
>        LocTy Loc;
>        Value *V;
> -      AttributeList Attrs;
> -      ParamInfo(LocTy loc, Value *v, AttributeList attrs)
> +      AttributeSetNode *Attrs;
> +      ParamInfo(LocTy loc, Value *v, AttributeSetNode *attrs)
>            : Loc(loc), V(v), Attrs(attrs) {}
>      };
>      bool ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
> @@ -450,9 +450,9 @@ namespace llvm {
>      struct ArgInfo {
>        LocTy Loc;
>        Type *Ty;
> -      AttributeList Attrs;
> +      AttributeSetNode *Attrs;
>        std::string Name;
> -      ArgInfo(LocTy L, Type *ty, AttributeList Attr, const std::string &N)
> +      ArgInfo(LocTy L, Type *ty, AttributeSetNode *Attr, const
> std::string &N)
>            : Loc(L), Ty(ty), Attrs(Attr), Name(N) {}
>      };
>      bool ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool
> &isVarArg);
>
> Modified: llvm/trunk/lib/IR/AsmWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/
> AsmWriter.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/IR/AsmWriter.cpp (original)
> +++ llvm/trunk/lib/IR/AsmWriter.cpp Mon Apr 10 18:31:05 2017
> @@ -21,6 +21,8 @@
>  #include "llvm/ADT/SmallString.h"
>  #include "llvm/ADT/StringExtras.h"
>  #include "llvm/IR/AssemblyAnnotationWriter.h"
> +#include "llvm/IR/AttributeSetNode.h"
> +#include "llvm/IR/Attributes.h"
>  #include "llvm/IR/CFG.h"
>  #include "llvm/IR/CallingConv.h"
>  #include "llvm/IR/Constants.h"
> @@ -604,7 +606,7 @@ private:
>    unsigned mdnNext;
>
>    /// asMap - The slot map for attribute sets.
> -  DenseMap<AttributeList, unsigned> asMap;
> +  DenseMap<AttributeSetNode *, unsigned> asMap;
>    unsigned asNext;
>  public:
>    /// Construct from a module.
> @@ -627,7 +629,7 @@ public:
>    int getLocalSlot(const Value *V);
>    int getGlobalSlot(const GlobalValue *V);
>    int getMetadataSlot(const MDNode *N);
> -  int getAttributeGroupSlot(AttributeList AS);
> +  int getAttributeGroupSlot(AttributeSetNode *AS);
>
>    /// If you'd like to deal with a function instead of just a module, use
>    /// this method to get its data into the SlotTracker.
> @@ -650,8 +652,8 @@ public:
>    unsigned mdn_size() const { return mdnMap.size(); }
>    bool mdn_empty() const { return mdnMap.empty(); }
>
> -  /// AttributeList map iterators.
> -  typedef DenseMap<AttributeList, unsigned>::iterator as_iterator;
> +  /// AttributeSetNode map iterators.
> +  typedef DenseMap<AttributeSetNode *, unsigned>::iterator as_iterator;
>    as_iterator as_begin()   { return asMap.begin(); }
>    as_iterator as_end()     { return asMap.end(); }
>    unsigned as_size() const { return asMap.size(); }
> @@ -671,8 +673,8 @@ private:
>    /// CreateFunctionSlot - Insert the specified Value* into the slot
> table.
>    void CreateFunctionSlot(const Value *V);
>
> -  /// \brief Insert the specified AttributeList into the slot table.
> -  void CreateAttributeSetSlot(AttributeList AS);
> +  /// \brief Insert the specified AttributeSetNode into the slot table.
> +  void CreateAttributeSetSlot(AttributeSetNode *AS);
>
>    /// Add all of the module level global variables (and their
> initializers)
>    /// and function declarations, but not the contents of those functions.
> @@ -831,8 +833,8 @@ void SlotTracker::processModule() {
>
>      // Add all the function attributes to the table.
>      // FIXME: Add attributes of other objects?
> -    AttributeList FnAttrs = F.getAttributes().getFnAttributes();
> -    if (FnAttrs.hasAttributes(AttributeList::FunctionIndex))
> +    AttributeSetNode *FnAttrs = F.getAttributes().getFnAttributes();
> +    if (FnAttrs)
>        CreateAttributeSetSlot(FnAttrs);
>    }
>
> @@ -869,13 +871,13 @@ void SlotTracker::processFunction() {
>        // target may not be linked into the optimizer.
>        if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
>          // Add all the call attributes to the table.
> -        AttributeList Attrs = CI->getAttributes().getFnAttributes();
> -        if (Attrs.hasAttributes(AttributeList::FunctionIndex))
> +        AttributeSetNode *Attrs = CI->getAttributes().getFnAttributes();
> +        if (Attrs)
>            CreateAttributeSetSlot(Attrs);
>        } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
>          // Add all the call attributes to the table.
> -        AttributeList Attrs = II->getAttributes().getFnAttributes();
> -        if (Attrs.hasAttributes(AttributeList::FunctionIndex))
> +        AttributeSetNode *Attrs = II->getAttributes().getFnAttributes();
> +        if (Attrs)
>            CreateAttributeSetSlot(Attrs);
>        }
>      }
> @@ -961,11 +963,11 @@ int SlotTracker::getLocalSlot(const Valu
>    return FI == fMap.end() ? -1 : (int)FI->second;
>  }
>
> -int SlotTracker::getAttributeGroupSlot(AttributeList AS) {
> +int SlotTracker::getAttributeGroupSlot(AttributeSetNode *AS) {
>    // Check for uninitialized state and do lazy initialization.
>    initialize();
>
> -  // Find the AttributeList in the module map.
> +  // Find the AttributeSetNode in the module map.
>    as_iterator AI = asMap.find(AS);
>    return AI == asMap.end() ? -1 : (int)AI->second;
>  }
> @@ -1015,9 +1017,8 @@ void SlotTracker::CreateMetadataSlot(con
>        CreateMetadataSlot(Op);
>  }
>
> -void SlotTracker::CreateAttributeSetSlot(AttributeList AS) {
> -  assert(AS.hasAttributes(AttributeList::FunctionIndex) &&
> -         "Doesn't need a slot!");
> +void SlotTracker::CreateAttributeSetSlot(AttributeSetNode *AS) {
> +  assert(AS && "Doesn't need a slot!");
>
>    as_iterator I = asMap.find(AS);
>    if (I != asMap.end())
> @@ -2606,17 +2607,10 @@ void AssemblyWriter::printFunction(const
>
>    const AttributeList &Attrs = F->getAttributes();
>    if (Attrs.hasAttributes(AttributeList::FunctionIndex)) {
> -    AttributeList AS = Attrs.getFnAttributes();
> +    AttributeSetNode *AS = Attrs.getFnAttributes();
>      std::string AttrStr;
>
> -    unsigned Idx = 0;
> -    for (unsigned E = AS.getNumSlots(); Idx != E; ++Idx)
> -      if (AS.getSlotIndex(Idx) == AttributeList::FunctionIndex)
> -        break;
> -
> -    for (AttributeList::iterator I = AS.begin(Idx), E = AS.end(Idx); I !=
> E;
> -         ++I) {
> -      Attribute Attr = *I;
> +    for (const Attribute &Attr : *AS) {
>        if (!Attr.isStringAttribute()) {
>          if (!AttrStr.empty()) AttrStr += ' ';
>          AttrStr += Attr.getAsString();
> @@ -3256,7 +3250,7 @@ void AssemblyWriter::printMDNodeBody(con
>  }
>
>  void AssemblyWriter::writeAllAttributeGroups() {
> -  std::vector<std::pair<AttributeList, unsigned>> asVec;
> +  std::vector<std::pair<AttributeSetNode *, unsigned>> asVec;
>    asVec.resize(Machine.as_size());
>
>    for (SlotTracker::as_iterator I = Machine.as_begin(), E =
> Machine.as_end();
> @@ -3265,7 +3259,7 @@ void AssemblyWriter::writeAllAttributeGr
>
>    for (const auto &I : asVec)
>      Out << "attributes #" << I.second << " = { "
> -        << I.first.getAsString(AttributeList::FunctionIndex, true) << "
> }\n";
> +        << I.first->getAsString(true) << " }\n";
>  }
>
>  void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
>
> Modified: llvm/trunk/lib/IR/AttributeImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/
> AttributeImpl.h?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/IR/AttributeImpl.h (original)
> +++ llvm/trunk/lib/IR/AttributeImpl.h Mon Apr 10 18:31:05 2017
> @@ -16,10 +16,10 @@
>  #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H
>  #define LLVM_LIB_IR_ATTRIBUTEIMPL_H
>
> -#include "AttributeSetNode.h"
>  #include "llvm/ADT/ArrayRef.h"
>  #include "llvm/ADT/FoldingSet.h"
>  #include "llvm/ADT/StringRef.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/Attributes.h"
>  #include "llvm/Support/TrailingObjects.h"
>  #include <algorithm>
>
> Removed: llvm/trunk/lib/IR/AttributeSetNode.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/
> AttributeSetNode.h?rev=299898&view=auto
> ============================================================
> ==================
> --- llvm/trunk/lib/IR/AttributeSetNode.h (original)
> +++ llvm/trunk/lib/IR/AttributeSetNode.h (removed)
> @@ -1,107 +0,0 @@
> -//===-- AttributeSetNode.h - AttributeList Internal Node ---------*- C++
> -//-*-===//
> -//
> -//                     The LLVM Compiler Infrastructure
> -//
> -// This file is distributed under the University of Illinois Open Source
> -// License. See LICENSE.TXT for details.
> -//
> -//===------------------------------------------------------
> ----------------===//
> -///
> -/// \file
> -/// \brief This file defines the node class used internally by
> AttributeList.
> -///
> -//===------------------------------------------------------
> ----------------===//
> -
> -#ifndef LLVM_IR_ATTRIBUTESETNODE_H
> -#define LLVM_IR_ATTRIBUTESETNODE_H
> -
> -#include "llvm/ADT/ArrayRef.h"
> -#include "llvm/ADT/FoldingSet.h"
> -#include "llvm/ADT/Optional.h"
> -#include "llvm/ADT/StringRef.h"
> -#include "llvm/IR/Attributes.h"
> -#include "llvm/Support/TrailingObjects.h"
> -#include <algorithm>
> -#include <climits>
> -#include <cstdint>
> -#include <string>
> -#include <utility>
> -
> -namespace llvm {
> -
> -//===------------------------------------------------------
> ----------------===//
> -/// \class
> -/// \brief This class represents a group of attributes that apply to one
> -/// element: function, return type, or parameter.
> -class AttributeSetNode final
> -    : public FoldingSetNode,
> -      private TrailingObjects<AttributeSetNode, Attribute> {
> -  friend TrailingObjects;
> -
> -  unsigned NumAttrs; ///< Number of attributes in this node.
> -  /// Bitset with a bit for each available attribute Attribute::AttrKind.
> -  uint64_t AvailableAttrs;
> -
> -  AttributeSetNode(ArrayRef<Attribute> Attrs)
> -    : NumAttrs(Attrs.size()), AvailableAttrs(0) {
> -    static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) *
> CHAR_BIT,
> -                  "Too many attributes for AvailableAttrs");
> -    // There's memory after the node where we can store the entries in.
> -    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>(
> ));
> -
> -    for (Attribute I : *this) {
> -      if (!I.isStringAttribute()) {
> -        AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
> -      }
> -    }
> -  }
> -
> -public:
> -  // AttributesSetNode is uniqued, these should not be available.
> -  AttributeSetNode(const AttributeSetNode &) = delete;
> -  AttributeSetNode &operator=(const AttributeSetNode &) = delete;
> -
> -  void operator delete(void *p) { ::operator delete(p); }
> -
> -  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
> -
> -  static AttributeSetNode *get(AttributeList AS, unsigned Index) {
> -    return AS.getAttributes(Index);
> -  }
> -
> -  /// \brief Return the number of attributes this AttributeList contains.
> -  unsigned getNumAttributes() const { return NumAttrs; }
> -
> -  bool hasAttribute(Attribute::AttrKind Kind) const {
> -    return AvailableAttrs & ((uint64_t)1) << Kind;
> -  }
> -  bool hasAttribute(StringRef Kind) const;
> -  bool hasAttributes() const { return NumAttrs != 0; }
> -
> -  Attribute getAttribute(Attribute::AttrKind Kind) const;
> -  Attribute getAttribute(StringRef Kind) const;
> -
> -  unsigned getAlignment() const;
> -  unsigned getStackAlignment() const;
> -  uint64_t getDereferenceableBytes() const;
> -  uint64_t getDereferenceableOrNullBytes() const;
> -  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
> -  std::string getAsString(bool InAttrGrp) const;
> -
> -  typedef const Attribute *iterator;
> -  iterator begin() const { return getTrailingObjects<Attribute>(); }
> -  iterator end() const { return begin() + NumAttrs; }
> -
> -  void Profile(FoldingSetNodeID &ID) const {
> -    Profile(ID, makeArrayRef(begin(), end()));
> -  }
> -  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList)
> {
> -    for (const auto &Attr : AttrList)
> -      Attr.Profile(ID);
> -  }
> -};
> -
> -} // end namespace llvm
> -
> -#endif // LLVM_IR_ATTRIBUTESETNODE_H
>
> Modified: llvm/trunk/lib/IR/Attributes.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/
> Attributes.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/IR/Attributes.cpp (original)
> +++ llvm/trunk/lib/IR/Attributes.cpp Mon Apr 10 18:31:05 2017
> @@ -14,7 +14,6 @@
>  //===-------------------------------------------------------
> ---------------===//
>
>  #include "AttributeImpl.h"
> -#include "AttributeSetNode.h"
>  #include "LLVMContextImpl.h"
>  #include "llvm/ADT/ArrayRef.h"
>  #include "llvm/ADT/FoldingSet.h"
> @@ -24,6 +23,7 @@
>  #include "llvm/ADT/StringExtras.h"
>  #include "llvm/ADT/StringRef.h"
>  #include "llvm/ADT/Twine.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/Attributes.h"
>  #include "llvm/IR/Function.h"
>  #include "llvm/IR/LLVMContext.h"
> @@ -527,6 +527,48 @@ AttributeSetNode *AttributeSetNode::get(
>    return PA;
>  }
>
> +AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const
> AttrBuilder &B) {
> +  // Add target-independent attributes.
> +  SmallVector<Attribute, 8> Attrs;
> +  for (Attribute::AttrKind Kind = Attribute::None;
> +       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind +
> 1)) {
> +    if (!B.contains(Kind))
> +      continue;
> +
> +    Attribute Attr;
> +    switch (Kind) {
> +    case Attribute::Alignment:
> +      Attr = Attribute::getWithAlignment(C, B.getAlignment());
> +      break;
> +    case Attribute::StackAlignment:
> +      Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
> +      break;
> +    case Attribute::Dereferenceable:
> +      Attr = Attribute::getWithDereferenceableBytes(
> +          C, B.getDereferenceableBytes());
> +      break;
> +    case Attribute::DereferenceableOrNull:
> +      Attr = Attribute::getWithDereferenceableOrNullBytes(
> +          C, B.getDereferenceableOrNullBytes());
> +      break;
> +    case Attribute::AllocSize: {
> +      auto A = B.getAllocSizeArgs();
> +      Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
> +      break;
> +    }
> +    default:
> +      Attr = Attribute::get(C, Kind);
> +    }
> +    Attrs.push_back(Attr);
> +  }
> +
> +  // Add target-dependent (string) attributes.
> +  for (const auto &TDA : B.td_attrs())
> +    Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
> +
> +  return get(C, Attrs);
> +}
> +
>  bool AttributeSetNode::hasAttribute(StringRef Kind) const {
>    for (Attribute I : *this)
>      if (I.hasAttribute(Kind))
> @@ -612,6 +654,19 @@ LLVM_DUMP_METHOD void AttributeListImpl:
>
>  AttributeList AttributeList::getImpl(
>      LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *>>
> Attrs) {
> +  assert(!Attrs.empty() && "creating pointless AttributeList");
> +#ifndef NDEBUG
> +  unsigned LastIndex = 0;
> +  bool IsFirst = true;
> +  for (const auto &AttrPair : Attrs) {
> +    assert((IsFirst || LastIndex < AttrPair.first) &&
> +           "unsorted or duplicate AttributeList indices");
> +    assert(AttrPair.second && "pointless AttributeList slot");
> +    LastIndex = AttrPair.first;
> +    IsFirst = false;
> +  }
> +#endif
> +
>    LLVMContextImpl *pImpl = C.pImpl;
>    FoldingSetNodeID ID;
>    AttributeListImpl::Profile(ID, Attrs);
> @@ -680,50 +735,32 @@ AttributeList::get(LLVMContext &C,
>    return getImpl(C, Attrs);
>  }
>
> +AttributeList AttributeList::get(LLVMContext &C,
> ArrayRef<AttributeSetNode*> Attrs) {
> +  assert(Attrs.size() >= 2 &&
> +         "should always have function and return attr slots");
> +  SmallVector<std::pair<unsigned, AttributeSetNode *>, 8> AttrPairs;
> +  size_t Index = 0;
> +  for (AttributeSetNode *AS : Attrs) {
> +    if (AS) {
> +      // If this is the last AttributeSetNode, it's for the function.
> +      if (Index == Attrs.size() - 1)
> +        Index = AttributeList::FunctionIndex;
> +      AttrPairs.emplace_back(Index, AS);
> +    }
> +    ++Index;
> +  }
> +  if (AttrPairs.empty())
> +    return AttributeList();
> +  return getImpl(C, AttrPairs);
> +}
> +
>  AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
>                                   const AttrBuilder &B) {
>    if (!B.hasAttributes())
>      return AttributeList();
> -
> -  // Add target-independent attributes.
> -  SmallVector<std::pair<unsigned, Attribute>, 8> Attrs;
> -  for (Attribute::AttrKind Kind = Attribute::None;
> -       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind +
> 1)) {
> -    if (!B.contains(Kind))
> -      continue;
> -
> -    Attribute Attr;
> -    switch (Kind) {
> -    case Attribute::Alignment:
> -      Attr = Attribute::getWithAlignment(C, B.getAlignment());
> -      break;
> -    case Attribute::StackAlignment:
> -      Attr = Attribute::getWithStackAlignment(C, B.getStackAlignment());
> -      break;
> -    case Attribute::Dereferenceable:
> -      Attr = Attribute::getWithDereferenceableBytes(
> -          C, B.getDereferenceableBytes());
> -      break;
> -    case Attribute::DereferenceableOrNull:
> -      Attr = Attribute::getWithDereferenceableOrNullBytes(
> -          C, B.getDereferenceableOrNullBytes());
> -      break;
> -    case Attribute::AllocSize: {
> -      auto A = B.getAllocSizeArgs();
> -      Attr = Attribute::getWithAllocSizeArgs(C, A.first, A.second);
> -      break;
> -    }
> -    default:
> -      Attr = Attribute::get(C, Kind);
> -    }
> -    Attrs.emplace_back(Index, Attr);
> -  }
> -
> -  // Add target-dependent (string) attributes.
> -  for (const auto &TDA : B.td_attrs())
> -    Attrs.emplace_back(Index, Attribute::get(C, TDA.first, TDA.second));
> -
> -  return get(C, Attrs);
> +  AttributeSetNode *ASN = AttributeSetNode::get(C, B);
> +  std::pair<unsigned, AttributeSetNode *> Arr[1] = {{Index, ASN}};
> +  return getImpl(C, Arr);
>  }
>
>  AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
> @@ -791,31 +828,31 @@ AttributeList AttributeList::addAttribut
>  AttributeList AttributeList::addAttribute(LLVMContext &C,
>                                            ArrayRef<unsigned> Indices,
>                                            Attribute A) const {
> -  unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;
> -  auto IdxI = Indices.begin(), IdxE = Indices.end();
> -  SmallVector<AttributeList, 4> AttrSet;
> +  assert(std::is_sorted(Indices.begin(), Indices.end()));
>
> -  while (I != E && IdxI != IdxE) {
> -    if (getSlotIndex(I) < *IdxI)
> -      AttrSet.emplace_back(getSlotAttributes(I++));
> -    else if (getSlotIndex(I) > *IdxI)
> -      AttrSet.emplace_back(AttributeList::get(C, std::make_pair(*IdxI++,
> A)));
> -    else {
> -      AttrBuilder B(getSlotAttributes(I), *IdxI);
> -      B.addAttribute(A);
> -      AttrSet.emplace_back(AttributeList::get(C, *IdxI, B));
> +  unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;
> +  SmallVector<IndexAttrPair, 4> AttrVec;
> +  for (unsigned Index : Indices) {
> +    // Add all attribute slots before the current index.
> +    for (; I < E && getSlotIndex(I) < Index; ++I)
> +      AttrVec.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
> +
> +    // Add the attribute at this index. If we already have attributes at
> this
> +    // index, merge them into a new set.
> +    AttrBuilder B;
> +    if (I < E && getSlotIndex(I) == Index) {
> +      B.merge(AttrBuilder(pImpl->getSlotNode(I)));
>        ++I;
> -      ++IdxI;
>      }
> +    B.addAttribute(A);
> +    AttrVec.emplace_back(Index, AttributeSetNode::get(C, B));
>    }
>
> -  while (I != E)
> -    AttrSet.emplace_back(getSlotAttributes(I++));
> +  // Add remaining attributes.
> +  for (; I < E; ++I)
> +    AttrVec.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
>
> -  while (IdxI != IdxE)
> -    AttrSet.emplace_back(AttributeList::get(C, std::make_pair(*IdxI++,
> A)));
> -
> -  return get(C, AttrSet);
> +  return get(C, AttrVec);
>  }
>
>  AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned
> Index,
> @@ -823,51 +860,58 @@ AttributeList AttributeList::addAttribut
>    if (!pImpl) return Attrs;
>    if (!Attrs.pImpl) return *this;
>
> +  return addAttributes(C, Index, Attrs.getAttributes(Index));
> +}
> +
> +AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned
> Index,
> +                                           AttributeSetNode *AS) const {
> +  if (!AS)
> +    return *this;
> +
>  #ifndef NDEBUG
>    // FIXME it is not obvious how this should work for alignment. For now,
> say
>    // we can't change a known alignment.
>    unsigned OldAlign = getParamAlignment(Index);
> -  unsigned NewAlign = Attrs.getParamAlignment(Index);
> +  unsigned NewAlign = AS->getAlignment();
>    assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
>           "Attempt to change alignment!");
>  #endif
>
> -  // Add the attribute slots before the one we're trying to add.
> -  SmallVector<AttributeList, 4> AttrSet;
> +  SmallVector<std::pair<unsigned, AttributeSetNode *>, 4> AttrSet;
>    uint64_t NumAttrs = pImpl->getNumSlots();
> -  AttributeList AS;
> -  uint64_t LastIndex = 0;
> -  for (unsigned I = 0, E = NumAttrs; I != E; ++I) {
> -    if (getSlotIndex(I) >= Index) {
> -      if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++);
> -      break;
> -    }
> -    LastIndex = I + 1;
> -    AttrSet.push_back(getSlotAttributes(I));
> -  }
> +  unsigned I;
>
> -  // Now add the attribute into the correct slot. There may already be an
> -  // AttributeList there.
> -  AttrBuilder B(AS, Index);
> -
> -  for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)
> -    if (Attrs.getSlotIndex(I) == Index) {
> -      for (AttributeListImpl::iterator II = Attrs.pImpl->begin(I),
> -                                       IE = Attrs.pImpl->end(I);
> -           II != IE; ++II)
> -        B.addAttribute(*II);
> +  // Add all the attribute slots before the one we need to merge.
> +  for (I = 0; I < NumAttrs; ++I) {
> +    if (getSlotIndex(I) >= Index)
>        break;
> -    }
> +    AttrSet.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
> +  }
>
> -  AttrSet.push_back(AttributeList::get(C, Index, B));
> +  if (I < NumAttrs && getSlotIndex(I) == Index) {
> +    // We need to merge two AttributeSetNodes.
> +    AttributeSetNode *Merged = AttributeSetNode::get(
> +        C, AttrBuilder(pImpl->getSlotNode(I)).merge(AttrBuilder(AS)));
> +    AttrSet.emplace_back(Index, Merged);
> +    ++I;
> +  } else {
> +    // Otherwise, there were no attributes at this position in the
> original
> +    // list. Add the set as is.
> +    AttrSet.emplace_back(Index, AS);
> +  }
>
> -  // Add the remaining attribute slots.
> -  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
> -    AttrSet.push_back(getSlotAttributes(I));
> +  // Add the remaining entries.
> +  for (; I < NumAttrs; ++I)
> +    AttrSet.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
>
>    return get(C, AttrSet);
>  }
>
> +AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned
> Index,
> +                                           const AttrBuilder &B) const {
> +  return get(C, Index, AttributeSetNode::get(C, B));
> +}
> +
>  AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned
> Index,
>                                               Attribute::AttrKind Kind)
> const {
>    if (!hasAttribute(Index, Kind)) return *this;
> @@ -961,6 +1005,20 @@ AttributeList AttributeList::removeAttri
>    return get(C, AttrSet);
>  }
>
> +AttributeList AttributeList::removeAttributes(LLVMContext &C,
> +                                              unsigned WithoutIndex)
> const {
> +  if (!pImpl)
> +    return AttributeList();
> +
> +  SmallVector<std::pair<unsigned, AttributeSetNode *>, 4> AttrSet;
> +  for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) {
> +    unsigned Index = getSlotIndex(I);
> +    if (Index != WithoutIndex)
> +      AttrSet.push_back({Index, pImpl->getSlotNode(I)});
> +  }
> +  return get(C, AttrSet);
> +}
> +
>  AttributeList AttributeList::addDereferenceableAttr(LLVMContext &C,
>                                                      unsigned Index,
>                                                      uint64_t Bytes) const
> {
> @@ -992,32 +1050,16 @@ AttributeList::addAllocSizeAttr(LLVMCont
>
>  LLVMContext &AttributeList::getContext() const { return
> pImpl->getContext(); }
>
> -AttributeList AttributeList::getParamAttributes(unsigned Index) const {
> -  return pImpl && hasAttributes(Index)
> -             ? AttributeList::get(
> -                   pImpl->getContext(),
> -                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(
> -                       std::make_pair(Index, getAttributes(Index))))
> -             : AttributeList();
> -}
> -
> -AttributeList AttributeList::getRetAttributes() const {
> -  return pImpl && hasAttributes(ReturnIndex)
> -             ? AttributeList::get(
> -                   pImpl->getContext(),
> -                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(
> -                       std::make_pair(ReturnIndex,
> getAttributes(ReturnIndex))))
> -             : AttributeList();
> -}
> -
> -AttributeList AttributeList::getFnAttributes() const {
> -  return pImpl && hasAttributes(FunctionIndex)
> -             ? AttributeList::get(
> -                   pImpl->getContext(),
> -                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(
> -                       std::make_pair(FunctionIndex,
> -                                      getAttributes(FunctionIndex))))
> -             : AttributeList();
> +AttributeSetNode *AttributeList::getParamAttributes(unsigned Index)
> const {
> +  return getAttributes(Index);
> +}
> +
> +AttributeSetNode *AttributeList::getRetAttributes() const {
> +  return getAttributes(ReturnIndex);
> +}
> +
> +AttributeSetNode *AttributeList::getFnAttributes() const {
> +  return getAttributes(FunctionIndex);
>  }
>
>  bool AttributeList::hasAttribute(unsigned Index,
> @@ -1181,6 +1223,13 @@ AttrBuilder::AttrBuilder(AttributeList A
>    }
>  }
>
> +AttrBuilder::AttrBuilder(AttributeSetNode *AS) {
> +  if (AS) {
> +    for (const Attribute &A : *AS)
> +      addAttribute(A);
> +  }
> +}
> +
>  void AttrBuilder::clear() {
>    Attrs.reset();
>    TargetDepAttrs.clear();
>
> Modified: llvm/trunk/lib/IR/Core.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/
> Core.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/IR/Core.cpp (original)
> +++ llvm/trunk/lib/IR/Core.cpp Mon Apr 10 18:31:05 2017
> @@ -16,7 +16,7 @@
>  #include "llvm/ADT/StringSwitch.h"
>  #include "llvm/Bitcode/BitcodeReader.h"
>  #include "llvm/IR/Attributes.h"
> -#include "AttributeSetNode.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/CallSite.h"
>  #include "llvm/IR/Constants.h"
>  #include "llvm/IR/DerivedTypes.h"
>
> Modified: llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/
> ArgumentPromotion.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp Mon Apr 10
> 18:31:05 2017
> @@ -42,6 +42,7 @@
>  #include "llvm/Analysis/LazyCallGraph.h"
>  #include "llvm/Analysis/Loads.h"
>  #include "llvm/Analysis/TargetLibraryInfo.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/CFG.h"
>  #include "llvm/IR/CallSite.h"
>  #include "llvm/IR/Constants.h"
> @@ -102,13 +103,11 @@ doPromotion(Function *F, SmallPtrSetImpl
>    // Attribute - Keep track of the parameter attributes for the arguments
>    // that we are *not* promoting. For the ones that we do promote, the
> parameter
>    // attributes are lost
> -  SmallVector<AttributeList, 8> AttributesVec;
> +  SmallVector<AttributeSetNode *, 8> AttributesVec;
>    const AttributeList &PAL = F->getAttributes();
>
>    // Add any return attributes.
> -  if (PAL.hasAttributes(AttributeList::ReturnIndex))
> -    AttributesVec.push_back(
> -        AttributeList::get(F->getContext(), PAL.getRetAttributes()));
> +  AttributesVec.push_back(PAL.getRetAttributes());
>
>    // First, determine the new argument list
>    unsigned ArgIndex = 1;
> @@ -119,16 +118,12 @@ doPromotion(Function *F, SmallPtrSetImpl
>        Type *AgTy = cast<PointerType>(I->getType())->getElementType();
>        StructType *STy = cast<StructType>(AgTy);
>        Params.insert(Params.end(), STy->element_begin(),
> STy->element_end());
> +      AttributesVec.insert(AttributesVec.end(), STy->getNumElements(),
> nullptr);
>        ++NumByValArgsPromoted;
>      } else if (!ArgsToPromote.count(&*I)) {
>        // Unchanged argument
>        Params.push_back(I->getType());
> -      AttributeList attrs = PAL.getParamAttributes(ArgIndex);
> -      if (attrs.hasAttributes(ArgIndex)) {
> -        AttrBuilder B(attrs, ArgIndex);
> -        AttributesVec.push_back(
> -            AttributeList::get(F->getContext(), Params.size(), B));
> -      }
> +      AttributesVec.push_back(PAL.getParamAttributes(ArgIndex));
>      } else if (I->use_empty()) {
>        // Dead argument (which are always marked as promotable)
>        ++NumArgumentsDead;
> @@ -173,6 +168,7 @@ doPromotion(Function *F, SmallPtrSetImpl
>          Params.push_back(GetElementPtrInst::getIndexedType(
>              cast<PointerType>(I->getType()->getScalarType())->
> getElementType(),
>              ArgIndex.second));
> +        AttributesVec.push_back(nullptr);
>          assert(Params.back());
>        }
>
> @@ -184,9 +180,7 @@ doPromotion(Function *F, SmallPtrSetImpl
>    }
>
>    // Add any function attributes.
> -  if (PAL.hasAttributes(AttributeList::FunctionIndex))
> -    AttributesVec.push_back(
> -        AttributeList::get(FTy->getContext(), PAL.getFnAttributes()));
> +  AttributesVec.push_back(PAL.getFnAttributes());
>
>    Type *RetTy = FTy->getReturnType();
>
> @@ -223,9 +217,7 @@ doPromotion(Function *F, SmallPtrSetImpl
>      const AttributeList &CallPAL = CS.getAttributes();
>
>      // Add any return attributes.
> -    if (CallPAL.hasAttributes(AttributeList::ReturnIndex))
> -      AttributesVec.push_back(
> -          AttributeList::get(F->getContext(),
> CallPAL.getRetAttributes()));
> +    AttributesVec.push_back(CallPAL.getRetAttributes());
>
>      // Loop over the operands, inserting GEP and loads in the caller as
>      // appropriate.
> @@ -235,12 +227,7 @@ doPromotion(Function *F, SmallPtrSetImpl
>           ++I, ++AI, ++ArgIndex)
>        if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I))
> {
>          Args.push_back(*AI); // Unmodified argument
> -
> -        if (CallPAL.hasAttributes(ArgIndex)) {
> -          AttrBuilder B(CallPAL, ArgIndex);
> -          AttributesVec.push_back(
> -              AttributeList::get(F->getContext(), Args.size(), B));
> -        }
> +        AttributesVec.push_back(CallPAL.getAttributes(ArgIndex));
>        } else if (ByValArgsToTransform.count(&*I)) {
>          // Emit a GEP and load for each element of the struct.
>          Type *AgTy = cast<PointerType>(I->getType())->getElementType();
> @@ -253,6 +240,7 @@ doPromotion(Function *F, SmallPtrSetImpl
>                STy, *AI, Idxs, (*AI)->getName() + "." + Twine(i), Call);
>            // TODO: Tell AA about the new values?
>            Args.push_back(new LoadInst(Idx, Idx->getName() + ".val",
> Call));
> +          AttributesVec.push_back(nullptr);
>          }
>        } else if (!I->use_empty()) {
>          // Non-dead argument: insert GEPs and loads as appropriate.
> @@ -295,23 +283,18 @@ doPromotion(Function *F, SmallPtrSetImpl
>            newLoad->setAAMetadata(AAInfo);
>
>            Args.push_back(newLoad);
> +          AttributesVec.push_back(nullptr);
>          }
>        }
>
>      // Push any varargs arguments on the list.
>      for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
>        Args.push_back(*AI);
> -      if (CallPAL.hasAttributes(ArgIndex)) {
> -        AttrBuilder B(CallPAL, ArgIndex);
> -        AttributesVec.push_back(
> -            AttributeList::get(F->getContext(), Args.size(), B));
> -      }
> +      AttributesVec.push_back(CallPAL.getAttributes(ArgIndex));
>      }
>
>      // Add any function attributes.
> -    if (CallPAL.hasAttributes(AttributeList::FunctionIndex))
> -      AttributesVec.push_back(
> -          AttributeList::get(Call->getContext(),
> CallPAL.getFnAttributes()));
> +    AttributesVec.push_back(CallPAL.getFnAttributes());
>
>      SmallVector<OperandBundleDef, 1> OpBundles;
>      CS.getOperandBundlesAsDefs(OpBundles);
>
> Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/
> DeadArgumentElimination.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Mon Apr 10
> 18:31:05 2017
> @@ -21,6 +21,7 @@
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/Statistic.h"
>  #include "llvm/ADT/StringExtras.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/CallSite.h"
>  #include "llvm/IR/CallingConv.h"
>  #include "llvm/IR/Constant.h"
> @@ -172,8 +173,9 @@ bool DeadArgumentEliminationPass::Delete
>        for (unsigned i = 0; PAL.getSlotIndex(i) <= NumArgs; ++i)
>          AttributesVec.push_back(PAL.getSlotAttributes(i));
>        if (PAL.hasAttributes(AttributeList::FunctionIndex))
> -        AttributesVec.push_back(
> -            AttributeList::get(Fn.getContext(), PAL.getFnAttributes()));
> +        AttributesVec.push_back(AttributeList::get(Fn.getContext(),
> +
>  AttributeList::FunctionIndex,
> +
>  PAL.getFnAttributes()));
>        PAL = AttributeList::get(Fn.getContext(), AttributesVec);
>      }
>
> @@ -684,9 +686,13 @@ bool DeadArgumentEliminationPass::Remove
>    bool HasLiveReturnedArg = false;
>
>    // Set up to build a new list of parameter attributes.
> -  SmallVector<AttributeList, 8> AttributesVec;
> +  SmallVector<AttributeSetNode *, 8> AttributesVec;
>    const AttributeList &PAL = F->getAttributes();
>
> +  // Reserve an empty slot for the return value attributes, which we will
> +  // compute last.
> +  AttributesVec.push_back(nullptr);
> +
>    // Remember which arguments are still alive.
>    SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false);
>    // Construct the new parameter list from non-dead arguments. Also
> construct
> @@ -699,16 +705,8 @@ bool DeadArgumentEliminationPass::Remove
>      if (LiveValues.erase(Arg)) {
>        Params.push_back(I->getType());
>        ArgAlive[i] = true;
> -
> -      // Get the original parameter attributes (skipping the first one,
> that is
> -      // for the return value.
> -      if (PAL.hasAttributes(i + 1)) {
> -        AttrBuilder B(PAL, i + 1);
> -        if (B.contains(Attribute::Returned))
> -          HasLiveReturnedArg = true;
> -        AttributesVec.push_back(
> -            AttributeList::get(F->getContext(), Params.size(), B));
> -      }
> +      AttributesVec.push_back(PAL.getParamAttributes(i + 1));
> +      HasLiveReturnedArg |= PAL.hasAttribute(i + 1, Attribute::Returned);
>      } else {
>        ++NumArgumentsEliminated;
>        DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing argument "
> << i
> @@ -782,29 +780,25 @@ bool DeadArgumentEliminationPass::Remove
>    assert(NRetTy && "No new return type found?");
>
>    // The existing function return attributes.
> -  AttributeList RAttrs = PAL.getRetAttributes();
> +  AttrBuilder RAttrs(PAL.getRetAttributes());
>
>    // Remove any incompatible attributes, but only if we removed all return
>    // values. Otherwise, ensure that we don't have any conflicting
> attributes
>    // here. Currently, this should not be possible, but special handling
> might be
>    // required when new return value attributes are added.
>    if (NRetTy->isVoidTy())
> -    RAttrs = RAttrs.removeAttributes(NRetTy->getContext(),
> -                                     AttributeList::ReturnIndex,
> -                                     AttributeFuncs::
> typeIncompatible(NRetTy));
> +    RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy));
>    else
> -    assert(!AttrBuilder(RAttrs, AttributeList::ReturnIndex)
> -                .overlaps(AttributeFuncs::typeIncompatible(NRetTy)) &&
> +    assert(!RAttrs.overlaps(AttributeFuncs::typeIncompatible(NRetTy)) &&
>             "Return attributes no longer compatible?");
>
> -  if (RAttrs.hasAttributes(AttributeList::ReturnIndex))
> -    AttributesVec.push_back(AttributeList::get(NRetTy->getContext(),
> RAttrs));
> +  AttributesVec[0] = AttributeSetNode::get(F->getContext(), RAttrs);
>
> -  if (PAL.hasAttributes(AttributeList::FunctionIndex))
> -    AttributesVec.push_back(
> -        AttributeList::get(F->getContext(), PAL.getFnAttributes()));
> +  // Transfer the function attributes, if any.
> +  AttributesVec.push_back(PAL.getFnAttributes());
>
>    // Reconstruct the AttributesList based on the vector we constructed.
> +  assert(AttributesVec.size() == Params.size() + 2);
>    AttributeList NewPAL = AttributeList::get(F->getContext(),
> AttributesVec);
>
>    // Create the new function type based on the recomputed parameters.
> @@ -835,15 +829,11 @@ bool DeadArgumentEliminationPass::Remove
>      AttributesVec.clear();
>      const AttributeList &CallPAL = CS.getAttributes();
>
> -    // The call return attributes.
> -    AttributeList RAttrs = CallPAL.getRetAttributes();
> -
> -    // Adjust in case the function was changed to return void.
> -    RAttrs = RAttrs.removeAttributes(
> -        NRetTy->getContext(), AttributeList::ReturnIndex,
> -        AttributeFuncs::typeIncompatible(NF->getReturnType()));
> -    if (RAttrs.hasAttributes(AttributeList::ReturnIndex))
> -      AttributesVec.push_back(AttributeList::get(NF->getContext(),
> RAttrs));
> +    // Adjust the call return attributes in case the function was changed
> to
> +    // return void.
> +    AttrBuilder RAttrs(CallPAL.getRetAttributes());
> +    RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy));
> +    AttributesVec.push_back(AttributeSetNode::get(F->getContext(),
> RAttrs));
>
>      // Declare these outside of the loops, so we can reuse them for the
> second
>      // loop, which loops the varargs.
> @@ -855,33 +845,30 @@ bool DeadArgumentEliminationPass::Remove
>        if (ArgAlive[i]) {
>          Args.push_back(*I);
>          // Get original parameter attributes, but skip return attributes.
> -        if (CallPAL.hasAttributes(i + 1)) {
> -          AttrBuilder B(CallPAL, i + 1);
> +        AttributeSetNode *Attrs = CallPAL.getParamAttributes(i + 1);
> +        if (NRetTy != RetTy && Attrs &&
> +            Attrs->hasAttribute(Attribute::Returned)) {
>            // If the return type has changed, then get rid of 'returned'
> on the
>            // call site. The alternative is to make all 'returned'
> attributes on
>            // call sites keep the return value alive just like 'returned'
> -          // attributes on function declaration but it's less clearly a
> win
> -          // and this is not an expected case anyway
> -          if (NRetTy != RetTy && B.contains(Attribute::Returned))
> -            B.removeAttribute(Attribute::Returned);
> -          AttributesVec.push_back(
> -              AttributeList::get(F->getContext(), Args.size(), B));
> +          // attributes on function declaration but it's less clearly a
> win and
> +          // this is not an expected case anyway
> +          AttributesVec.push_back(AttributeSetNode::get(
> +              F->getContext(),
> +              AttrBuilder(Attrs).removeAttribute(Attribute::Returned)));
> +        } else {
> +          // Otherwise, use the original attributes.
> +          AttributesVec.push_back(Attrs);
>          }
>        }
>
>      // Push any varargs arguments on the list. Don't forget their
> attributes.
>      for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) {
>        Args.push_back(*I);
> -      if (CallPAL.hasAttributes(i + 1)) {
> -        AttrBuilder B(CallPAL, i + 1);
> -        AttributesVec.push_back(
> -            AttributeList::get(F->getContext(), Args.size(), B));
> -      }
> +      AttributesVec.push_back(CallPAL.getParamAttributes(i + 1));
>      }
>
> -    if (CallPAL.hasAttributes(AttributeList::FunctionIndex))
> -      AttributesVec.push_back(
> -          AttributeList::get(Call->getContext(),
> CallPAL.getFnAttributes()));
> +    AttributesVec.push_back(CallPAL.getFnAttributes());
>
>      // Reconstruct the AttributesList based on the vector we constructed.
>      AttributeList NewCallPAL =
>
> Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/IPO/MergeFunctions.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Mon Apr 10 18:31:05
> 2017
> @@ -439,8 +439,7 @@ void MergeFunctions::replaceDirectCaller
>            Context, AttributeList::ReturnIndex,
> NewFuncAttrs.getRetAttributes());
>
>        for (unsigned argIdx = 0; argIdx < CS.arg_size(); argIdx++) {
> -        AttributeList Attrs = NewFuncAttrs.getParamAttributes(argIdx);
> -        if (Attrs.getNumSlots())
> +        if (AttributeSetNode *Attrs = NewFuncAttrs.
> getParamAttributes(argIdx))
>            CallSiteAttrs = CallSiteAttrs.addAttributes(Context, argIdx,
> Attrs);
>        }
>
>
> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
> Transforms/InstCombine/InstCombineCalls.cpp?rev=
> 299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Mon Apr 10
> 18:31:05 2017
> @@ -23,6 +23,7 @@
>  #include "llvm/Analysis/InstructionSimplify.h"
>  #include "llvm/Analysis/MemoryBuiltins.h"
>  #include "llvm/Analysis/ValueTracking.h"
> +#include "llvm/IR/AttributeSetNode.h"
>  #include "llvm/IR/BasicBlock.h"
>  #include "llvm/IR/CallSite.h"
>  #include "llvm/IR/Constant.h"
> @@ -3992,7 +3993,7 @@ bool InstCombiner::transformConstExprCas
>      if (!CastInst::isBitOrNoopPointerCastable(ActTy, ParamTy, DL))
>        return false;   // Cannot transform this parameter value.
>
> -    if (AttrBuilder(CallerPAL.getParamAttributes(i + 1), i + 1).
> +    if (AttrBuilder(CallerPAL.getParamAttributes(i + 1)).
>            overlaps(AttributeFuncs::typeIncompatible(ParamTy)))
>        return false;   // Attribute not compatible with transformed value.
>
> @@ -4001,9 +4002,7 @@ bool InstCombiner::transformConstExprCas
>
>      // If the parameter is passed as a byval argument, then we have to
> have a
>      // sized type and the sized type has to have the same size as the old
> type.
> -    if (ParamTy != ActTy &&
> -        CallerPAL.getParamAttributes(i + 1).hasAttribute(i + 1,
> -
>  Attribute::ByVal)) {
> +    if (ParamTy != ActTy && CallerPAL.hasAttribute(i + 1,
> Attribute::ByVal)) {
>        PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy);
>        if (!ParamPTy || !ParamPTy->getElementType()->isSized())
>          return false;
> @@ -4084,7 +4083,7 @@ bool InstCombiner::transformConstExprCas
>      }
>
>      // Add any parameter attributes.
> -    AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1), i + 1);
> +    AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1));
>      if (PAttrs.hasAttributes())
>        attrVec.push_back(
>            AttributeList::get(Caller->getContext(), i + 1, PAttrs));
> @@ -4112,7 +4111,7 @@ bool InstCombiner::transformConstExprCas
>          }
>
>          // Add any parameter attributes.
> -        AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1), i + 1);
> +        AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1));
>          if (PAttrs.hasAttributes())
>            attrVec.push_back(
>                AttributeList::get(FT->getContext(), i + 1, PAttrs));
> @@ -4120,9 +4119,11 @@ bool InstCombiner::transformConstExprCas
>      }
>    }
>
> -  AttributeList FnAttrs = CallerPAL.getFnAttributes();
> +  AttributeSetNode *FnAttrs = CallerPAL.getFnAttributes();
>    if (CallerPAL.hasAttributes(AttributeList::FunctionIndex))
> -    attrVec.push_back(AttributeList::get(Callee->getContext(), FnAttrs));
> +    attrVec.push_back(AttributeList::get(Callee->getContext(),
> +                                         AttributeList::FunctionIndex,
> +                                         AttrBuilder(FnAttrs)));
>
>    if (NewRetTy->isVoidTy())
>      Caller->setName("");   // Void type should not have a name.
> @@ -4200,7 +4201,7 @@ InstCombiner::transformCallThroughTrampo
>    Value *Callee = CS.getCalledValue();
>    PointerType *PTy = cast<PointerType>(Callee->getType());
>    FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
> -  const AttributeList &Attrs = CS.getAttributes();
> +  AttributeList Attrs = CS.getAttributes();
>
>    // If the call already has the 'nest' attribute somewhere then give up -
>    // otherwise 'nest' would occur twice after splicing in the chain.
> @@ -4213,11 +4214,11 @@ InstCombiner::transformCallThroughTrampo
>    Function *NestF =cast<Function>(Tramp->getArgOperand(1)->
> stripPointerCasts());
>    FunctionType *NestFTy = cast<FunctionType>(NestF->getValueType());
>
> -  const AttributeList &NestAttrs = NestF->getAttributes();
> +  AttributeList NestAttrs = NestF->getAttributes();
>    if (!NestAttrs.isEmpty()) {
>      unsigned NestIdx = 1;
>      Type *NestTy = nullptr;
> -    AttributeList NestAttr;
> +    AttributeSetNode *NestAttr;
>
>      // Look for a parameter marked with the 'nest' attribute.
>      for (FunctionType::param_iterator I = NestFTy->param_begin(),
> @@ -4232,18 +4233,15 @@ InstCombiner::transformCallThroughTrampo
>      if (NestTy) {
>        Instruction *Caller = CS.getInstruction();
>        std::vector<Value*> NewArgs;
> +      std::vector<AttributeSetNode *> NewAttrs;
>        NewArgs.reserve(CS.arg_size() + 1);
> -
> -      SmallVector<AttributeList, 8> NewAttrs;
> -      NewAttrs.reserve(Attrs.getNumSlots() + 1);
> +      NewAttrs.reserve(CS.arg_size() + 2);
>
>        // Insert the nest argument into the call argument list, which may
>        // mean appending it.  Likewise for attributes.
>
>        // Add any result attributes.
> -      if (Attrs.hasAttributes(AttributeList::ReturnIndex))
> -        NewAttrs.push_back(
> -            AttributeList::get(Caller->getContext(),
> Attrs.getRetAttributes()));
> +      NewAttrs.push_back(Attrs.getRetAttributes());
>
>        {
>          unsigned Idx = 1;
> @@ -4255,8 +4253,7 @@ InstCombiner::transformCallThroughTrampo
>              if (NestVal->getType() != NestTy)
>                NestVal = Builder->CreateBitCast(NestVal, NestTy, "nest");
>              NewArgs.push_back(NestVal);
> -            NewAttrs.push_back(
> -                AttributeList::get(Caller->getContext(), NestAttr));
> +            NewAttrs.push_back(NestAttr);
>            }
>
>            if (I == E)
> @@ -4264,12 +4261,7 @@ InstCombiner::transformCallThroughTrampo
>
>            // Add the original argument and attributes.
>            NewArgs.push_back(*I);
> -          AttributeList Attr = Attrs.getParamAttributes(Idx);
> -          if (Attr.hasAttributes(Idx)) {
> -            AttrBuilder B(Attr, Idx);
> -            NewAttrs.push_back(AttributeList::get(Caller->getContext(),
> -                                                  Idx + (Idx >= NestIdx),
> B));
> -          }
> +          NewAttrs.push_back(Attrs.getParamAttributes(Idx));
>
>            ++Idx;
>            ++I;
> @@ -4277,9 +4269,7 @@ InstCombiner::transformCallThroughTrampo
>        }
>
>        // Add any function attributes.
> -      if (Attrs.hasAttributes(AttributeList::FunctionIndex))
> -        NewAttrs.push_back(
> -            AttributeList::get(FTy->getContext(),
> Attrs.getFnAttributes()));
> +      NewAttrs.push_back(Attrs.getFnAttributes());
>
>        // The trampoline may have been bitcast to a bogus type (FTy).
>        // Handle this by synthesizing a new function type, equal to FTy
> @@ -4319,8 +4309,7 @@ InstCombiner::transformCallThroughTrampo
>          NestF->getType() == PointerType::getUnqual(NewFTy) ?
>          NestF : ConstantExpr::getBitCast(NestF,
>                                           PointerType::getUnqual(NewFTy));
> -      const AttributeList &NewPAL =
> -          AttributeList::get(FTy->getContext(), NewAttrs);
> +      AttributeList NewPAL = AttributeList::get(FTy->getContext(),
> NewAttrs);
>
>        SmallVector<OperandBundleDef, 1> OpBundles;
>        CS.getOperandBundlesAsDefs(OpBundles);
>
> Modified: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/
> RewriteStatepointsForGC.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
> (original)
> +++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp Mon Apr
> 10 18:31:05 2017
> @@ -1392,7 +1392,6 @@ makeStatepointExplicitImpl(const CallSit
>
>    // Create the statepoint given all the arguments
>    Instruction *Token = nullptr;
> -  AttributeList ReturnAttrs;
>    if (CS.isCall()) {
>      CallInst *ToReplace = cast<CallInst>(CS.getInstruction());
>      CallInst *Call = Builder.CreateGCStatepointCall(
> @@ -1407,8 +1406,9 @@ makeStatepointExplicitImpl(const CallSit
>      AttributeList NewAttrs = legalizeCallAttributes(
> ToReplace->getAttributes());
>      // In case if we can handle this set of attributes - set up function
> attrs
>      // directly on statepoint and return attrs later for gc_result
> intrinsic.
> -    Call->setAttributes(NewAttrs.getFnAttributes());
> -    ReturnAttrs = NewAttrs.getRetAttributes();
> +    Call->setAttributes(AttributeList::get(Call->getContext(),
> +                                           AttributeList::FunctionIndex,
> +                                           NewAttrs.getFnAttributes()));
>
>      Token = Call;
>
> @@ -1435,8 +1435,9 @@ makeStatepointExplicitImpl(const CallSit
>      AttributeList NewAttrs = legalizeCallAttributes(
> ToReplace->getAttributes());
>      // In case if we can handle this set of attributes - set up function
> attrs
>      // directly on statepoint and return attrs later for gc_result
> intrinsic.
> -    Invoke->setAttributes(NewAttrs.getFnAttributes());
> -    ReturnAttrs = NewAttrs.getRetAttributes();
> +    Invoke->setAttributes(AttributeList::get(Invoke->getContext(),
> +                                             AttributeList::FunctionIndex,
> +                                             NewAttrs.getFnAttributes()));
>
>      Token = Invoke;
>
> @@ -1482,7 +1483,9 @@ makeStatepointExplicitImpl(const CallSit
>        StringRef Name =
>            CS.getInstruction()->hasName() ? CS.getInstruction()->getName()
> : "";
>        CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(),
> Name);
> -      GCResult->setAttributes(CS.getAttributes().getRetAttributes());
> +      GCResult->setAttributes(
> +          AttributeList::get(GCResult->getContext(),
> AttributeList::ReturnIndex,
> +                             CS.getAttributes().getRetAttributes()));
>
>        // We cannot RAUW or delete CS.getInstruction() because it could be
> in the
>        // live set of some other safepoint, in which case that safepoint's
>
> Modified: llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/
> CloneFunction.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp Mon Apr 10 18:31:05
> 2017
> @@ -103,21 +103,25 @@ void llvm::CloneFunctionInto(Function *N
>                   ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
>                   TypeMapper, Materializer));
>
> +  SmallVector<std::pair<unsigned, AttributeSetNode*>, 4> AttrVec;
>    AttributeList OldAttrs = OldFunc->getAttributes();
> +
> +  // Copy the return attributes.
> +  if (auto *RetAttrs = OldAttrs.getRetAttributes())
> +    AttrVec.emplace_back(AttributeList::ReturnIndex, RetAttrs);
> +
>    // Clone any argument attributes that are present in the VMap.
>    for (const Argument &OldArg : OldFunc->args())
>      if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) {
> -      AttributeList attrs = OldAttrs.getParamAttributes(OldArg.getArgNo()
> + 1);
> -      if (attrs.getNumSlots() > 0)
> -        NewArg->addAttr(attrs);
> +      if (auto *ParmAttrs = OldAttrs.getParamAttributes(OldArg.getArgNo()
> + 1))
> +        AttrVec.emplace_back(NewArg->getArgNo() + 1, ParmAttrs);
>      }
>
> -  NewFunc->setAttributes(
> -      NewFunc->getAttributes()
> -          .addAttributes(NewFunc->getContext(),
> AttributeList::ReturnIndex,
> -                         OldAttrs.getRetAttributes())
> -          .addAttributes(NewFunc->getContext(),
> AttributeList::FunctionIndex,
> -                         OldAttrs.getFnAttributes()));
> +  // Copy any function attributes.
> +  if (auto *FnAttrs = OldAttrs.getFnAttributes())
> +    AttrVec.emplace_back(AttributeList::FunctionIndex, FnAttrs);
> +
> +  NewFunc->setAttributes(AttributeList::get(NewFunc->getContext(),
> AttrVec));
>
>    SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
>    OldFunc->getAllMetadata(MDs);
>
> Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/
> CodeExtractor.cpp?rev=299899&r1=299898&r2=299899&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Mon Apr 10 18:31:05
> 2017
> @@ -362,8 +362,7 @@ Function *CodeExtractor::constructFuncti
>    //  "target-features" attribute allowing it to be lowered.
>    // FIXME: This should be changed to check to see if a specific
>    //           attribute can not be inherited.
> -  AttributeList OldFnAttrs = oldFunction->getAttributes().
> getFnAttributes();
> -  AttrBuilder AB(OldFnAttrs, AttributeList::FunctionIndex);
> +  AttrBuilder AB(oldFunction->getAttributes().getFnAttributes());
>    for (const auto &Attr : AB.td_attrs())
>      newFunction->addFnAttr(Attr.first, Attr.second);
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170411/b2216593/attachment-0001.html>


More information about the llvm-commits mailing list