<div dir="ltr">Hopefully <a href="https://reviews.llvm.org/D31940">https://reviews.llvm.org/D31940</a> will fix it.</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Apr 11, 2017 at 2:12 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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).<div><br></div><div>Should the new header be in the intrinsics_gen module in the module map?<div><div class="h5"><br><div class="gmail_extra"><br><div class="gmail_quote">On 10 April 2017 at 16:31, Reid Kleckner via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Mon Apr 10 18:31:05 2017<br>
New Revision: 299899<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=299899&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=299899&view=rev</a><br>
Log:<br>
Reland "[IR] Make AttributeSetNode public, avoid temporary AttributeList copies"<br>
<br>
This re-lands r299875.<br>
<br>
I introduced a bug in Clang code responsible for replacing K&R, no<br>
prototype declarations with a real function definition with a prototype.<br>
The bug was here:<br>
<br>
       // Collect any return attributes from the call.<br>
  -    if (oldAttrs.hasAttributes(llvm::<wbr>AttributeList::ReturnIndex))<br>
  -      newAttrs.push_back(llvm::Attri<wbr>buteList::get(newFn->getContex<wbr>t(),<br>
  -                                                  oldAttrs.getRetAttributes()));<br>
  +    newAttrs.push_back(oldAttrs.ge<wbr>tRetAttributes());<br>
<br>
Previously getRetAttributes() carried AttributeList::ReturnIndex in its<br>
AttributeList. Now that we return the AttributeSetNode* directly, it no<br>
longer carries that index, and we call this overload with a single node:<br>
  AttributeList::get(LLVMContext<wbr>&, ArrayRef<AttributeSetNode*>)<br>
<br>
That aborted with an assertion on x86_32 targets. I added an explicit<br>
triple to the test and added CHECKs to help find issues like this in the<br>
future sooner.<br>
<br>
Added:<br>
    llvm/trunk/include/llvm/IR/Att<wbr>ributeSetNode.h<br>
Removed:<br>
    llvm/trunk/lib/IR/AttributeSet<wbr>Node.h<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/Att<wbr>ributes.h<br>
    llvm/trunk/lib/AsmParser/LLPar<wbr>ser.cpp<br>
    llvm/trunk/lib/AsmParser/LLPar<wbr>ser.h<br>
    llvm/trunk/lib/IR/AsmWriter.cp<wbr>p<br>
    llvm/trunk/lib/IR/AttributeImp<wbr>l.h<br>
    llvm/trunk/lib/IR/Attributes.c<wbr>pp<br>
    llvm/trunk/lib/IR/Core.cpp<br>
    llvm/trunk/lib/Transforms/IPO/<wbr>ArgumentPromotion.cpp<br>
    llvm/trunk/lib/Transforms/IPO/<wbr>DeadArgumentElimination.cpp<br>
    llvm/trunk/lib/Transforms/IPO/<wbr>MergeFunctions.cpp<br>
    llvm/trunk/lib/Transforms/Inst<wbr>Combine/InstCombineCalls.cpp<br>
    llvm/trunk/lib/Transforms/Scal<wbr>ar/RewriteStatepointsForGC.cpp<br>
    llvm/trunk/lib/Transforms/Util<wbr>s/CloneFunction.cpp<br>
    llvm/trunk/lib/Transforms/Util<wbr>s/CodeExtractor.cpp<br>
<br>
Added: llvm/trunk/include/llvm/IR/Att<wbr>ributeSetNode.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/AttributeSetNode.h?rev=299899&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>IR/AttributeSetNode.h?rev=<wbr>299899&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/IR/Att<wbr>ributeSetNode.h (added)<br>
+++ llvm/trunk/include/llvm/IR/Att<wbr>ributeSetNode.h Mon Apr 10 18:31:05 2017<br>
@@ -0,0 +1,109 @@<br>
+//===-- AttributeSetNode.h - AttributeList Internal Node --------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+///<br>
+/// \file<br>
+/// \brief This file defines the class that represents a group of attributes<br>
+/// that apply to one element: function, return type, or parameter.<br>
+///<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+<br>
+#ifndef LLVM_IR_ATTRIBUTESETNODE_H<br>
+#define LLVM_IR_ATTRIBUTESETNODE_H<br>
+<br>
+#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/FoldingSet.h"<br>
+#include "llvm/ADT/Optional.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/IR/Attributes.h"<br>
+#include "llvm/Support/TrailingObjects.<wbr>h"<br>
+#include <algorithm><br>
+#include <climits><br>
+#include <cstdint><br>
+#include <string><br>
+#include <utility><br>
+<br>
+namespace llvm {<br>
+<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+/// \class<br>
+/// \brief This class represents a group of attributes that apply to one<br>
+/// element: function, return type, or parameter.<br>
+class AttributeSetNode final<br>
+    : public FoldingSetNode,<br>
+      private TrailingObjects<AttributeSetNo<wbr>de, Attribute> {<br>
+  friend TrailingObjects;<br>
+<br>
+  unsigned NumAttrs; ///< Number of attributes in this node.<br>
+  /// Bitset with a bit for each available attribute Attribute::AttrKind.<br>
+  uint64_t AvailableAttrs;<br>
+<br>
+  AttributeSetNode(ArrayRef<Attr<wbr>ibute> Attrs)<br>
+    : NumAttrs(Attrs.size()), AvailableAttrs(0) {<br>
+    static_assert(Attribute::EndAt<wbr>trKinds <= sizeof(AvailableAttrs) * CHAR_BIT,<br>
+                  "Too many attributes for AvailableAttrs");<br>
+    // There's memory after the node where we can store the entries in.<br>
+    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>(<wbr>));<br>
+<br>
+    for (Attribute I : *this) {<br>
+      if (!I.isStringAttribute()) {<br>
+        AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+public:<br>
+  // AttributesSetNode is uniqued, these should not be available.<br>
+  AttributeSetNode(const AttributeSetNode &) = delete;<br>
+  AttributeSetNode &operator=(const AttributeSetNode &) = delete;<br>
+<br>
+  void operator delete(void *p) { ::operator delete(p); }<br>
+<br>
+  static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B);<br>
+<br>
+  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);<br>
+<br>
+  static AttributeSetNode *get(AttributeList AS, unsigned Index) {<br>
+    return AS.getAttributes(Index);<br>
+  }<br>
+<br>
+  /// \brief Return the number of attributes this AttributeList contains.<br>
+  unsigned getNumAttributes() const { return NumAttrs; }<br>
+<br>
+  bool hasAttribute(Attribute::AttrKi<wbr>nd Kind) const {<br>
+    return AvailableAttrs & ((uint64_t)1) << Kind;<br>
+  }<br>
+  bool hasAttribute(StringRef Kind) const;<br>
+  bool hasAttributes() const { return NumAttrs != 0; }<br>
+<br>
+  Attribute getAttribute(Attribute::AttrKi<wbr>nd Kind) const;<br>
+  Attribute getAttribute(StringRef Kind) const;<br>
+<br>
+  unsigned getAlignment() const;<br>
+  unsigned getStackAlignment() const;<br>
+  uint64_t getDereferenceableBytes() const;<br>
+  uint64_t getDereferenceableOrNullBytes(<wbr>) const;<br>
+  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;<br>
+  std::string getAsString(bool InAttrGrp) const;<br>
+<br>
+  typedef const Attribute *iterator;<br>
+  iterator begin() const { return getTrailingObjects<Attribute>(<wbr>); }<br>
+  iterator end() const { return begin() + NumAttrs; }<br>
+<br>
+  void Profile(FoldingSetNodeID &ID) const {<br>
+    Profile(ID, makeArrayRef(begin(), end()));<br>
+  }<br>
+  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {<br>
+    for (const auto &Attr : AttrList)<br>
+      Attr.Profile(ID);<br>
+  }<br>
+};<br>
+<br>
+} // end namespace llvm<br>
+<br>
+#endif // LLVM_IR_ATTRIBUTESETNODE_H<br>
<br>
Modified: llvm/trunk/include/llvm/IR/Att<wbr>ributes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Attributes.h?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>IR/Attributes.h?rev=299899&r1=<wbr>299898&r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/include/llvm/IR/Att<wbr>ributes.h (original)<br>
+++ llvm/trunk/include/llvm/IR/Att<wbr>ributes.h Mon Apr 10 18:31:05 2017<br>
@@ -221,19 +221,26 @@ private:<br>
   /// the empty attributes list.<br>
   AttributeListImpl *pImpl = nullptr;<br>
<br>
-  /// \brief The attributes for the specified index are returned.<br>
-  AttributeSetNode *getAttributes(unsigned Index) const;<br>
-<br>
+public:<br>
   /// \brief Create an AttributeList with the specified parameters in it.<br>
   static AttributeList get(LLVMContext &C,<br>
                            ArrayRef<std::pair<unsigned, Attribute>> Attrs);<br>
   static AttributeList<br>
   get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *>> Attrs);<br>
<br>
+  /// \brief Create an AttributeList from a vector of AttributeSetNodes. The<br>
+  /// index of each set is implied by its position in the array \p Attrs:<br>
+  ///   0      : Return attributes<br>
+  /// 1 to n-1 : Argument attributes<br>
+  ///   n      : Function attributes<br>
+  /// Any element that has no entries should be left null.<br>
+  static AttributeList get(LLVMContext &C, ArrayRef<AttributeSetNode *> Attrs);<br>
+<br>
   static AttributeList<br>
   getImpl(LLVMContext &C,<br>
           ArrayRef<std::pair<unsigned, AttributeSetNode *>> Attrs);<br>
<br>
+private:<br>
   explicit AttributeList(AttributeListImp<wbr>l *LI) : pImpl(LI) {}<br>
<br>
 public:<br>
@@ -272,6 +279,12 @@ public:<br>
   AttributeList addAttributes(LLVMContext &C, unsigned Index,<br>
                               AttributeList Attrs) const;<br>
<br>
+  AttributeList addAttributes(LLVMContext &C, unsigned Index,<br>
+                              AttributeSetNode *AS) const;<br>
+<br>
+  AttributeList addAttributes(LLVMContext &C, unsigned Index,<br>
+                              const AttrBuilder &B) const;<br>
+<br>
   /// \brief Remove the specified attribute at the specified index from this<br>
   /// attribute list. Because attribute lists are immutable, this returns the<br>
   /// new list.<br>
@@ -296,6 +309,11 @@ public:<br>
   AttributeList removeAttributes(LLVMContext &C, unsigned Index,<br>
                                  const AttrBuilder &Attrs) const;<br>
<br>
+  /// \brief Remove all attributes at the specified index from this<br>
+  /// attribute list. Because attribute lists are immutable, this returns the<br>
+  /// new list.<br>
+  AttributeList removeAttributes(LLVMContext &C, unsigned Index) const;<br>
+<br>
   /// \brief Add the dereferenceable attribute to the attribute set at the given<br>
   /// index. Because attribute sets are immutable, this returns a new set.<br>
   AttributeList addDereferenceableAttr(LLVMCon<wbr>text &C, unsigned Index,<br>
@@ -321,13 +339,16 @@ public:<br>
   LLVMContext &getContext() const;<br>
<br>
   /// \brief The attributes for the specified index are returned.<br>
-  AttributeList getParamAttributes(unsigned Index) const;<br>
+  AttributeSetNode *getAttributes(unsigned Index) const;<br>
+<br>
+  /// \brief The attributes for the specified index are returned.<br>
+  AttributeSetNode *getParamAttributes(unsigned Index) const;<br>
<br>
   /// \brief The attributes for the ret value are returned.<br>
-  AttributeList getRetAttributes() const;<br>
+  AttributeSetNode *getRetAttributes() const;<br>
<br>
   /// \brief The function attributes are returned.<br>
-  AttributeList getFnAttributes() const;<br>
+  AttributeSetNode *getFnAttributes() const;<br>
<br>
   /// \brief Return true if the attribute exists at the given index.<br>
   bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;<br>
@@ -462,6 +483,7 @@ public:<br>
     addAttribute(A);<br>
   }<br>
   AttrBuilder(AttributeList AS, unsigned Idx);<br>
