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

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 11 17:46:26 PDT 2017


Hopefully https://reviews.llvm.org/D31940 will fix it.

On Tue, Apr 11, 2017 at 2:12 PM, Richard Smith <richard at metafoo.co.uk>
wrote:

> 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->getC
>> ontext(),
>> -                                                            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/AsmWri
>> ter.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/Attrib
>> uteImpl.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/Attrib
>> uteSetNode.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/Attrib
>> utes.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/Transform
>> s/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())->getElemen
>> tType(),
>>              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/Transform
>> s/IPO/DeadArgumentElimination.cpp?rev=299899&r1=299898&r2=29
>> 9899&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::typeIncompati
>> ble(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/Transform
>> s/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.getParamAttribute
>> s(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/Transform
>> s/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->getArgO
>> perand(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/Transform
>> s/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(ToRepla
>> ce->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(ToRepla
>> ce->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/Transform
>> s/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/Transform
>> s/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().g
>> etFnAttributes();
>> -  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/7f686dbd/attachment-0001.html>


More information about the llvm-commits mailing list