+  AttrBuilder(AttributeSetNode *AS);<br>
<br>
   void clear();<br>
<br>
@@ -478,7 +500,7 @@ public:<br>
   AttrBuilder &removeAttribute(Attribute::At<wbr>trKind Val);<br>
<br>
   /// \brief Remove the attributes from the builder.<br>
-  AttrBuilder &removeAttributes(AttributeLis<wbr>t A, uint64_t Index);<br>
+  AttrBuilder &removeAttributes(AttributeLis<wbr>t A, uint64_t WithoutIndex);<br>
<br>
   /// \brief Remove the target-dependent attribute to the builder.<br>
   AttrBuilder &removeAttribute(StringRef A);<br>
<br>
Modified: llvm/trunk/lib/AsmParser/LLPar<wbr>ser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/AsmParser<wbr>/LLParser.cpp?rev=299899&r1=<wbr>299898&r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/AsmParser/LLPar<wbr>ser.cpp (original)<br>
+++ llvm/trunk/lib/AsmParser/LLPar<wbr>ser.cpp Mon Apr 10 18:31:05 2017<br>
@@ -19,6 +19,7 @@<br>
 #include "llvm/ADT/STLExtras.h"<br>
 #include "llvm/AsmParser/SlotMapping.h"<br>
 #include "llvm/IR/Argument.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/AutoUpgrade.h"<br>
 #include "llvm/IR/BasicBlock.h"<br>
 #include "llvm/IR/CallingConv.h"<br>
@@ -131,9 +132,8 @@ bool LLParser::ValidateEndOfModule(<wbr>) {<br>
<br>
     if (Function *Fn = dyn_cast<Function>(V)) {<br>
       AttributeList AS = Fn->getAttributes();<br>
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);<br>
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,<br>
-                               AS.getFnAttributes());<br>
+      AttrBuilder FnAttrs(AS.getFnAttributes());<br>
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);<br>
<br>
       FnAttrs.merge(B);<br>
<br>
@@ -150,9 +150,8 @@ bool LLParser::ValidateEndOfModule(<wbr>) {<br>
       Fn->setAttributes(AS);<br>
     } else if (CallInst *CI = dyn_cast<CallInst>(V)) {<br>
       AttributeList AS = CI->getAttributes();<br>
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);<br>
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,<br>
-                               AS.getFnAttributes());<br>
+      AttrBuilder FnAttrs(AS.getFnAttributes());<br>
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);<br>
       FnAttrs.merge(B);<br>
       AS = AS.addAttributes(<br>
           Context, AttributeList::FunctionIndex,<br>
@@ -160,9 +159,8 @@ bool LLParser::ValidateEndOfModule(<wbr>) {<br>
       CI->setAttributes(AS);<br>
     } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) {<br>
       AttributeList AS = II->getAttributes();<br>
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);<br>
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,<br>
-                               AS.getFnAttributes());<br>
+      AttrBuilder FnAttrs(AS.getFnAttributes());<br>
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);<br>
       FnAttrs.merge(B);<br>
       AS = AS.addAttributes(<br>
           Context, AttributeList::FunctionIndex,<br>
@@ -2123,7 +2121,6 @@ bool LLParser::ParseParameterList(S<wbr>mallV<br>
   if (ParseToken(lltok::lparen, "expected '(' in call"))<br>
     return true;<br>
<br>
-  unsigned AttrIndex = 1;<br>
   while (Lex.getKind() != lltok::rparen) {<br>
     // If this isn't the first argument, we need a comma.<br>
     if (!ArgList.empty() &&<br>
@@ -2158,7 +2155,7 @@ bool LLParser::ParseParameterList(S<wbr>mallV<br>
         return true;<br>
     }<br>
     ArgList.push_back(ParamInfo(<br>
-        ArgLoc, V, AttributeList::get(V->getConte<wbr>xt(), AttrIndex++, ArgAttrs)));<br>
+        ArgLoc, V, AttributeSetNode::get(V->getCo<wbr>ntext(), ArgAttrs)));<br>
   }<br>
<br>
   if (IsMustTailCall && InVarArgsFunc)<br>
@@ -2263,9 +2260,8 @@ bool LLParser::ParseArgumentList(Sm<wbr>allVe<br>
     if (!FunctionType::isValidArgumen<wbr>tType(ArgTy))<br>
       return Error(TypeLoc, "invalid type for function argument");<br>
<br>
-    unsigned AttrIndex = 1;<br>
-    ArgList.emplace_back(TypeLoc, ArgTy, AttributeList::get(ArgTy->getC<wbr>ontext(),<br>
-                                                            AttrIndex++, Attrs),<br>
+    ArgList.emplace_back(TypeLoc, ArgTy,<br>
+                         AttributeSetNode::get(ArgTy-><wbr>getContext(), Attrs),<br>
                          std::move(Name));<br>
<br>
     while (EatIfPresent(lltok::comma)) {<br>
@@ -2292,10 +2288,9 @@ bool LLParser::ParseArgumentList(Sm<wbr>allVe<br>
       if (!ArgTy->isFirstClassType())<br>
         return Error(TypeLoc, "invalid type for function argument");<br>
<br>
-      ArgList.emplace_back(<br>
-          TypeLoc, ArgTy,<br>
-          AttributeList::get(ArgTy->getC<wbr>ontext(), AttrIndex++, Attrs),<br>
-          std::move(Name));<br>
+      ArgList.emplace_back(TypeLoc, ArgTy,<br>
+                           AttributeSetNode::get(ArgTy-><wbr>getContext(), Attrs),<br>
+                           std::move(Name));<br>
     }<br>
   }<br>
<br>
@@ -2319,7 +2314,7 @@ bool LLParser::ParseFunctionType(Ty<wbr>pe *&<br>
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {<br>
     if (!ArgList[i].Name.empty())<br>
       return Error(ArgList[i].Loc, "argument name invalid in function type");<br>
-    if (ArgList[i].Attrs.hasAttribute<wbr>s(i + 1))<br>
+    if (ArgList[i].Attrs)<br>
       return Error(ArgList[i].Loc,<br>
                    "argument attributes invalid in function type");<br>
   }<br>
@@ -4768,23 +4763,16 @@ bool LLParser::ParseFunctionHeader(<wbr>Funct<br>
   // Okay, if we got here, the function is syntactically valid.  Convert types<br>
   // and do semantic checks.<br>
   std::vector<Type*> ParamTypeList;<br>
-  SmallVector<AttributeList, 8> Attrs;<br>
+  SmallVector<AttributeSetNode *, 8> Attrs;<br>
<br>
-  if (RetAttrs.hasAttributes())<br>
-    Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(),<br>
-                                       AttributeList::ReturnIndex, RetAttrs));<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, RetAttrs));<br>
<br>
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {<br>
     ParamTypeList.push_back(ArgLi<wbr>st[i].Ty);<br>
-    if (ArgList[i].Attrs.hasAttribute<wbr>s(i + 1)) {<br>
-      AttrBuilder B(ArgList[i].Attrs, i + 1);<br>
-      Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(), i + 1, B));<br>
-    }<br>
+    Attrs.push_back(ArgList[i].Att<wbr>rs);<br>
   }<br>
<br>
-  if (FuncAttrs.hasAttributes())<br>
-    Attrs.push_back(AttributeList:<wbr>:get(<br>
-        RetType->getContext(), AttributeList::FunctionIndex, FuncAttrs));<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, FuncAttrs));<br>
<br>
   AttributeList PAL = AttributeList::get(Context, Attrs);<br>
<br>
@@ -5396,10 +5384,8 @@ bool LLParser::ParseInvoke(Instruct<wbr>ion *<br>
     return true;<br>
<br>
   // Set up the Attribute for the function.<br>
-  SmallVector<AttributeList, 8> Attrs;<br>
-  if (RetAttrs.hasAttributes())<br>
-    Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(),<br>
-                                       AttributeList::ReturnIndex, RetAttrs));<br>
+  SmallVector<AttributeSetNode *, 8> Attrs;<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, RetAttrs));<br>
<br>
   SmallVector<Value*, 8> Args;<br>
<br>
@@ -5419,22 +5405,16 @@ bool LLParser::ParseInvoke(Instruct<wbr>ion *<br>
       return Error(ArgList[i].Loc, "argument is not of expected type '" +<br>
                    getTypeString(ExpectedTy) + "'");<br>
     Args.push_back(ArgList[i].V);<br>
-    if (ArgList[i].Attrs.hasAttribute<wbr>s(i + 1)) {<br>
-      AttrBuilder B(ArgList[i].Attrs, i + 1);<br>
-      Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(), i + 1, B));<br>
-    }<br>
+    Attrs.push_back(ArgList[i].Att<wbr>rs);<br>
   }<br>
<br>
   if (I != E)<br>
     return Error(CallLoc, "not enough parameters specified for call");<br>
<br>
-  if (FnAttrs.hasAttributes()) {<br>
-    if (FnAttrs.hasAlignmentAttr())<br>
-      return Error(CallLoc, "invoke instructions may not have an alignment");<br>
+  if (FnAttrs.hasAlignmentAttr())<br>
+    return Error(CallLoc, "invoke instructions may not have an alignment");<br>
<br>
-    Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(),<br>
-                                       AttributeList::FunctionIndex, FnAttrs));<br>
-  }<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, FnAttrs));<br>
<br>
   // Finish off the Attribute and check them<br>
   AttributeList PAL = AttributeList::get(Context, Attrs);<br>
@@ -5998,10 +5978,8 @@ bool LLParser::ParseCall(Instructio<wbr>n *&I<br>
     return true;<br>
<br>
   // Set up the Attribute for the function.<br>
-  SmallVector<AttributeList, 8> Attrs;<br>
-  if (RetAttrs.hasAttributes())<br>
-    Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(),<br>
-                                       AttributeList::ReturnIndex, RetAttrs));<br>
+  SmallVector<AttributeSetNode *, 8> Attrs;<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, RetAttrs));<br>
<br>
   SmallVector<Value*, 8> Args;<br>
<br>
@@ -6021,22 +5999,16 @@ bool LLParser::ParseCall(Instructio<wbr>n *&I<br>
       return Error(ArgList[i].Loc, "argument is not of expected type '" +<br>
                    getTypeString(ExpectedTy) + "'");<br>
     Args.push_back(ArgList[i].V);<br>
-    if (ArgList[i].Attrs.hasAttribute<wbr>s(i + 1)) {<br>
-      AttrBuilder B(ArgList[i].Attrs, i + 1);<br>
-      Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(), i + 1, B));<br>
-    }<br>
+    Attrs.push_back(ArgList[i].Att<wbr>rs);<br>
   }<br>
<br>
   if (I != E)<br>
     return Error(CallLoc, "not enough parameters specified for call");<br>
<br>
-  if (FnAttrs.hasAttributes()) {<br>
-    if (FnAttrs.hasAlignmentAttr())<br>
-      return Error(CallLoc, "call instructions may not have an alignment");<br>
+  if (FnAttrs.hasAlignmentAttr())<br>
+    return Error(CallLoc, "call instructions may not have an alignment");<br>
<br>
-    Attrs.push_back(AttributeList:<wbr>:get(RetType->getContext(),<br>
-                                       AttributeList::FunctionIndex, FnAttrs));<br>
-  }<br>
+  Attrs.push_back(AttributeSetNo<wbr>de::get(Context, FnAttrs));<br>
<br>
   // Finish off the Attribute and check them<br>
   AttributeList PAL = AttributeList::get(Context, Attrs);<br>
<br>
Modified: llvm/trunk/lib/AsmParser/LLPar<wbr>ser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/AsmParser<wbr>/LLParser.h?rev=299899&r1=<wbr>299898&r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/AsmParser/LLPar<wbr>ser.h (original)<br>
+++ llvm/trunk/lib/AsmParser/LLPar<wbr>ser.h Mon Apr 10 18:31:05 2017<br>
@@ -397,8 +397,8 @@ namespace llvm {<br>
     struct ParamInfo {<br>
       LocTy Loc;<br>
       Value *V;<br>
-      AttributeList Attrs;<br>
-      ParamInfo(LocTy loc, Value *v, AttributeList attrs)<br>
+      AttributeSetNode *Attrs;<br>
+      ParamInfo(LocTy loc, Value *v, AttributeSetNode *attrs)<br>
           : Loc(loc), V(v), Attrs(attrs) {}<br>
     };<br>
     bool ParseParameterList(SmallVector<wbr>Impl<ParamInfo> &ArgList,<br>
@@ -450,9 +450,9 @@ namespace llvm {<br>
     struct ArgInfo {<br>
       LocTy Loc;<br>
       Type *Ty;<br>
-      AttributeList Attrs;<br>
+      AttributeSetNode *Attrs;<br>
       std::string Name;<br>
-      ArgInfo(LocTy L, Type *ty, AttributeList Attr, const std::string &N)<br>
+      ArgInfo(LocTy L, Type *ty, AttributeSetNode *Attr, const std::string &N)<br>
           : Loc(L), Ty(ty), Attrs(Attr), Name(N) {}<br>
     };<br>
     bool ParseArgumentList(SmallVectorI<wbr>mpl<ArgInfo> &ArgList, bool &isVarArg);<br>
<br>
Modified: llvm/trunk/lib/IR/AsmWriter.cp<wbr>p<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/AsmWri<wbr>ter.cpp?rev=299899&r1=299898&<wbr>r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/AsmWriter.cp<wbr>p (original)<br>
+++ llvm/trunk/lib/IR/AsmWriter.cp<wbr>p Mon Apr 10 18:31:05 2017<br>
@@ -21,6 +21,8 @@<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/StringExtras.h"<br>
 #include "llvm/IR/AssemblyAnnotationWri<wbr>ter.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
+#include "llvm/IR/Attributes.h"<br>
 #include "llvm/IR/CFG.h"<br>
 #include "llvm/IR/CallingConv.h"<br>
 #include "llvm/IR/Constants.h"<br>
@@ -604,7 +606,7 @@ private:<br>
   unsigned mdnNext;<br>
<br>
   /// asMap - The slot map for attribute sets.<br>
-  DenseMap<AttributeList, unsigned> asMap;<br>
+  DenseMap<AttributeSetNode *, unsigned> asMap;<br>
   unsigned asNext;<br>
 public:<br>
   /// Construct from a module.<br>
@@ -627,7 +629,7 @@ public:<br>
   int getLocalSlot(const Value *V);<br>
   int getGlobalSlot(const GlobalValue *V);<br>
   int getMetadataSlot(const MDNode *N);<br>
-  int getAttributeGroupSlot(Attribut<wbr>eList AS);<br>
+  int getAttributeGroupSlot(Attribut<wbr>eSetNode *AS);<br>
<br>
   /// If you'd like to deal with a function instead of just a module, use<br>
   /// this method to get its data into the SlotTracker.<br>
@@ -650,8 +652,8 @@ public:<br>
   unsigned mdn_size() const { return mdnMap.size(); }<br>
   bool mdn_empty() const { return mdnMap.empty(); }<br>
<br>
-  /// AttributeList map iterators.<br>
-  typedef DenseMap<AttributeList, unsigned>::iterator as_iterator;<br>
+  /// AttributeSetNode map iterators.<br>
+  typedef DenseMap<AttributeSetNode *, unsigned>::iterator as_iterator;<br>
   as_iterator as_begin()   { return asMap.begin(); }<br>
   as_iterator as_end()     { return asMap.end(); }<br>
   unsigned as_size() const { return asMap.size(); }<br>
@@ -671,8 +673,8 @@ private:<br>
   /// CreateFunctionSlot - Insert the specified Value* into the slot table.<br>
   void CreateFunctionSlot(const Value *V);<br>
<br>
-  /// \brief Insert the specified AttributeList into the slot table.<br>
-  void CreateAttributeSetSlot(Attribu<wbr>teList AS);<br>
+  /// \brief Insert the specified AttributeSetNode into the slot table.<br>
+  void CreateAttributeSetSlot(Attribu<wbr>teSetNode *AS);<br>
<br>
   /// Add all of the module level global variables (and their initializers)<br>
   /// and function declarations, but not the contents of those functions.<br>
@@ -831,8 +833,8 @@ void SlotTracker::processModule() {<br>
<br>
     // Add all the function attributes to the table.<br>
     // FIXME: Add attributes of other objects?<br>
-    AttributeList FnAttrs = F.getAttributes().getFnAttribu<wbr>tes();<br>
-    if (FnAttrs.hasAttributes(Attribu<wbr>teList::FunctionIndex))<br>
+    AttributeSetNode *FnAttrs = F.getAttributes().getFnAttribu<wbr>tes();<br>
+    if (FnAttrs)<br>
       CreateAttributeSetSlot(FnAttr<wbr>s);<br>
   }<br>
<br>
@@ -869,13 +871,13 @@ void SlotTracker::processFunction() {<br>
       // target may not be linked into the optimizer.<br>
       if (const CallInst *CI = dyn_cast<CallInst>(&I)) {<br>
         // Add all the call attributes to the table.<br>
-        AttributeList Attrs = CI->getAttributes().getFnAttri<wbr>butes();<br>
-        if (Attrs.hasAttributes(Attribute<wbr>List::FunctionIndex))<br>
+        AttributeSetNode *Attrs = CI->getAttributes().getFnAttri<wbr>butes();<br>
+        if (Attrs)<br>
           CreateAttributeSetSlot(Attrs)<wbr>;<br>
       } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {<br>
         // Add all the call attributes to the table.<br>
-        AttributeList Attrs = II->getAttributes().getFnAttri<wbr>butes();<br>
-        if (Attrs.hasAttributes(Attribute<wbr>List::FunctionIndex))<br>
+        AttributeSetNode *Attrs = II->getAttributes().getFnAttri<wbr>butes();<br>
+        if (Attrs)<br>
           CreateAttributeSetSlot(Attrs)<wbr>;<br>
       }<br>
     }<br>
@@ -961,11 +963,11 @@ int SlotTracker::getLocalSlot(cons<wbr>t Valu<br>
   return FI == fMap.end() ? -1 : (int)FI->second;<br>
 }<br>
<br>
-int SlotTracker::getAttributeGroup<wbr>Slot(AttributeList AS) {<br>
+int SlotTracker::getAttributeGroup<wbr>Slot(AttributeSetNode *AS) {<br>
   // Check for uninitialized state and do lazy initialization.<br>
   initialize();<br>
<br>
-  // Find the AttributeList in the module map.<br>
+  // Find the AttributeSetNode in the module map.<br>
   as_iterator AI = asMap.find(AS);<br>
   return AI == asMap.end() ? -1 : (int)AI->second;<br>
 }<br>
@@ -1015,9 +1017,8 @@ void SlotTracker::CreateMetadataSlo<wbr>t(con<br>
       CreateMetadataSlot(Op);<br>
 }<br>
<br>
-void SlotTracker::CreateAttributeSe<wbr>tSlot(AttributeList AS) {<br>
-  assert(AS.hasAttributes(Attrib<wbr>uteList::FunctionIndex) &&<br>
-         "Doesn't need a slot!");<br>
+void SlotTracker::CreateAttributeSe<wbr>tSlot(AttributeSetNode *AS) {<br>
+  assert(AS && "Doesn't need a slot!");<br>
<br>
   as_iterator I = asMap.find(AS);<br>
   if (I != asMap.end())<br>
@@ -2606,17 +2607,10 @@ void AssemblyWriter::printFunction(<wbr>const<br>
<br>
   const AttributeList &Attrs = F->getAttributes();<br>
   if (Attrs.hasAttributes(Attribute<wbr>List::FunctionIndex)) {<br>
-    AttributeList AS = Attrs.getFnAttributes();<br>
+    AttributeSetNode *AS = Attrs.getFnAttributes();<br>
     std::string AttrStr;<br>
<br>
-    unsigned Idx = 0;<br>
-    for (unsigned E = AS.getNumSlots(); Idx != E; ++Idx)<br>
-      if (AS.getSlotIndex(Idx) == AttributeList::FunctionIndex)<br>
-        break;<br>
-<br>
-    for (AttributeList::iterator I = AS.begin(Idx), E = AS.end(Idx); I != E;<br>
-         ++I) {<br>
-      Attribute Attr = *I;<br>
+    for (const Attribute &Attr : *AS) {<br>
       if (!Attr.isStringAttribute()) {<br>
         if (!AttrStr.empty()) AttrStr += ' ';<br>
         AttrStr += Attr.getAsString();<br>
@@ -3256,7 +3250,7 @@ void AssemblyWriter::printMDNodeBod<wbr>y(con<br>
 }<br>
<br>
 void AssemblyWriter::writeAllAttrib<wbr>uteGroups() {<br>
-  std::vector<std::pair<Attribut<wbr>eList, unsigned>> asVec;<br>
+  std::vector<std::pair<Attribut<wbr>eSetNode *, unsigned>> asVec;<br>
   asVec.resize(Machine.as_size(<wbr>));<br>
<br>
   for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end();<br>
@@ -3265,7 +3259,7 @@ void AssemblyWriter::writeAllAttrib<wbr>uteGr<br>
<br>
   for (const auto &I : asVec)<br>
     Out << "attributes #" << I.second << " = { "<br>
-        << I.first.getAsString(AttributeL<wbr>ist::FunctionIndex, true) << " }\n";<br>
+        << I.first->getAsString(true) << " }\n";<br>
 }<br>
<br>
 void AssemblyWriter::printUseListOr<wbr>der(const UseListOrder &Order) {<br>
<br>
Modified: llvm/trunk/lib/IR/AttributeImp<wbr>l.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeImpl.h?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/Attrib<wbr>uteImpl.h?rev=299899&r1=299898<wbr>&r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/AttributeImp<wbr>l.h (original)<br>
+++ llvm/trunk/lib/IR/AttributeImp<wbr>l.h Mon Apr 10 18:31:05 2017<br>
@@ -16,10 +16,10 @@<br>
 #ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H<br>
 #define LLVM_LIB_IR_ATTRIBUTEIMPL_H<br>
<br>
-#include "AttributeSetNode.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/FoldingSet.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/Attributes.h"<br>
 #include "llvm/Support/TrailingObjects.<wbr>h"<br>
 #include <algorithm><br>
<br>
Removed: llvm/trunk/lib/IR/AttributeSet<wbr>Node.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeSetNode.h?rev=299898&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/Attrib<wbr>uteSetNode.h?rev=299898&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/AttributeSet<wbr>Node.h (original)<br>
+++ llvm/trunk/lib/IR/AttributeSet<wbr>Node.h (removed)<br>
@@ -1,107 +0,0 @@<br>
-//===-- AttributeSetNode.h - AttributeList Internal Node ---------*- C++<br>
-//-*-===//<br>
-//<br>
-//                     The LLVM Compiler Infrastructure<br>
-//<br>
-// This file is distributed under the University of Illinois Open Source<br>
-// License. See LICENSE.TXT for details.<br>
-//<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-///<br>
-/// \file<br>
-/// \brief This file defines the node class used internally by AttributeList.<br>
-///<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-<br>
-#ifndef LLVM_IR_ATTRIBUTESETNODE_H<br>
-#define LLVM_IR_ATTRIBUTESETNODE_H<br>
-<br>
-#include "llvm/ADT/ArrayRef.h"<br>
-#include "llvm/ADT/FoldingSet.h"<br>
-#include "llvm/ADT/Optional.h"<br>
-#include "llvm/ADT/StringRef.h"<br>
-#include "llvm/IR/Attributes.h"<br>
-#include "llvm/Support/TrailingObjects.<wbr>h"<br>
-#include <algorithm><br>
-#include <climits><br>
-#include <cstdint><br>
-#include <string><br>
-#include <utility><br>
-<br>
-namespace llvm {<br>
-<br>
-//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
-/// \class<br>
-/// \brief This class represents a group of attributes that apply to one<br>
-/// element: function, return type, or parameter.<br>
-class AttributeSetNode final<br>
-    : public FoldingSetNode,<br>
-      private TrailingObjects<AttributeSetNo<wbr>de, Attribute> {<br>
-  friend TrailingObjects;<br>
-<br>
-  unsigned NumAttrs; ///< Number of attributes in this node.<br>
-  /// Bitset with a bit for each available attribute Attribute::AttrKind.<br>
-  uint64_t AvailableAttrs;<br>
-<br>
-  AttributeSetNode(ArrayRef<Attr<wbr>ibute> Attrs)<br>
-    : NumAttrs(Attrs.size()), AvailableAttrs(0) {<br>
-    static_assert(Attribute::EndAt<wbr>trKinds <= sizeof(AvailableAttrs) * CHAR_BIT,<br>
-                  "Too many attributes for AvailableAttrs");<br>
-    // There's memory after the node where we can store the entries in.<br>
-    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>(<wbr>));<br>
-<br>
-    for (Attribute I : *this) {<br>
-      if (!I.isStringAttribute()) {<br>
-        AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();<br>
-      }<br>
-    }<br>
-  }<br>
-<br>
-public:<br>
-  // AttributesSetNode is uniqued, these should not be available.<br>
-  AttributeSetNode(const AttributeSetNode &) = delete;<br>
-  AttributeSetNode &operator=(const AttributeSetNode &) = delete;<br>
-<br>
-  void operator delete(void *p) { ::operator delete(p); }<br>
-<br>
-  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);<br>
-<br>
-  static AttributeSetNode *get(AttributeList AS, unsigned Index) {<br>
-    return AS.getAttributes(Index);<br>
-  }<br>
-<br>
-  /// \brief Return the number of attributes this AttributeList contains.<br>
-  unsigned getNumAttributes() const { return NumAttrs; }<br>
-<br>
-  bool hasAttribute(Attribute::AttrKi<wbr>nd Kind) const {<br>
-    return AvailableAttrs & ((uint64_t)1) << Kind;<br>
-  }<br>
-  bool hasAttribute(StringRef Kind) const;<br>
-  bool hasAttributes() const { return NumAttrs != 0; }<br>
-<br>
-  Attribute getAttribute(Attribute::AttrKi<wbr>nd Kind) const;<br>
-  Attribute getAttribute(StringRef Kind) const;<br>
-<br>
-  unsigned getAlignment() const;<br>
-  unsigned getStackAlignment() const;<br>
-  uint64_t getDereferenceableBytes() const;<br>
-  uint64_t getDereferenceableOrNullBytes(<wbr>) const;<br>
-  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;<br>
-  std::string getAsString(bool InAttrGrp) const;<br>
-<br>
-  typedef const Attribute *iterator;<br>
-  iterator begin() const { return getTrailingObjects<Attribute>(<wbr>); }<br>
-  iterator end() const { return begin() + NumAttrs; }<br>
-<br>
-  void Profile(FoldingSetNodeID &ID) const {<br>
-    Profile(ID, makeArrayRef(begin(), end()));<br>
-  }<br>
-  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {<br>
-    for (const auto &Attr : AttrList)<br>
-      Attr.Profile(ID);<br>
-  }<br>
-};<br>
-<br>
-} // end namespace llvm<br>
-<br>
-#endif // LLVM_IR_ATTRIBUTESETNODE_H<br>
<br>
Modified: llvm/trunk/lib/IR/Attributes.c<wbr>pp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/Attrib<wbr>utes.cpp?rev=299899&r1=299898&<wbr>r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/Attributes.c<wbr>pp (original)<br>
+++ llvm/trunk/lib/IR/Attributes.c<wbr>pp Mon Apr 10 18:31:05 2017<br>
@@ -14,7 +14,6 @@<br>
 //===------------------------<wbr>------------------------------<wbr>----------------===//<br>
<br>
 #include "AttributeImpl.h"<br>
-#include "AttributeSetNode.h"<br>
 #include "LLVMContextImpl.h"<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/FoldingSet.h"<br>
@@ -24,6 +23,7 @@<br>
 #include "llvm/ADT/StringExtras.h"<br>
 #include "llvm/ADT/StringRef.h"<br>
 #include "llvm/ADT/Twine.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/Attributes.h"<br>
 #include "llvm/IR/Function.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
@@ -527,6 +527,48 @@ AttributeSetNode *AttributeSetNode::get(<br>
   return PA;<br>
 }<br>
<br>
+AttributeSetNode *AttributeSetNode::get(LLVMCon<wbr>text &C, const AttrBuilder &B) {<br>
+  // Add target-independent attributes.<br>
+  SmallVector<Attribute, 8> Attrs;<br>
+  for (Attribute::AttrKind Kind = Attribute::None;<br>
+       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {<br>
+    if (!B.contains(Kind))<br>
+      continue;<br>
+<br>
+    Attribute Attr;<br>
+    switch (Kind) {<br>
+    case Attribute::Alignment:<br>
+      Attr = Attribute::getWithAlignment(C, B.getAlignment());<br>
+      break;<br>
+    case Attribute::StackAlignment:<br>
+      Attr = Attribute::getWithStackAlignme<wbr>nt(C, B.getStackAlignment());<br>
+      break;<br>
+    case Attribute::Dereferenceable:<br>
+      Attr = Attribute::getWithDereferencea<wbr>bleBytes(<br>
+          C, B.getDereferenceableBytes());<br>
+      break;<br>
+    case Attribute::DereferenceableOrNu<wbr>ll:<br>
+      Attr = Attribute::getWithDereferencea<wbr>bleOrNullBytes(<br>
+          C, B.getDereferenceableOrNullByte<wbr>s());<br>
+      break;<br>
+    case Attribute::AllocSize: {<br>
+      auto A = B.getAllocSizeArgs();<br>
+      Attr = Attribute::getWithAllocSizeArg<wbr>s(C, A.first, A.second);<br>
+      break;<br>
+    }<br>
+    default:<br>
+      Attr = Attribute::get(C, Kind);<br>
+    }<br>
+    Attrs.push_back(Attr);<br>
+  }<br>
+<br>
+  // Add target-dependent (string) attributes.<br>
+  for (const auto &TDA : B.td_attrs())<br>
+    Attrs.emplace_back(Attribute::<wbr>get(C, TDA.first, TDA.second));<br>
+<br>
+  return get(C, Attrs);<br>
+}<br>
+<br>
 bool AttributeSetNode::hasAttribute<wbr>(StringRef Kind) const {<br>
   for (Attribute I : *this)<br>
     if (I.hasAttribute(Kind))<br>
@@ -612,6 +654,19 @@ LLVM_DUMP_METHOD void AttributeListImpl:<br>
<br>
 AttributeList AttributeList::getImpl(<br>
     LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSetNode *>> Attrs) {<br>
+  assert(!Attrs.empty() && "creating pointless AttributeList");<br>
+#ifndef NDEBUG<br>
+  unsigned LastIndex = 0;<br>
+  bool IsFirst = true;<br>
+  for (const auto &AttrPair : Attrs) {<br>
+    assert((IsFirst || LastIndex < AttrPair.first) &&<br>
+           "unsorted or duplicate AttributeList indices");<br>
+    assert(AttrPair.second && "pointless AttributeList slot");<br>
+    LastIndex = AttrPair.first;<br>
+    IsFirst = false;<br>
+  }<br>
+#endif<br>
+<br>
   LLVMContextImpl *pImpl = C.pImpl;<br>
   FoldingSetNodeID ID;<br>
   AttributeListImpl::Profile(<wbr>ID, Attrs);<br>
@@ -680,50 +735,32 @@ AttributeList::get(LLVMContext &C,<br>
   return getImpl(C, Attrs);<br>
 }<br>
<br>
+AttributeList AttributeList::get(LLVMContext &C, ArrayRef<AttributeSetNode*> Attrs) {<br>
+  assert(Attrs.size() >= 2 &&<br>
+         "should always have function and return attr slots");<br>
+  SmallVector<std::pair<unsigned<wbr>, AttributeSetNode *>, 8> AttrPairs;<br>
+  size_t Index = 0;<br>
+  for (AttributeSetNode *AS : Attrs) {<br>
+    if (AS) {<br>
+      // If this is the last AttributeSetNode, it's for the function.<br>
+      if (Index == Attrs.size() - 1)<br>
+        Index = AttributeList::FunctionIndex;<br>
+      AttrPairs.emplace_back(Index, AS);<br>
+    }<br>
+    ++Index;<br>
+  }<br>
+  if (AttrPairs.empty())<br>
+    return AttributeList();<br>
+  return getImpl(C, AttrPairs);<br>
+}<br>
+<br>
 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,<br>
                                  const AttrBuilder &B) {<br>
   if (!B.hasAttributes())<br>
     return AttributeList();<br>
-<br>
-  // Add target-independent attributes.<br>
-  SmallVector<std::pair<unsigned<wbr>, Attribute>, 8> Attrs;<br>
-  for (Attribute::AttrKind Kind = Attribute::None;<br>
-       Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {<br>
-    if (!B.contains(Kind))<br>
-      continue;<br>
-<br>
-    Attribute Attr;<br>
-    switch (Kind) {<br>
-    case Attribute::Alignment:<br>
-      Attr = Attribute::getWithAlignment(C, B.getAlignment());<br>
-      break;<br>
-    case Attribute::StackAlignment:<br>
-      Attr = Attribute::getWithStackAlignme<wbr>nt(C, B.getStackAlignment());<br>
-      break;<br>
-    case Attribute::Dereferenceable:<br>
-      Attr = Attribute::getWithDereferencea<wbr>bleBytes(<br>
-          C, B.getDereferenceableBytes());<br>
-      break;<br>
-    case Attribute::DereferenceableOrNu<wbr>ll:<br>
-      Attr = Attribute::getWithDereferencea<wbr>bleOrNullBytes(<br>
-          C, B.getDereferenceableOrNullByte<wbr>s());<br>
-      break;<br>
-    case Attribute::AllocSize: {<br>
-      auto A = B.getAllocSizeArgs();<br>
-      Attr = Attribute::getWithAllocSizeArg<wbr>s(C, A.first, A.second);<br>
-      break;<br>
-    }<br>
-    default:<br>
-      Attr = Attribute::get(C, Kind);<br>
-    }<br>
-    Attrs.emplace_back(Index, Attr);<br>
-  }<br>
-<br>
-  // Add target-dependent (string) attributes.<br>
-  for (const auto &TDA : B.td_attrs())<br>
-    Attrs.emplace_back(Index, Attribute::get(C, TDA.first, TDA.second));<br>
-<br>
-  return get(C, Attrs);<br>
+  AttributeSetNode *ASN = AttributeSetNode::get(C, B);<br>
+  std::pair<unsigned, AttributeSetNode *> Arr[1] = {{Index, ASN}};<br>
+  return getImpl(C, Arr);<br>
 }<br>
<br>
 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,<br>
@@ -791,31 +828,31 @@ AttributeList AttributeList::addAttribut<br>
 AttributeList AttributeList::addAttribute(LL<wbr>VMContext &C,<br>
                                           ArrayRef<unsigned> Indices,<br>
                                           Attribute A) const {<br>
-  unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;<br>
-  auto IdxI = Indices.begin(), IdxE = Indices.end();<br>
-  SmallVector<AttributeList, 4> AttrSet;<br>
+  assert(std::is_sorted(Indices.<wbr>begin(), Indices.end()));<br>
<br>
-  while (I != E && IdxI != IdxE) {<br>
-    if (getSlotIndex(I) < *IdxI)<br>
-      AttrSet.emplace_back(getSlotAt<wbr>tributes(I++));<br>
-    else if (getSlotIndex(I) > *IdxI)<br>
-      AttrSet.emplace_back(Attribute<wbr>List::get(C, std::make_pair(*IdxI++, A)));<br>
-    else {<br>
-      AttrBuilder B(getSlotAttributes(I), *IdxI);<br>
-      B.addAttribute(A);<br>
-      AttrSet.emplace_back(Attribute<wbr>List::get(C, *IdxI, B));<br>
+  unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0;<br>
+  SmallVector<IndexAttrPair, 4> AttrVec;<br>
+  for (unsigned Index : Indices) {<br>
+    // Add all attribute slots before the current index.<br>
+    for (; I < E && getSlotIndex(I) < Index; ++I)<br>
+      AttrVec.emplace_back(getSlotIn<wbr>dex(I), pImpl->getSlotNode(I));<br>
+<br>
+    // Add the attribute at this index. If we already have attributes at this<br>
+    // index, merge them into a new set.<br>
+    AttrBuilder B;<br>
+    if (I < E && getSlotIndex(I) == Index) {<br>
+      B.merge(AttrBuilder(pImpl->get<wbr>SlotNode(I)));<br>
       ++I;<br>
-      ++IdxI;<br>
     }<br>
+    B.addAttribute(A);<br>
+    AttrVec.emplace_back(Index, AttributeSetNode::get(C, B));<br>
   }<br>
<br>
-  while (I != E)<br>
-    AttrSet.emplace_back(getSlotAt<wbr>tributes(I++));<br>
+  // Add remaining attributes.<br>
+  for (; I < E; ++I)<br>
+    AttrVec.emplace_back(getSlotIn<wbr>dex(I), pImpl->getSlotNode(I));<br>
<br>
-  while (IdxI != IdxE)<br>
-    AttrSet.emplace_back(Attribute<wbr>List::get(C, std::make_pair(*IdxI++, A)));<br>
-<br>
-  return get(C, AttrSet);<br>
+  return get(C, AttrVec);<br>
 }<br>
<br>
 AttributeList AttributeList::addAttributes(L<wbr>LVMContext &C, unsigned Index,<br>
@@ -823,51 +860,58 @@ AttributeList AttributeList::addAttribut<br>
   if (!pImpl) return Attrs;<br>
   if (!Attrs.pImpl) return *this;<br>
<br>
+  return addAttributes(C, Index, Attrs.getAttributes(Index));<br>
+}<br>
+<br>
+AttributeList AttributeList::addAttributes(L<wbr>LVMContext &C, unsigned Index,<br>
+                                           AttributeSetNode *AS) const {<br>
+  if (!AS)<br>
+    return *this;<br>
+<br>
 #ifndef NDEBUG<br>
   // FIXME it is not obvious how this should work for alignment. For now, say<br>
   // we can't change a known alignment.<br>
   unsigned OldAlign = getParamAlignment(Index);<br>
-  unsigned NewAlign = Attrs.getParamAlignment(Index)<wbr>;<br>
+  unsigned NewAlign = AS->getAlignment();<br>
   assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&<br>
          "Attempt to change alignment!");<br>
 #endif<br>
<br>
-  // Add the attribute slots before the one we're trying to add.<br>
-  SmallVector<AttributeList, 4> AttrSet;<br>
+  SmallVector<std::pair<unsigned<wbr>, AttributeSetNode *>, 4> AttrSet;<br>
   uint64_t NumAttrs = pImpl->getNumSlots();<br>
-  AttributeList AS;<br>
-  uint64_t LastIndex = 0;<br>
-  for (unsigned I = 0, E = NumAttrs; I != E; ++I) {<br>
-    if (getSlotIndex(I) >= Index) {<br>
-      if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++)<wbr>;<br>
-      break;<br>
-    }<br>
-    LastIndex = I + 1;<br>
-    AttrSet.push_back(getSlotAttri<wbr>butes(I));<br>
-  }<br>
+  unsigned I;<br>
<br>
-  // Now add the attribute into the correct slot. There may already be an<br>
-  // AttributeList there.<br>
-  AttrBuilder B(AS, Index);<br>
-<br>
-  for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I)<br>
-    if (Attrs.getSlotIndex(I) == Index) {<br>
-      for (AttributeListImpl::iterator II = Attrs.pImpl->begin(I),<br>
-                                       IE = Attrs.pImpl->end(I);<br>
-           II != IE; ++II)<br>
-        B.addAttribute(*II);<br>
+  // Add all the attribute slots before the one we need to merge.<br>
+  for (I = 0; I < NumAttrs; ++I) {<br>
+    if (getSlotIndex(I) >= Index)<br>
       break;<br>
-    }<br>
+    AttrSet.emplace_back(getSlotIn<wbr>dex(I), pImpl->getSlotNode(I));<br>
+  }<br>
<br>
-  AttrSet.push_back(AttributeLis<wbr>t::get(C, Index, B));<br>
+  if (I < NumAttrs && getSlotIndex(I) == Index) {<br>
+    // We need to merge two AttributeSetNodes.<br>
+    AttributeSetNode *Merged = AttributeSetNode::get(<br>
+        C, AttrBuilder(pImpl->getSlotNode<wbr>(I)).merge(AttrBuilder(AS)));<br>
+    AttrSet.emplace_back(Index, Merged);<br>
+    ++I;<br>
+  } else {<br>
+    // Otherwise, there were no attributes at this position in the original<br>
+    // list. Add the set as is.<br>
+    AttrSet.emplace_back(Index, AS);<br>
+  }<br>
<br>
-  // Add the remaining attribute slots.<br>
-  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)<br>
-    AttrSet.push_back(getSlotAttri<wbr>butes(I));<br>
+  // Add the remaining entries.<br>
+  for (; I < NumAttrs; ++I)<br>
+    AttrSet.emplace_back(getSlotIn<wbr>dex(I), pImpl->getSlotNode(I));<br>
<br>
   return get(C, AttrSet);<br>
 }<br>
<br>
+AttributeList AttributeList::addAttributes(L<wbr>LVMContext &C, unsigned Index,<br>
+                                           const AttrBuilder &B) const {<br>
+  return get(C, Index, AttributeSetNode::get(C, B));<br>
+}<br>
+<br>
 AttributeList AttributeList::removeAttribute<wbr>(LLVMContext &C, unsigned Index,<br>
                                              Attribute::AttrKind Kind) const {<br>
   if (!hasAttribute(Index, Kind)) return *this;<br>
@@ -961,6 +1005,20 @@ AttributeList AttributeList::removeAttri<br>
   return get(C, AttrSet);<br>
 }<br>
<br>
+AttributeList AttributeList::removeAttribute<wbr>s(LLVMContext &C,<br>
+                                              unsigned WithoutIndex) const {<br>
+  if (!pImpl)<br>
+    return AttributeList();<br>
+<br>
+  SmallVector<std::pair<unsigned<wbr>, AttributeSetNode *>, 4> AttrSet;<br>
+  for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) {<br>
+    unsigned Index = getSlotIndex(I);<br>
+    if (Index != WithoutIndex)<br>
+      AttrSet.push_back({Index, pImpl->getSlotNode(I)});<br>
+  }<br>
+  return get(C, AttrSet);<br>
+}<br>
+<br>
 AttributeList AttributeList::addDereferencea<wbr>bleAttr(LLVMContext &C,<br>
                                                     unsigned Index,<br>
                                                     uint64_t Bytes) const {<br>
@@ -992,32 +1050,16 @@ AttributeList::addAllocSizeAtt<wbr>r(LLVMCont<br>
<br>
 LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }<br>
<br>
-AttributeList AttributeList::getParamAttribu<wbr>tes(unsigned Index) const {<br>
-  return pImpl && hasAttributes(Index)<br>
-             ? AttributeList::get(<br>
-                   pImpl->getContext(),<br>
-                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(<br>
-                       std::make_pair(Index, getAttributes(Index))))<br>
-             : AttributeList();<br>
-}<br>
-<br>
-AttributeList AttributeList::getRetAttribute<wbr>s() const {<br>
-  return pImpl && hasAttributes(ReturnIndex)<br>
-             ? AttributeList::get(<br>
-                   pImpl->getContext(),<br>
-                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(<br>
-                       std::make_pair(ReturnIndex, getAttributes(ReturnIndex))))<br>
-             : AttributeList();<br>
-}<br>
-<br>
-AttributeList AttributeList::getFnAttributes<wbr>() const {<br>
-  return pImpl && hasAttributes(FunctionIndex)<br>
-             ? AttributeList::get(<br>
-                   pImpl->getContext(),<br>
-                   ArrayRef<std::pair<unsigned, AttributeSetNode *>>(<br>
-                       std::make_pair(FunctionIndex,<br>
-                                      getAttributes(FunctionIndex)))<wbr>)<br>
-             : AttributeList();<br>
+AttributeSetNode *AttributeList::getParamAttrib<wbr>utes(unsigned Index) const {<br>
+  return getAttributes(Index);<br>
+}<br>
+<br>
+AttributeSetNode *AttributeList::getRetAttribut<wbr>es() const {<br>
+  return getAttributes(ReturnIndex);<br>
+}<br>
+<br>
+AttributeSetNode *AttributeList::getFnAttribute<wbr>s() const {<br>
+  return getAttributes(FunctionIndex);<br>
 }<br>
<br>
 bool AttributeList::hasAttribute(un<wbr>signed Index,<br>
@@ -1181,6 +1223,13 @@ AttrBuilder::AttrBuilder(Attri<wbr>buteList A<br>
   }<br>
 }<br>
<br>
+AttrBuilder::AttrBuilder(Attr<wbr>ibuteSetNode *AS) {<br>
+  if (AS) {<br>
+    for (const Attribute &A : *AS)<br>
+      addAttribute(A);<br>
+  }<br>
+}<br>
+<br>
 void AttrBuilder::clear() {<br>
   Attrs.reset();<br>
   TargetDepAttrs.clear();<br>
<br>
Modified: llvm/trunk/lib/IR/Core.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Core.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/IR/Core.<wbr>cpp?rev=299899&r1=299898&r2=<wbr>299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/IR/Core.cpp (original)<br>
+++ llvm/trunk/lib/IR/Core.cpp Mon Apr 10 18:31:05 2017<br>
@@ -16,7 +16,7 @@<br>
 #include "llvm/ADT/StringSwitch.h"<br>
 #include "llvm/Bitcode/BitcodeReader.h"<br>
 #include "llvm/IR/Attributes.h"<br>
-#include "AttributeSetNode.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/DerivedTypes.h"<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/<wbr>ArgumentPromotion.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/IPO/ArgumentPromotion.cpp?<wbr>rev=299899&r1=299898&r2=<wbr>299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/IPO/<wbr>ArgumentPromotion.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/<wbr>ArgumentPromotion.cpp Mon Apr 10 18:31:05 2017<br>
@@ -42,6 +42,7 @@<br>
 #include "llvm/Analysis/LazyCallGraph.h<wbr>"<br>
 #include "llvm/Analysis/Loads.h"<br>
 #include "llvm/Analysis/TargetLibraryIn<wbr>fo.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/CFG.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/Constants.h"<br>
@@ -102,13 +103,11 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
   // Attribute - Keep track of the parameter attributes for the arguments<br>
   // that we are *not* promoting. For the ones that we do promote, the parameter<br>
   // attributes are lost<br>
-  SmallVector<AttributeList, 8> AttributesVec;<br>
+  SmallVector<AttributeSetNode *, 8> AttributesVec;<br>
   const AttributeList &PAL = F->getAttributes();<br>
<br>
   // Add any return attributes.<br>
-  if (PAL.hasAttributes(AttributeLi<wbr>st::ReturnIndex))<br>
-    AttributesVec.push_back(<br>
-        AttributeList::get(F->getConte<wbr>xt(), PAL.getRetAttributes()));<br>
+  AttributesVec.push_back(PAL.ge<wbr>tRetAttributes());<br>
<br>
   // First, determine the new argument list<br>
   unsigned ArgIndex = 1;<br>
@@ -119,16 +118,12 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
       Type *AgTy = cast<PointerType>(I->getType()<wbr>)->getElementType();<br>
       StructType *STy = cast<StructType>(AgTy);<br>
       Params.insert(Params.end(), STy->element_begin(), STy->element_end());<br>
+      AttributesVec.insert(Attribute<wbr>sVec.end(), STy->getNumElements(), nullptr);<br>
       ++NumByValArgsPromoted;<br>
     } else if (!ArgsToPromote.count(&*I)) {<br>
       // Unchanged argument<br>
       Params.push_back(I->getType()<wbr>);<br>
-      AttributeList attrs = PAL.getParamAttributes(ArgInde<wbr>x);<br>
-      if (attrs.hasAttributes(ArgIndex)<wbr>) {<br>
-        AttrBuilder B(attrs, ArgIndex);<br>
-        AttributesVec.push_back(<br>
-            AttributeList::get(F->getConte<wbr>xt(), Params.size(), B));<br>
-      }<br>
+      AttributesVec.push_back(PAL.ge<wbr>tParamAttributes(ArgIndex));<br>
     } else if (I->use_empty()) {<br>
       // Dead argument (which are always marked as promotable)<br>
       ++NumArgumentsDead;<br>
@@ -173,6 +168,7 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
         Params.push_back(GetElementPt<wbr>rInst::getIndexedType(<br>
             cast<PointerType>(I->getType(<wbr>)->getScalarType())->getElemen<wbr>tType(),<br>
             ArgIndex.second));<br>
+        AttributesVec.push_back(nullpt<wbr>r);<br>
         assert(Params.back());<br>
       }<br>
<br>
@@ -184,9 +180,7 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
   }<br>
<br>
   // Add any function attributes.<br>
-  if (PAL.hasAttributes(AttributeLi<wbr>st::FunctionIndex))<br>
-    AttributesVec.push_back(<br>
-        AttributeList::get(FTy->getCon<wbr>text(), PAL.getFnAttributes()));<br>
+  AttributesVec.push_back(PAL.ge<wbr>tFnAttributes());<br>
<br>
   Type *RetTy = FTy->getReturnType();<br>
<br>
@@ -223,9 +217,7 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
     const AttributeList &CallPAL = CS.getAttributes();<br>
<br>
     // Add any return attributes.<br>
-    if (CallPAL.hasAttributes(Attribu<wbr>teList::ReturnIndex))<br>
-      AttributesVec.push_back(<br>
-          AttributeList::get(F->getConte<wbr>xt(), CallPAL.getRetAttributes()));<br>
+    AttributesVec.push_back(CallPA<wbr>L.getRetAttributes());<br>
<br>
     // Loop over the operands, inserting GEP and loads in the caller as<br>
     // appropriate.<br>
@@ -235,12 +227,7 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
          ++I, ++AI, ++ArgIndex)<br>
       if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*<wbr>I)) {<br>
         Args.push_back(*AI); // Unmodified argument<br>
-<br>
-        if (CallPAL.hasAttributes(ArgInde<wbr>x)) {<br>
-          AttrBuilder B(CallPAL, ArgIndex);<br>
-          AttributesVec.push_back(<br>
-              AttributeList::get(F->getConte<wbr>xt(), Args.size(), B));<br>
-        }<br>
+        AttributesVec.push_back(CallPA<wbr>L.getAttributes(ArgIndex));<br>
       } else if (ByValArgsToTransform.count(&*<wbr>I)) {<br>
         // Emit a GEP and load for each element of the struct.<br>
         Type *AgTy = cast<PointerType>(I->getType()<wbr>)->getElementType();<br>
@@ -253,6 +240,7 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
               STy, *AI, Idxs, (*AI)->getName() + "." + Twine(i), Call);<br>
           // TODO: Tell AA about the new values?<br>
           Args.push_back(new LoadInst(Idx, Idx->getName() + ".val", Call));<br>
+          AttributesVec.push_back(nullpt<wbr>r);<br>
         }<br>
       } else if (!I->use_empty()) {<br>
         // Non-dead argument: insert GEPs and loads as appropriate.<br>
@@ -295,23 +283,18 @@ doPromotion(Function *F, SmallPtrSetImpl<br>
           newLoad->setAAMetadata(<wbr>AAInfo);<br>
<br>
           Args.push_back(newLoad);<br>
+          AttributesVec.push_back(nullpt<wbr>r);<br>
         }<br>
       }<br>
<br>
     // Push any varargs arguments on the list.<br>
     for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {<br>
       Args.push_back(*AI);<br>
-      if (CallPAL.hasAttributes(ArgInde<wbr>x)) {<br>
-        AttrBuilder B(CallPAL, ArgIndex);<br>
-        AttributesVec.push_back(<br>
-            AttributeList::get(F->getConte<wbr>xt(), Args.size(), B));<br>
-      }<br>
+      AttributesVec.push_back(CallPA<wbr>L.getAttributes(ArgIndex));<br>
     }<br>
<br>
     // Add any function attributes.<br>
-    if (CallPAL.hasAttributes(Attribu<wbr>teList::FunctionIndex))<br>
-      AttributesVec.push_back(<br>
-          AttributeList::get(Call->getCo<wbr>ntext(), CallPAL.getFnAttributes()));<br>
+    AttributesVec.push_back(CallPA<wbr>L.getFnAttributes());<br>
<br>
     SmallVector<OperandBundleDef, 1> OpBundles;<br>
     CS.getOperandBundlesAsDefs(Op<wbr>Bundles);<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/<wbr>DeadArgumentElimination.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/IPO/DeadArgumentElimination.<wbr>cpp?rev=299899&r1=299898&r2=29<wbr>9899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/IPO/<wbr>DeadArgumentElimination.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/<wbr>DeadArgumentElimination.cpp Mon Apr 10 18:31:05 2017<br>
@@ -21,6 +21,7 @@<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/ADT/StringExtras.h"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/CallingConv.h"<br>
 #include "llvm/IR/Constant.h"<br>
@@ -172,8 +173,9 @@ bool DeadArgumentEliminationPass::D<wbr>elete<br>
       for (unsigned i = 0; PAL.getSlotIndex(i) <= NumArgs; ++i)<br>
         AttributesVec.push_back(PAL.g<wbr>etSlotAttributes(i));<br>
       if (PAL.hasAttributes(AttributeLi<wbr>st::FunctionIndex))<br>
-        AttributesVec.push_back(<br>
-            AttributeList::get(Fn.getConte<wbr>xt(), PAL.getFnAttributes()));<br>
+        AttributesVec.push_back(Attrib<wbr>uteList::get(Fn.getContext(),<br>
+                                                   AttributeList::FunctionIndex,<br>
+                                                   PAL.getFnAttributes()));<br>
       PAL = AttributeList::get(Fn.getConte<wbr>xt(), AttributesVec);<br>
     }<br>
<br>
@@ -684,9 +686,13 @@ bool DeadArgumentEliminationPass::R<wbr>emove<br>
   bool HasLiveReturnedArg = false;<br>
<br>
   // Set up to build a new list of parameter attributes.<br>
-  SmallVector<AttributeList, 8> AttributesVec;<br>
+  SmallVector<AttributeSetNode *, 8> AttributesVec;<br>
   const AttributeList &PAL = F->getAttributes();<br>
<br>
+  // Reserve an empty slot for the return value attributes, which we will<br>
+  // compute last.<br>
+  AttributesVec.push_back(nullpt<wbr>r);<br>
+<br>
   // Remember which arguments are still alive.<br>
   SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false);<br>
   // Construct the new parameter list from non-dead arguments. Also construct<br>
@@ -699,16 +705,8 @@ bool DeadArgumentEliminationPass::R<wbr>emove<br>
     if (LiveValues.erase(Arg)) {<br>
       Params.push_back(I->getType()<wbr>);<br>
       ArgAlive[i] = true;<br>
-<br>
-      // Get the original parameter attributes (skipping the first one, that is<br>
-      // for the return value.<br>
-      if (PAL.hasAttributes(i + 1)) {<br>
-        AttrBuilder B(PAL, i + 1);<br>
-        if (B.contains(Attribute::Returne<wbr>d))<br>
-          HasLiveReturnedArg = true;<br>
-        AttributesVec.push_back(<br>
-            AttributeList::get(F->getConte<wbr>xt(), Params.size(), B));<br>
-      }<br>
+      AttributesVec.push_back(PAL.ge<wbr>tParamAttributes(i + 1));<br>
+      HasLiveReturnedArg |= PAL.hasAttribute(i + 1, Attribute::Returned);<br>
     } else {<br>
       ++NumArgumentsEliminated;<br>
       DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing argument " << i<br>
@@ -782,29 +780,25 @@ bool DeadArgumentEliminationPass::R<wbr>emove<br>
   assert(NRetTy && "No new return type found?");<br>
<br>
   // The existing function return attributes.<br>
-  AttributeList RAttrs = PAL.getRetAttributes();<br>
+  AttrBuilder RAttrs(PAL.getRetAttributes())<wbr>;<br>
<br>
   // Remove any incompatible attributes, but only if we removed all return<br>
   // values. Otherwise, ensure that we don't have any conflicting attributes<br>
   // here. Currently, this should not be possible, but special handling might be<br>
   // required when new return value attributes are added.<br>
   if (NRetTy->isVoidTy())<br>
-    RAttrs = RAttrs.removeAttributes(NRetTy<wbr>->getContext(),<br>
-                                     AttributeList::ReturnIndex,<br>
-                                     AttributeFuncs::typeIncompati<wbr>ble(NRetTy));<br>
+    RAttrs.remove(AttributeFuncs::<wbr>typeIncompatible(NRetTy));<br>
   else<br>
-    assert(!AttrBuilder(RAttrs, AttributeList::ReturnIndex)<br>
-                .overlaps(AttributeFuncs::type<wbr>Incompatible(NRetTy)) &&<br>
+    assert(!RAttrs.overlaps(Attrib<wbr>uteFuncs::typeIncompatible(<wbr>NRetTy)) &&<br>
            "Return attributes no longer compatible?");<br>
<br>
-  if (RAttrs.hasAttributes(Attribut<wbr>eList::ReturnIndex))<br>
-    AttributesVec.push_back(Attrib<wbr>uteList::get(NRetTy->getContex<wbr>t(), RAttrs));<br>
+  AttributesVec[0] = AttributeSetNode::get(F->getCo<wbr>ntext(), RAttrs);<br>
<br>
-  if (PAL.hasAttributes(AttributeLi<wbr>st::FunctionIndex))<br>
-    AttributesVec.push_back(<br>
-        AttributeList::get(F->getConte<wbr>xt(), PAL.getFnAttributes()));<br>
+  // Transfer the function attributes, if any.<br>
+  AttributesVec.push_back(PAL.ge<wbr>tFnAttributes());<br>
<br>
   // Reconstruct the AttributesList based on the vector we constructed.<br>
+  assert(AttributesVec.size() == Params.size() + 2);<br>
   AttributeList NewPAL = AttributeList::get(F->getConte<wbr>xt(), AttributesVec);<br>
<br>
   // Create the new function type based on the recomputed parameters.<br>
@@ -835,15 +829,11 @@ bool DeadArgumentEliminationPass::R<wbr>emove<br>
     AttributesVec.clear();<br>
     const AttributeList &CallPAL = CS.getAttributes();<br>
<br>
-    // The call return attributes.<br>
-    AttributeList RAttrs = CallPAL.getRetAttributes();<br>
-<br>
-    // Adjust in case the function was changed to return void.<br>
-    RAttrs = RAttrs.removeAttributes(<br>
-        NRetTy->getContext(), AttributeList::ReturnIndex,<br>
-        AttributeFuncs::typeIncompatib<wbr>le(NF->getReturnType()));<br>
-    if (RAttrs.hasAttributes(Attribut<wbr>eList::ReturnIndex))<br>
-      AttributesVec.push_back(Attrib<wbr>uteList::get(NF->getContext(), RAttrs));<br>
+    // Adjust the call return attributes in case the function was changed to<br>
+    // return void.<br>
+    AttrBuilder RAttrs(CallPAL.getRetAttribute<wbr>s());<br>
+    RAttrs.remove(AttributeFuncs::<wbr>typeIncompatible(NRetTy));<br>
+    AttributesVec.push_back(Attrib<wbr>uteSetNode::get(F->getContext(<wbr>), RAttrs));<br>
<br>
     // Declare these outside of the loops, so we can reuse them for the second<br>
     // loop, which loops the varargs.<br>
@@ -855,33 +845,30 @@ bool DeadArgumentEliminationPass::R<wbr>emove<br>
       if (ArgAlive[i]) {<br>
         Args.push_back(*I);<br>
         // Get original parameter attributes, but skip return attributes.<br>
-        if (CallPAL.hasAttributes(i + 1)) {<br>
-          AttrBuilder B(CallPAL, i + 1);<br>
+        AttributeSetNode *Attrs = CallPAL.getParamAttributes(i + 1);<br>
+        if (NRetTy != RetTy && Attrs &&<br>
+            Attrs->hasAttribute(Attribute:<wbr>:Returned)) {<br>
           // If the return type has changed, then get rid of 'returned' on the<br>
           // call site. The alternative is to make all 'returned' attributes on<br>
           // call sites keep the return value alive just like 'returned'<br>
-          // attributes on function declaration but it's less clearly a win<br>
-          // and this is not an expected case anyway<br>
-          if (NRetTy != RetTy && B.contains(Attribute::Returned<wbr>))<br>
-            B.removeAttribute(Attribute::R<wbr>eturned);<br>
-          AttributesVec.push_back(<br>
-              AttributeList::get(F->getConte<wbr>xt(), Args.size(), B));<br>
+          // attributes on function declaration but it's less clearly a win and<br>
+          // this is not an expected case anyway<br>
+          AttributesVec.push_back(Attrib<wbr>uteSetNode::get(<br>
+              F->getContext(),<br>
+              AttrBuilder(Attrs).removeAttri<wbr>bute(Attribute::Returned)));<br>
+        } else {<br>
+          // Otherwise, use the original attributes.<br>
+          AttributesVec.push_back(Attrs)<wbr>;<br>
         }<br>
       }<br>
<br>
     // Push any varargs arguments on the list. Don't forget their attributes.<br>
     for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) {<br>
       Args.push_back(*I);<br>
-      if (CallPAL.hasAttributes(i + 1)) {<br>
-        AttrBuilder B(CallPAL, i + 1);<br>
-        AttributesVec.push_back(<br>
-            AttributeList::get(F->getConte<wbr>xt(), Args.size(), B));<br>
-      }<br>
+      AttributesVec.push_back(CallPA<wbr>L.getParamAttributes(i + 1));<br>
     }<br>
<br>
-    if (CallPAL.hasAttributes(Attribu<wbr>teList::FunctionIndex))<br>
-      AttributesVec.push_back(<br>
-          AttributeList::get(Call->getCo<wbr>ntext(), CallPAL.getFnAttributes()));<br>
+    AttributesVec.push_back(CallPA<wbr>L.getFnAttributes());<br>
<br>
     // Reconstruct the AttributesList based on the vector we constructed.<br>
     AttributeList NewCallPAL =<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/<wbr>MergeFunctions.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/IPO/MergeFunctions.cpp?rev=<wbr>299899&r1=299898&r2=299899&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/IPO/<wbr>MergeFunctions.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/<wbr>MergeFunctions.cpp Mon Apr 10 18:31:05 2017<br>
@@ -439,8 +439,7 @@ void MergeFunctions::replaceDirectC<wbr>aller<br>
           Context, AttributeList::ReturnIndex, NewFuncAttrs.getRetAttributes(<wbr>));<br>
<br>
       for (unsigned argIdx = 0; argIdx < CS.arg_size(); argIdx++) {<br>
-        AttributeList Attrs = NewFuncAttrs.getParamAttribute<wbr>s(argIdx);<br>
-        if (Attrs.getNumSlots())<br>
+        if (AttributeSetNode *Attrs = NewFuncAttrs.getParamAttribute<wbr>s(argIdx))<br>
           CallSiteAttrs = CallSiteAttrs.addAttributes(Co<wbr>ntext, argIdx, Attrs);<br>
       }<br>
<br>
<br>
Modified: llvm/trunk/lib/Transforms/Inst<wbr>Combine/InstCombineCalls.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/InstCombine/InstCombineCalls<wbr>.cpp?rev=299899&r1=299898&r2=<wbr>299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Inst<wbr>Combine/InstCombineCalls.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Inst<wbr>Combine/InstCombineCalls.cpp Mon Apr 10 18:31:05 2017<br>
@@ -23,6 +23,7 @@<br>
 #include "llvm/Analysis/InstructionSimp<wbr>lify.h"<br>
 #include "llvm/Analysis/MemoryBuiltins.<wbr>h"<br>
 #include "llvm/Analysis/ValueTracking.h<wbr>"<br>
+#include "llvm/IR/AttributeSetNode.h"<br>
 #include "llvm/IR/BasicBlock.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/Constant.h"<br>
@@ -3992,7 +3993,7 @@ bool InstCombiner::transformConstEx<wbr>prCas<br>
     if (!CastInst::isBitOrNoopPointer<wbr>Castable(ActTy, ParamTy, DL))<br>
       return false;   // Cannot transform this parameter value.<br>
<br>
-    if (AttrBuilder(CallerPAL.getPara<wbr>mAttributes(i + 1), i + 1).<br>
+    if (AttrBuilder(CallerPAL.getPara<wbr>mAttributes(i + 1)).<br>
           overlaps(AttributeFuncs::type<wbr>Incompatible(ParamTy)))<br>
       return false;   // Attribute not compatible with transformed value.<br>
<br>
@@ -4001,9 +4002,7 @@ bool InstCombiner::transformConstEx<wbr>prCas<br>
<br>
     // If the parameter is passed as a byval argument, then we have to have a<br>
     // sized type and the sized type has to have the same size as the old type.<br>
-    if (ParamTy != ActTy &&<br>
-        CallerPAL.getParamAttributes(i + 1).hasAttribute(i + 1,<br>
-                                                         Attribute::ByVal)) {<br>
+    if (ParamTy != ActTy && CallerPAL.hasAttribute(i + 1, Attribute::ByVal)) {<br>
       PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy)<wbr>;<br>
       if (!ParamPTy || !ParamPTy->getElementType()->i<wbr>sSized())<br>
         return false;<br>
@@ -4084,7 +4083,7 @@ bool InstCombiner::transformConstEx<wbr>prCas<br>
     }<br>
<br>
     // Add any parameter attributes.<br>
-    AttrBuilder PAttrs(CallerPAL.getParamAttri<wbr>butes(i + 1), i + 1);<br>
+    AttrBuilder PAttrs(CallerPAL.getParamAttri<wbr>butes(i + 1));<br>
     if (PAttrs.hasAttributes())<br>
       attrVec.push_back(<br>
           AttributeList::get(Caller->ge<wbr>tContext(), i + 1, PAttrs));<br>
@@ -4112,7 +4111,7 @@ bool InstCombiner::transformConstEx<wbr>prCas<br>
         }<br>
<br>
         // Add any parameter attributes.<br>
-        AttrBuilder PAttrs(CallerPAL.getParamAttri<wbr>butes(i + 1), i + 1);<br>
+        AttrBuilder PAttrs(CallerPAL.getParamAttri<wbr>butes(i + 1));<br>
         if (PAttrs.hasAttributes())<br>
           attrVec.push_back(<br>
               AttributeList::get(FT->getCon<wbr>text(), i + 1, PAttrs));<br>
@@ -4120,9 +4119,11 @@ bool InstCombiner::transformConstEx<wbr>prCas<br>
     }<br>
   }<br>
<br>
-  AttributeList FnAttrs = CallerPAL.getFnAttributes();<br>
+  AttributeSetNode *FnAttrs = CallerPAL.getFnAttributes();<br>
   if (CallerPAL.hasAttributes(Attri<wbr>buteList::FunctionIndex))<br>
-    attrVec.push_back(AttributeLis<wbr>t::get(Callee->getContext(), FnAttrs));<br>
+    attrVec.push_back(AttributeLis<wbr>t::get(Callee->getContext(),<br>
+                                         AttributeList::FunctionIndex,<br>
+                                         AttrBuilder(FnAttrs)));<br>
<br>
   if (NewRetTy->isVoidTy())<br>
     Caller->setName("");   // Void type should not have a name.<br>
@@ -4200,7 +4201,7 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
   Value *Callee = CS.getCalledValue();<br>
   PointerType *PTy = cast<PointerType>(Callee->getT<wbr>ype());<br>
   FunctionType *FTy = cast<FunctionType>(PTy->getEle<wbr>mentType());<br>
-  const AttributeList &Attrs = CS.getAttributes();<br>
+  AttributeList Attrs = CS.getAttributes();<br>
<br>
   // If the call already has the 'nest' attribute somewhere then give up -<br>
   // otherwise 'nest' would occur twice after splicing in the chain.<br>
@@ -4213,11 +4214,11 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
   Function *NestF =cast<Function>(Tramp->getArgO<wbr>perand(1)->stripPointerCasts()<wbr>);<br>
   FunctionType *NestFTy = cast<FunctionType>(NestF->getV<wbr>alueType());<br>
<br>
-  const AttributeList &NestAttrs = NestF->getAttributes();<br>
+  AttributeList NestAttrs = NestF->getAttributes();<br>
   if (!NestAttrs.isEmpty()) {<br>
     unsigned NestIdx = 1;<br>
     Type *NestTy = nullptr;<br>
-    AttributeList NestAttr;<br>
+    AttributeSetNode *NestAttr;<br>
<br>
     // Look for a parameter marked with the 'nest' attribute.<br>
     for (FunctionType::param_iterator I = NestFTy->param_begin(),<br>
@@ -4232,18 +4233,15 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
     if (NestTy) {<br>
       Instruction *Caller = CS.getInstruction();<br>
       std::vector<Value*> NewArgs;<br>
+      std::vector<AttributeSetNode *> NewAttrs;<br>
       NewArgs.reserve(CS.arg_size() + 1);<br>
-<br>
-      SmallVector<AttributeList, 8> NewAttrs;<br>
-      NewAttrs.reserve(Attrs.getNumS<wbr>lots() + 1);<br>
+      NewAttrs.reserve(CS.arg_size() + 2);<br>
<br>
       // Insert the nest argument into the call argument list, which may<br>
       // mean appending it.  Likewise for attributes.<br>
<br>
       // Add any result attributes.<br>
-      if (Attrs.hasAttributes(Attribute<wbr>List::ReturnIndex))<br>
-        NewAttrs.push_back(<br>
-            AttributeList::get(Caller->get<wbr>Context(), Attrs.getRetAttributes()));<br>
+      NewAttrs.push_back(Attrs.getRe<wbr>tAttributes());<br>
<br>
       {<br>
         unsigned Idx = 1;<br>
@@ -4255,8 +4253,7 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
             if (NestVal->getType() != NestTy)<br>
               NestVal = Builder->CreateBitCast(NestVal<wbr>, NestTy, "nest");<br>
             NewArgs.push_back(NestVal);<br>
-            NewAttrs.push_back(<br>
-                AttributeList::get(Caller->get<wbr>Context(), NestAttr));<br>
+            NewAttrs.push_back(NestAttr);<br>
           }<br>
<br>
           if (I == E)<br>
@@ -4264,12 +4261,7 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
<br>
           // Add the original argument and attributes.<br>
           NewArgs.push_back(*I);<br>
-          AttributeList Attr = Attrs.getParamAttributes(Idx);<br>
-          if (Attr.hasAttributes(Idx)) {<br>
-            AttrBuilder B(Attr, Idx);<br>
-            NewAttrs.push_back(AttributeLi<wbr>st::get(Caller->getContext(),<br>
-                                                  Idx + (Idx >= NestIdx), B));<br>
-          }<br>
+          NewAttrs.push_back(Attrs.getPa<wbr>ramAttributes(Idx));<br>
<br>
           ++Idx;<br>
           ++I;<br>
@@ -4277,9 +4269,7 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
       }<br>
<br>
       // Add any function attributes.<br>
-      if (Attrs.hasAttributes(Attribute<wbr>List::FunctionIndex))<br>
-        NewAttrs.push_back(<br>
-            AttributeList::get(FTy->getCon<wbr>text(), Attrs.getFnAttributes()));<br>
+      NewAttrs.push_back(Attrs.getFn<wbr>Attributes());<br>
<br>
       // The trampoline may have been bitcast to a bogus type (FTy).<br>
       // Handle this by synthesizing a new function type, equal to FTy<br>
@@ -4319,8 +4309,7 @@ InstCombiner::transformCallThr<wbr>oughTrampo<br>
         NestF->getType() == PointerType::getUnqual(NewFTy) ?<br>
         NestF : ConstantExpr::getBitCast(NestF<wbr>,<br>
                                          PointerType::getUnqual(NewFTy)<wbr>);<br>
-      const AttributeList &NewPAL =<br>
-          AttributeList::get(FTy->getCon<wbr>text(), NewAttrs);<br>
+      AttributeList NewPAL = AttributeList::get(FTy->getCon<wbr>text(), NewAttrs);<br>
<br>
       SmallVector<OperandBundleDef, 1> OpBundles;<br>
       CS.getOperandBundlesAsDefs(Op<wbr>Bundles);<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scal<wbr>ar/RewriteStatepointsForGC.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Scalar/RewriteStatepointsFor<wbr>GC.cpp?rev=299899&r1=299898&<wbr>r2=299899&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Scal<wbr>ar/RewriteStatepointsForGC.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scal<wbr>ar/RewriteStatepointsForGC.cpp Mon Apr 10 18:31:05 2017<br>
@@ -1392,7 +1392,6 @@ makeStatepointExplicitImpl(con<wbr>st CallSit<br>
<br>
   // Create the statepoint given all the arguments<br>
   Instruction *Token = nullptr;<br>
-  AttributeList ReturnAttrs;<br>
   if (CS.isCall()) {<br>
     CallInst *ToReplace = cast<CallInst>(CS.getInstructi<wbr>on());<br>
     CallInst *Call = Builder.CreateGCStatepointCall<wbr>(<br>
@@ -1407,8 +1406,9 @@ makeStatepointExplicitImpl(con<wbr>st CallSit<br>
     AttributeList NewAttrs = legalizeCallAttributes(ToRepla<wbr>ce->getAttributes());<br>
     // In case if we can handle this set of attributes - set up function attrs<br>
     // directly on statepoint and return attrs later for gc_result intrinsic.<br>
-    Call->setAttributes(NewAttrs.g<wbr>etFnAttributes());<br>
-    ReturnAttrs = NewAttrs.getRetAttributes();<br>
+    Call->setAttributes(AttributeL<wbr>ist::get(Call->getContext(),<br>
+                                           AttributeList::FunctionIndex,<br>
+                                           NewAttrs.getFnAttributes()));<br>
<br>
     Token = Call;<br>
<br>
@@ -1435,8 +1435,9 @@ makeStatepointExplicitImpl(con<wbr>st CallSit<br>
     AttributeList NewAttrs = legalizeCallAttributes(ToRepla<wbr>ce->getAttributes());<br>
     // In case if we can handle this set of attributes - set up function attrs<br>
     // directly on statepoint and return attrs later for gc_result intrinsic.<br>
-    Invoke->setAttributes(NewAttrs<wbr>.getFnAttributes());<br>
-    ReturnAttrs = NewAttrs.getRetAttributes();<br>
+    Invoke->setAttributes(Attribut<wbr>eList::get(Invoke->getContext(<wbr>),<br>
+                                             AttributeList::FunctionIndex,<br>
+                                             NewAttrs.getFnAttributes()));<br>
<br>
     Token = Invoke;<br>
<br>
@@ -1482,7 +1483,9 @@ makeStatepointExplicitImpl(con<wbr>st CallSit<br>
       StringRef Name =<br>
           CS.getInstruction()->hasName(<wbr>) ? CS.getInstruction()->getName() : "";<br>
       CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(), Name);<br>
-      GCResult->setAttributes(CS.get<wbr>Attributes().getRetAttributes(<wbr>));<br>
+      GCResult->setAttributes(<br>
+          AttributeList::get(GCResult->g<wbr>etContext(), AttributeList::ReturnIndex,<br>
+                             CS.getAttributes().getRetAttr<wbr>ibutes()));<br>
<br>
       // We cannot RAUW or delete CS.getInstruction() because it could be in the<br>
       // live set of some other safepoint, in which case that safepoint's<br>
<br>
Modified: llvm/trunk/lib/Transforms/Util<wbr>s/CloneFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/CloneFunction.cpp?rev=<wbr>299899&r1=299898&r2=299899&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Util<wbr>s/CloneFunction.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Util<wbr>s/CloneFunction.cpp Mon Apr 10 18:31:05 2017<br>
@@ -103,21 +103,25 @@ void llvm::CloneFunctionInto(Functi<wbr>on *N<br>
                  ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,<br>
                  TypeMapper, Materializer));<br>
<br>
+  SmallVector<std::pair<unsigned<wbr>, AttributeSetNode*>, 4> AttrVec;<br>
   AttributeList OldAttrs = OldFunc->getAttributes();<br>
+<br>
+  // Copy the return attributes.<br>
+  if (auto *RetAttrs = OldAttrs.getRetAttributes())<br>
+    AttrVec.emplace_back(Attribute<wbr>List::ReturnIndex, RetAttrs);<br>
+<br>
   // Clone any argument attributes that are present in the VMap.<br>
   for (const Argument &OldArg : OldFunc->args())<br>
     if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldAr<wbr>g])) {<br>
-      AttributeList attrs = OldAttrs.getParamAttributes(Ol<wbr>dArg.getArgNo() + 1);<br>
-      if (attrs.getNumSlots() > 0)<br>
-        NewArg->addAttr(attrs);<br>
+      if (auto *ParmAttrs = OldAttrs.getParamAttributes(Ol<wbr>dArg.getArgNo() + 1))<br>
+        AttrVec.emplace_back(NewArg->g<wbr>etArgNo() + 1, ParmAttrs);<br>
     }<br>
<br>
-  NewFunc->setAttributes(<br>
-      NewFunc->getAttributes()<br>
-          .addAttributes(NewFunc->getCon<wbr>text(), AttributeList::ReturnIndex,<br>
-                         OldAttrs.getRetAttributes())<br>
-          .addAttributes(NewFunc->getCon<wbr>text(), AttributeList::FunctionIndex,<br>
-                         OldAttrs.getFnAttributes()));<br>
+  // Copy any function attributes.<br>
+  if (auto *FnAttrs = OldAttrs.getFnAttributes())<br>
+    AttrVec.emplace_back(Attribute<wbr>List::FunctionIndex, FnAttrs);<br>
+<br>
+  NewFunc->setAttributes(Attribu<wbr>teList::get(NewFunc->getContex<wbr>t(), AttrVec));<br>
<br>
   SmallVector<std::pair<unsigne<wbr>d, MDNode *>, 1> MDs;<br>
   OldFunc->getAllMetadata(MDs);<br>
<br>
Modified: llvm/trunk/lib/Transforms/Util<wbr>s/CodeExtractor.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=299899&r1=299898&r2=299899&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Transform<wbr>s/Utils/CodeExtractor.cpp?rev=<wbr>299899&r1=299898&r2=299899&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- llvm/trunk/lib/Transforms/Util<wbr>s/CodeExtractor.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Util<wbr>s/CodeExtractor.cpp Mon Apr 10 18:31:05 2017<br>
@@ -362,8 +362,7 @@ Function *CodeExtractor::constructFunct<wbr>i<br>
   //  "target-features" attribute allowing it to be lowered.<br>
   // FIXME: This should be changed to check to see if a specific<br>
   //           attribute can not be inherited.<br>
-  AttributeList OldFnAttrs = oldFunction->getAttributes().g<wbr>etFnAttributes();<br>
-  AttrBuilder AB(OldFnAttrs, AttributeList::FunctionIndex);<br>
+  AttrBuilder AB(oldFunction->getAttributes(<wbr>).getFnAttributes());<br>
   for (const auto &Attr : AB.td_attrs())<br>
     newFunction->addFnAttr(Attr.f<wbr>irst, Attr.second);<br>
<br>
<br>
<br>
______________________________<wbr>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div></div></div></div>
</blockquote></div><br></div>