[llvm] r299878 - Revert "[IR] Make AttributeSetNode public, avoid temporary AttributeList copies"

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 10 13:34:20 PDT 2017


Author: rnk
Date: Mon Apr 10 15:34:19 2017
New Revision: 299878

URL: http://llvm.org/viewvc/llvm-project?rev=299878&view=rev
Log:
Revert "[IR] Make AttributeSetNode public, avoid temporary AttributeList copies"

This reverts r299875. A Linux bot came back with a test failure:
http://bb.pgr.jp/builders/test-clang-i686-linux-RA/builds/741/steps/test_clang/logs/Clang%20%3A%3A%20CodeGen__2006-05-19-SingleEltReturn.c

Added:
    llvm/trunk/lib/IR/AttributeSetNode.h
Removed:
    llvm/trunk/include/llvm/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

Removed: llvm/trunk/include/llvm/IR/AttributeSetNode.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/AttributeSetNode.h?rev=299877&view=auto
==============================================================================
--- llvm/trunk/include/llvm/IR/AttributeSetNode.h (original)
+++ llvm/trunk/include/llvm/IR/AttributeSetNode.h (removed)
@@ -1,109 +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 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=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Attributes.h (original)
+++ llvm/trunk/include/llvm/IR/Attributes.h Mon Apr 10 15:34:19 2017
@@ -221,26 +221,19 @@ private:
   /// the empty attributes list.
   AttributeListImpl *pImpl = nullptr;
 
-public:
+  /// \brief The attributes for the specified index are returned.
+  AttributeSetNode *getAttributes(unsigned Index) const;
+
   /// \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:
@@ -279,12 +272,6 @@ 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.
@@ -309,11 +296,6 @@ 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,
@@ -339,16 +321,13 @@ public:
   LLVMContext &getContext() const;
 
   /// \brief The attributes for the specified index are returned.
-  AttributeSetNode *getAttributes(unsigned Index) const;
-
-  /// \brief The attributes for the specified index are returned.
-  AttributeSetNode *getParamAttributes(unsigned Index) const;
+  AttributeList getParamAttributes(unsigned Index) const;
 
   /// \brief The attributes for the ret value are returned.
-  AttributeSetNode *getRetAttributes() const;
+  AttributeList getRetAttributes() const;
 
   /// \brief The function attributes are returned.
-  AttributeSetNode *getFnAttributes() const;
+  AttributeList getFnAttributes() const;
 
   /// \brief Return true if the attribute exists at the given index.
   bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const;
@@ -483,7 +462,6 @@ public:
     addAttribute(A);
   }
   AttrBuilder(AttributeList AS, unsigned Idx);
-  AttrBuilder(AttributeSetNode *AS);
 
   void clear();
 
@@ -500,7 +478,7 @@ public:
   AttrBuilder &removeAttribute(Attribute::AttrKind Val);
 
   /// \brief Remove the attributes from the builder.
-  AttrBuilder &removeAttributes(AttributeList A, uint64_t WithoutIndex);
+  AttrBuilder &removeAttributes(AttributeList A, uint64_t Index);
 
   /// \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=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Apr 10 15:34:19 2017
@@ -19,7 +19,6 @@
 #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"
@@ -132,8 +131,9 @@ bool LLParser::ValidateEndOfModule() {
 
     if (Function *Fn = dyn_cast<Function>(V)) {
       AttributeList AS = Fn->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes());
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
+      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
+                               AS.getFnAttributes());
 
       FnAttrs.merge(B);
 
@@ -150,8 +150,9 @@ bool LLParser::ValidateEndOfModule() {
       Fn->setAttributes(AS);
     } else if (CallInst *CI = dyn_cast<CallInst>(V)) {
       AttributeList AS = CI->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes());
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
+      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
+                               AS.getFnAttributes());
       FnAttrs.merge(B);
       AS = AS.addAttributes(
           Context, AttributeList::FunctionIndex,
@@ -159,8 +160,9 @@ bool LLParser::ValidateEndOfModule() {
       CI->setAttributes(AS);
     } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) {
       AttributeList AS = II->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes());
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
+      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
+                               AS.getFnAttributes());
       FnAttrs.merge(B);
       AS = AS.addAttributes(
           Context, AttributeList::FunctionIndex,
@@ -2093,6 +2095,7 @@ 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() &&
@@ -2127,7 +2130,7 @@ bool LLParser::ParseParameterList(SmallV
         return true;
     }
     ArgList.push_back(ParamInfo(
-        ArgLoc, V, AttributeSetNode::get(V->getContext(), ArgAttrs)));
+        ArgLoc, V, AttributeList::get(V->getContext(), AttrIndex++, ArgAttrs)));
   }
 
   if (IsMustTailCall && InVarArgsFunc)
@@ -2232,8 +2235,9 @@ bool LLParser::ParseArgumentList(SmallVe
     if (!FunctionType::isValidArgumentType(ArgTy))
       return Error(TypeLoc, "invalid type for function argument");
 
-    ArgList.emplace_back(TypeLoc, ArgTy,
-                         AttributeSetNode::get(ArgTy->getContext(), Attrs),
+    unsigned AttrIndex = 1;
+    ArgList.emplace_back(TypeLoc, ArgTy, AttributeList::get(ArgTy->getContext(),
+                                                            AttrIndex++, Attrs),
                          std::move(Name));
 
     while (EatIfPresent(lltok::comma)) {
@@ -2260,9 +2264,10 @@ bool LLParser::ParseArgumentList(SmallVe
       if (!ArgTy->isFirstClassType())
         return Error(TypeLoc, "invalid type for function argument");
 
-      ArgList.emplace_back(TypeLoc, ArgTy,
-                           AttributeSetNode::get(ArgTy->getContext(), Attrs),
-                           std::move(Name));
+      ArgList.emplace_back(
+          TypeLoc, ArgTy,
+          AttributeList::get(ArgTy->getContext(), AttrIndex++, Attrs),
+          std::move(Name));
     }
   }
 
@@ -2286,7 +2291,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)
+    if (ArgList[i].Attrs.hasAttributes(i + 1))
       return Error(ArgList[i].Loc,
                    "argument attributes invalid in function type");
   }
@@ -4735,16 +4740,23 @@ 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<AttributeSetNode *, 8> Attrs;
+  SmallVector<AttributeList, 8> Attrs;
 
-  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
+  if (RetAttrs.hasAttributes())
+    Attrs.push_back(AttributeList::get(RetType->getContext(),
+                                       AttributeList::ReturnIndex, RetAttrs));
 
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
     ParamTypeList.push_back(ArgList[i].Ty);
-    Attrs.push_back(ArgList[i].Attrs);
+    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(AttributeSetNode::get(Context, FuncAttrs));
+  if (FuncAttrs.hasAttributes())
+    Attrs.push_back(AttributeList::get(
+        RetType->getContext(), AttributeList::FunctionIndex, FuncAttrs));
 
   AttributeList PAL = AttributeList::get(Context, Attrs);
 
@@ -5356,8 +5368,10 @@ bool LLParser::ParseInvoke(Instruction *
     return true;
 
   // Set up the Attribute for the function.
-  SmallVector<AttributeSetNode *, 8> Attrs;
-  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
+  SmallVector<AttributeList, 8> Attrs;
+  if (RetAttrs.hasAttributes())
+    Attrs.push_back(AttributeList::get(RetType->getContext(),
+                                       AttributeList::ReturnIndex, RetAttrs));
 
   SmallVector<Value*, 8> Args;
 
@@ -5377,16 +5391,22 @@ bool LLParser::ParseInvoke(Instruction *
       return Error(ArgList[i].Loc, "argument is not of expected type '" +
                    getTypeString(ExpectedTy) + "'");
     Args.push_back(ArgList[i].V);
-    Attrs.push_back(ArgList[i].Attrs);
+    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
+      AttrBuilder B(ArgList[i].Attrs, i + 1);
+      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1, B));
+    }
   }
 
   if (I != E)
     return Error(CallLoc, "not enough parameters specified for call");
 
-  if (FnAttrs.hasAlignmentAttr())
-    return Error(CallLoc, "invoke instructions may not have an alignment");
+  if (FnAttrs.hasAttributes()) {
+    if (FnAttrs.hasAlignmentAttr())
+      return Error(CallLoc, "invoke instructions may not have an alignment");
 
-  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
+    Attrs.push_back(AttributeList::get(RetType->getContext(),
+                                       AttributeList::FunctionIndex, FnAttrs));
+  }
 
   // Finish off the Attribute and check them
   AttributeList PAL = AttributeList::get(Context, Attrs);
@@ -5950,8 +5970,10 @@ bool LLParser::ParseCall(Instruction *&I
     return true;
 
   // Set up the Attribute for the function.
-  SmallVector<AttributeSetNode *, 8> Attrs;
-  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
+  SmallVector<AttributeList, 8> Attrs;
+  if (RetAttrs.hasAttributes())
+    Attrs.push_back(AttributeList::get(RetType->getContext(),
+                                       AttributeList::ReturnIndex, RetAttrs));
 
   SmallVector<Value*, 8> Args;
 
@@ -5971,16 +5993,22 @@ bool LLParser::ParseCall(Instruction *&I
       return Error(ArgList[i].Loc, "argument is not of expected type '" +
                    getTypeString(ExpectedTy) + "'");
     Args.push_back(ArgList[i].V);
-    Attrs.push_back(ArgList[i].Attrs);
+    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
+      AttrBuilder B(ArgList[i].Attrs, i + 1);
+      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1, B));
+    }
   }
 
   if (I != E)
     return Error(CallLoc, "not enough parameters specified for call");
 
-  if (FnAttrs.hasAlignmentAttr())
-    return Error(CallLoc, "call instructions may not have an alignment");
+  if (FnAttrs.hasAttributes()) {
+    if (FnAttrs.hasAlignmentAttr())
+      return Error(CallLoc, "call instructions may not have an alignment");
 
-  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
+    Attrs.push_back(AttributeList::get(RetType->getContext(),
+                                       AttributeList::FunctionIndex, 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=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Mon Apr 10 15:34:19 2017
@@ -395,8 +395,8 @@ namespace llvm {
     struct ParamInfo {
       LocTy Loc;
       Value *V;
-      AttributeSetNode *Attrs;
-      ParamInfo(LocTy loc, Value *v, AttributeSetNode *attrs)
+      AttributeList Attrs;
+      ParamInfo(LocTy loc, Value *v, AttributeList attrs)
           : Loc(loc), V(v), Attrs(attrs) {}
     };
     bool ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
@@ -448,9 +448,9 @@ namespace llvm {
     struct ArgInfo {
       LocTy Loc;
       Type *Ty;
-      AttributeSetNode *Attrs;
+      AttributeList Attrs;
       std::string Name;
-      ArgInfo(LocTy L, Type *ty, AttributeSetNode *Attr, const std::string &N)
+      ArgInfo(LocTy L, Type *ty, AttributeList Attr, const std::string &N)
           : Loc(L), Ty(ty), Attrs(Attr), Name(N) {}
     };
     bool ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList, bool &isVarArg);

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Mon Apr 10 15:34:19 2017
@@ -21,8 +21,6 @@
 #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"
@@ -606,7 +604,7 @@ private:
   unsigned mdnNext;
 
   /// asMap - The slot map for attribute sets.
-  DenseMap<AttributeSetNode *, unsigned> asMap;
+  DenseMap<AttributeList, unsigned> asMap;
   unsigned asNext;
 public:
   /// Construct from a module.
@@ -629,7 +627,7 @@ public:
   int getLocalSlot(const Value *V);
   int getGlobalSlot(const GlobalValue *V);
   int getMetadataSlot(const MDNode *N);
-  int getAttributeGroupSlot(AttributeSetNode *AS);
+  int getAttributeGroupSlot(AttributeList 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.
@@ -652,8 +650,8 @@ public:
   unsigned mdn_size() const { return mdnMap.size(); }
   bool mdn_empty() const { return mdnMap.empty(); }
 
-  /// AttributeSetNode map iterators.
-  typedef DenseMap<AttributeSetNode *, unsigned>::iterator as_iterator;
+  /// AttributeList map iterators.
+  typedef DenseMap<AttributeList, 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(); }
@@ -673,8 +671,8 @@ private:
   /// CreateFunctionSlot - Insert the specified Value* into the slot table.
   void CreateFunctionSlot(const Value *V);
 
-  /// \brief Insert the specified AttributeSetNode into the slot table.
-  void CreateAttributeSetSlot(AttributeSetNode *AS);
+  /// \brief Insert the specified AttributeList into the slot table.
+  void CreateAttributeSetSlot(AttributeList AS);
 
   /// Add all of the module level global variables (and their initializers)
   /// and function declarations, but not the contents of those functions.
@@ -833,8 +831,8 @@ void SlotTracker::processModule() {
 
     // Add all the function attributes to the table.
     // FIXME: Add attributes of other objects?
-    AttributeSetNode *FnAttrs = F.getAttributes().getFnAttributes();
-    if (FnAttrs)
+    AttributeList FnAttrs = F.getAttributes().getFnAttributes();
+    if (FnAttrs.hasAttributes(AttributeList::FunctionIndex))
       CreateAttributeSetSlot(FnAttrs);
   }
 
@@ -871,13 +869,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.
-        AttributeSetNode *Attrs = CI->getAttributes().getFnAttributes();
-        if (Attrs)
+        AttributeList Attrs = CI->getAttributes().getFnAttributes();
+        if (Attrs.hasAttributes(AttributeList::FunctionIndex))
           CreateAttributeSetSlot(Attrs);
       } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
         // Add all the call attributes to the table.
-        AttributeSetNode *Attrs = II->getAttributes().getFnAttributes();
-        if (Attrs)
+        AttributeList Attrs = II->getAttributes().getFnAttributes();
+        if (Attrs.hasAttributes(AttributeList::FunctionIndex))
           CreateAttributeSetSlot(Attrs);
       }
     }
@@ -963,11 +961,11 @@ int SlotTracker::getLocalSlot(const Valu
   return FI == fMap.end() ? -1 : (int)FI->second;
 }
 
-int SlotTracker::getAttributeGroupSlot(AttributeSetNode *AS) {
+int SlotTracker::getAttributeGroupSlot(AttributeList AS) {
   // Check for uninitialized state and do lazy initialization.
   initialize();
 
-  // Find the AttributeSetNode in the module map.
+  // Find the AttributeList in the module map.
   as_iterator AI = asMap.find(AS);
   return AI == asMap.end() ? -1 : (int)AI->second;
 }
@@ -1017,8 +1015,9 @@ void SlotTracker::CreateMetadataSlot(con
       CreateMetadataSlot(Op);
 }
 
-void SlotTracker::CreateAttributeSetSlot(AttributeSetNode *AS) {
-  assert(AS && "Doesn't need a slot!");
+void SlotTracker::CreateAttributeSetSlot(AttributeList AS) {
+  assert(AS.hasAttributes(AttributeList::FunctionIndex) &&
+         "Doesn't need a slot!");
 
   as_iterator I = asMap.find(AS);
   if (I != asMap.end())
@@ -2607,10 +2606,17 @@ void AssemblyWriter::printFunction(const
 
   const AttributeList &Attrs = F->getAttributes();
   if (Attrs.hasAttributes(AttributeList::FunctionIndex)) {
-    AttributeSetNode *AS = Attrs.getFnAttributes();
+    AttributeList AS = Attrs.getFnAttributes();
     std::string AttrStr;
 
-    for (const Attribute &Attr : *AS) {
+    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;
       if (!Attr.isStringAttribute()) {
         if (!AttrStr.empty()) AttrStr += ' ';
         AttrStr += Attr.getAsString();
@@ -3244,7 +3250,7 @@ void AssemblyWriter::printMDNodeBody(con
 }
 
 void AssemblyWriter::writeAllAttributeGroups() {
-  std::vector<std::pair<AttributeSetNode *, unsigned>> asVec;
+  std::vector<std::pair<AttributeList, unsigned>> asVec;
   asVec.resize(Machine.as_size());
 
   for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end();
@@ -3253,7 +3259,7 @@ void AssemblyWriter::writeAllAttributeGr
 
   for (const auto &I : asVec)
     Out << "attributes #" << I.second << " = { "
-        << I.first->getAsString(true) << " }\n";
+        << I.first.getAsString(AttributeList::FunctionIndex, true) << " }\n";
 }
 
 void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {

Modified: llvm/trunk/lib/IR/AttributeImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeImpl.h?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AttributeImpl.h (original)
+++ llvm/trunk/lib/IR/AttributeImpl.h Mon Apr 10 15:34:19 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>

Added: llvm/trunk/lib/IR/AttributeSetNode.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AttributeSetNode.h?rev=299878&view=auto
==============================================================================
--- llvm/trunk/lib/IR/AttributeSetNode.h (added)
+++ llvm/trunk/lib/IR/AttributeSetNode.h Mon Apr 10 15:34:19 2017
@@ -0,0 +1,107 @@
+//===-- AttributeSetNode.h - AttributeList Internal Node ---------*- C++
+//-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the node class used internally by AttributeList.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_ATTRIBUTESETNODE_H
+#define LLVM_IR_ATTRIBUTESETNODE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/Support/TrailingObjects.h"
+#include <algorithm>
+#include <climits>
+#include <cstdint>
+#include <string>
+#include <utility>
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+/// \class
+/// \brief This class represents a group of attributes that apply to one
+/// element: function, return type, or parameter.
+class AttributeSetNode final
+    : public FoldingSetNode,
+      private TrailingObjects<AttributeSetNode, Attribute> {
+  friend TrailingObjects;
+
+  unsigned NumAttrs; ///< Number of attributes in this node.
+  /// Bitset with a bit for each available attribute Attribute::AttrKind.
+  uint64_t AvailableAttrs;
+
+  AttributeSetNode(ArrayRef<Attribute> Attrs)
+    : NumAttrs(Attrs.size()), AvailableAttrs(0) {
+    static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) * CHAR_BIT,
+                  "Too many attributes for AvailableAttrs");
+    // There's memory after the node where we can store the entries in.
+    std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>());
+
+    for (Attribute I : *this) {
+      if (!I.isStringAttribute()) {
+        AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
+      }
+    }
+  }
+
+public:
+  // AttributesSetNode is uniqued, these should not be available.
+  AttributeSetNode(const AttributeSetNode &) = delete;
+  AttributeSetNode &operator=(const AttributeSetNode &) = delete;
+
+  void operator delete(void *p) { ::operator delete(p); }
+
+  static AttributeSetNode *get(LLVMContext &C, ArrayRef<Attribute> Attrs);
+
+  static AttributeSetNode *get(AttributeList AS, unsigned Index) {
+    return AS.getAttributes(Index);
+  }
+
+  /// \brief Return the number of attributes this AttributeList contains.
+  unsigned getNumAttributes() const { return NumAttrs; }
+
+  bool hasAttribute(Attribute::AttrKind Kind) const {
+    return AvailableAttrs & ((uint64_t)1) << Kind;
+  }
+  bool hasAttribute(StringRef Kind) const;
+  bool hasAttributes() const { return NumAttrs != 0; }
+
+  Attribute getAttribute(Attribute::AttrKind Kind) const;
+  Attribute getAttribute(StringRef Kind) const;
+
+  unsigned getAlignment() const;
+  unsigned getStackAlignment() const;
+  uint64_t getDereferenceableBytes() const;
+  uint64_t getDereferenceableOrNullBytes() const;
+  std::pair<unsigned, Optional<unsigned>> getAllocSizeArgs() const;
+  std::string getAsString(bool InAttrGrp) const;
+
+  typedef const Attribute *iterator;
+  iterator begin() const { return getTrailingObjects<Attribute>(); }
+  iterator end() const { return begin() + NumAttrs; }
+
+  void Profile(FoldingSetNodeID &ID) const {
+    Profile(ID, makeArrayRef(begin(), end()));
+  }
+  static void Profile(FoldingSetNodeID &ID, ArrayRef<Attribute> AttrList) {
+    for (const auto &Attr : AttrList)
+      Attr.Profile(ID);
+  }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_IR_ATTRIBUTESETNODE_H

Modified: llvm/trunk/lib/IR/Attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Attributes.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Attributes.cpp (original)
+++ llvm/trunk/lib/IR/Attributes.cpp Mon Apr 10 15:34:19 2017
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "AttributeImpl.h"
+#include "AttributeSetNode.h"
 #include "LLVMContextImpl.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -23,7 +24,6 @@
 #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,48 +527,6 @@ 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))
@@ -654,19 +612,6 @@ 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);
@@ -735,32 +680,50 @@ 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();
-  AttributeSetNode *ASN = AttributeSetNode::get(C, B);
-  std::pair<unsigned, AttributeSetNode *> Arr[1] = {{Index, ASN}};
-  return getImpl(C, Arr);
+
+  // 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);
 }
 
 AttributeList AttributeList::get(LLVMContext &C, unsigned Index,
@@ -828,31 +791,31 @@ AttributeList AttributeList::addAttribut
 AttributeList AttributeList::addAttribute(LLVMContext &C,
                                           ArrayRef<unsigned> Indices,
                                           Attribute A) const {
-  assert(std::is_sorted(Indices.begin(), Indices.end()));
-
   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)));
+  auto IdxI = Indices.begin(), IdxE = Indices.end();
+  SmallVector<AttributeList, 4> AttrSet;
+
+  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));
       ++I;
+      ++IdxI;
     }
-    B.addAttribute(A);
-    AttrVec.emplace_back(Index, AttributeSetNode::get(C, B));
   }
 
-  // Add remaining attributes.
-  for (; I < E; ++I)
-    AttrVec.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
+  while (I != E)
+    AttrSet.emplace_back(getSlotAttributes(I++));
 
-  return get(C, AttrVec);
+  while (IdxI != IdxE)
+    AttrSet.emplace_back(AttributeList::get(C, std::make_pair(*IdxI++, A)));
+
+  return get(C, AttrSet);
 }
 
 AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
@@ -860,56 +823,49 @@ 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 = AS->getAlignment();
+  unsigned NewAlign = Attrs.getParamAlignment(Index);
   assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
          "Attempt to change alignment!");
 #endif
 
-  SmallVector<std::pair<unsigned, AttributeSetNode *>, 4> AttrSet;
+  // Add the attribute slots before the one we're trying to add.
+  SmallVector<AttributeList, 4> AttrSet;
   uint64_t NumAttrs = pImpl->getNumSlots();
-  unsigned I;
-
-  // Add all the attribute slots before the one we need to merge.
-  for (I = 0; I < NumAttrs; ++I) {
-    if (getSlotIndex(I) >= Index)
+  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;
-    AttrSet.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
+    }
+    LastIndex = I + 1;
+    AttrSet.push_back(getSlotAttributes(I));
   }
 
-  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);
-  }
+  // Now add the attribute into the correct slot. There may already be an
+  // AttributeList there.
+  AttrBuilder B(AS, Index);
 
-  // Add the remaining entries.
-  for (; I < NumAttrs; ++I)
-    AttrSet.emplace_back(getSlotIndex(I), pImpl->getSlotNode(I));
+  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);
+      break;
+    }
 
-  return get(C, AttrSet);
-}
+  AttrSet.push_back(AttributeList::get(C, Index, B));
 
-AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index,
-                                           const AttrBuilder &B) const {
-  return get(C, Index, AttributeSetNode::get(C, B));
+  // Add the remaining attribute slots.
+  for (unsigned I = LastIndex, E = NumAttrs; I < E; ++I)
+    AttrSet.push_back(getSlotAttributes(I));
+
+  return get(C, AttrSet);
 }
 
 AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index,
@@ -1005,20 +961,6 @@ 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 {
@@ -1050,16 +992,32 @@ AttributeList::addAllocSizeAttr(LLVMCont
 
 LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); }
 
-AttributeSetNode *AttributeList::getParamAttributes(unsigned Index) const {
-  return getAttributes(Index);
-}
-
-AttributeSetNode *AttributeList::getRetAttributes() const {
-  return getAttributes(ReturnIndex);
-}
-
-AttributeSetNode *AttributeList::getFnAttributes() const {
-  return getAttributes(FunctionIndex);
+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();
 }
 
 bool AttributeList::hasAttribute(unsigned Index,
@@ -1223,13 +1181,6 @@ 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=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Core.cpp (original)
+++ llvm/trunk/lib/IR/Core.cpp Mon Apr 10 15:34:19 2017
@@ -16,7 +16,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/IR/Attributes.h"
-#include "llvm/IR/AttributeSetNode.h"
+#include "AttributeSetNode.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DerivedTypes.h"

Modified: llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp Mon Apr 10 15:34:19 2017
@@ -42,7 +42,6 @@
 #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"
@@ -103,11 +102,13 @@ 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<AttributeSetNode *, 8> AttributesVec;
+  SmallVector<AttributeList, 8> AttributesVec;
   const AttributeList &PAL = F->getAttributes();
 
   // Add any return attributes.
-  AttributesVec.push_back(PAL.getRetAttributes());
+  if (PAL.hasAttributes(AttributeList::ReturnIndex))
+    AttributesVec.push_back(
+        AttributeList::get(F->getContext(), PAL.getRetAttributes()));
 
   // First, determine the new argument list
   unsigned ArgIndex = 1;
@@ -118,12 +119,16 @@ 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());
-      AttributesVec.push_back(PAL.getParamAttributes(ArgIndex));
+      AttributeList attrs = PAL.getParamAttributes(ArgIndex);
+      if (attrs.hasAttributes(ArgIndex)) {
+        AttrBuilder B(attrs, ArgIndex);
+        AttributesVec.push_back(
+            AttributeList::get(F->getContext(), Params.size(), B));
+      }
     } else if (I->use_empty()) {
       // Dead argument (which are always marked as promotable)
       ++NumArgumentsDead;
@@ -168,7 +173,6 @@ doPromotion(Function *F, SmallPtrSetImpl
         Params.push_back(GetElementPtrInst::getIndexedType(
             cast<PointerType>(I->getType()->getScalarType())->getElementType(),
             ArgIndex.second));
-        AttributesVec.push_back(nullptr);
         assert(Params.back());
       }
 
@@ -180,7 +184,9 @@ doPromotion(Function *F, SmallPtrSetImpl
   }
 
   // Add any function attributes.
-  AttributesVec.push_back(PAL.getFnAttributes());
+  if (PAL.hasAttributes(AttributeList::FunctionIndex))
+    AttributesVec.push_back(
+        AttributeList::get(FTy->getContext(), PAL.getFnAttributes()));
 
   Type *RetTy = FTy->getReturnType();
 
@@ -217,7 +223,9 @@ doPromotion(Function *F, SmallPtrSetImpl
     const AttributeList &CallPAL = CS.getAttributes();
 
     // Add any return attributes.
-    AttributesVec.push_back(CallPAL.getRetAttributes());
+    if (CallPAL.hasAttributes(AttributeList::ReturnIndex))
+      AttributesVec.push_back(
+          AttributeList::get(F->getContext(), CallPAL.getRetAttributes()));
 
     // Loop over the operands, inserting GEP and loads in the caller as
     // appropriate.
@@ -227,7 +235,12 @@ doPromotion(Function *F, SmallPtrSetImpl
          ++I, ++AI, ++ArgIndex)
       if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I)) {
         Args.push_back(*AI); // Unmodified argument
-        AttributesVec.push_back(CallPAL.getAttributes(ArgIndex));
+
+        if (CallPAL.hasAttributes(ArgIndex)) {
+          AttrBuilder B(CallPAL, ArgIndex);
+          AttributesVec.push_back(
+              AttributeList::get(F->getContext(), Args.size(), B));
+        }
       } else if (ByValArgsToTransform.count(&*I)) {
         // Emit a GEP and load for each element of the struct.
         Type *AgTy = cast<PointerType>(I->getType())->getElementType();
@@ -240,7 +253,6 @@ 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.
@@ -283,18 +295,23 @@ 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);
-      AttributesVec.push_back(CallPAL.getAttributes(ArgIndex));
+      if (CallPAL.hasAttributes(ArgIndex)) {
+        AttrBuilder B(CallPAL, ArgIndex);
+        AttributesVec.push_back(
+            AttributeList::get(F->getContext(), Args.size(), B));
+      }
     }
 
     // Add any function attributes.
-    AttributesVec.push_back(CallPAL.getFnAttributes());
+    if (CallPAL.hasAttributes(AttributeList::FunctionIndex))
+      AttributesVec.push_back(
+          AttributeList::get(Call->getContext(), CallPAL.getFnAttributes()));
 
     SmallVector<OperandBundleDef, 1> OpBundles;
     CS.getOperandBundlesAsDefs(OpBundles);

Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Mon Apr 10 15:34:19 2017
@@ -21,7 +21,6 @@
 #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"
@@ -173,9 +172,8 @@ 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(),
-                                                   AttributeList::FunctionIndex,
-                                                   PAL.getFnAttributes()));
+        AttributesVec.push_back(
+            AttributeList::get(Fn.getContext(), PAL.getFnAttributes()));
       PAL = AttributeList::get(Fn.getContext(), AttributesVec);
     }
 
@@ -686,13 +684,9 @@ bool DeadArgumentEliminationPass::Remove
   bool HasLiveReturnedArg = false;
 
   // Set up to build a new list of parameter attributes.
-  SmallVector<AttributeSetNode *, 8> AttributesVec;
+  SmallVector<AttributeList, 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
@@ -705,8 +699,16 @@ bool DeadArgumentEliminationPass::Remove
     if (LiveValues.erase(Arg)) {
       Params.push_back(I->getType());
       ArgAlive[i] = true;
-      AttributesVec.push_back(PAL.getParamAttributes(i + 1));
-      HasLiveReturnedArg |= PAL.hasAttribute(i + 1, Attribute::Returned);
+
+      // 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));
+      }
     } else {
       ++NumArgumentsEliminated;
       DEBUG(dbgs() << "DeadArgumentEliminationPass - Removing argument " << i
@@ -780,25 +782,29 @@ bool DeadArgumentEliminationPass::Remove
   assert(NRetTy && "No new return type found?");
 
   // The existing function return attributes.
-  AttrBuilder RAttrs(PAL.getRetAttributes());
+  AttributeList 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.remove(AttributeFuncs::typeIncompatible(NRetTy));
+    RAttrs = RAttrs.removeAttributes(NRetTy->getContext(),
+                                     AttributeList::ReturnIndex,
+                                     AttributeFuncs::typeIncompatible(NRetTy));
   else
-    assert(!RAttrs.overlaps(AttributeFuncs::typeIncompatible(NRetTy)) &&
+    assert(!AttrBuilder(RAttrs, AttributeList::ReturnIndex)
+                .overlaps(AttributeFuncs::typeIncompatible(NRetTy)) &&
            "Return attributes no longer compatible?");
 
-  AttributesVec[0] = AttributeSetNode::get(F->getContext(), RAttrs);
+  if (RAttrs.hasAttributes(AttributeList::ReturnIndex))
+    AttributesVec.push_back(AttributeList::get(NRetTy->getContext(), RAttrs));
 
-  // Transfer the function attributes, if any.
-  AttributesVec.push_back(PAL.getFnAttributes());
+  if (PAL.hasAttributes(AttributeList::FunctionIndex))
+    AttributesVec.push_back(
+        AttributeList::get(F->getContext(), 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.
@@ -829,11 +835,15 @@ bool DeadArgumentEliminationPass::Remove
     AttributesVec.clear();
     const AttributeList &CallPAL = CS.getAttributes();
 
-    // 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));
+    // 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));
 
     // Declare these outside of the loops, so we can reuse them for the second
     // loop, which loops the varargs.
@@ -845,30 +855,33 @@ bool DeadArgumentEliminationPass::Remove
       if (ArgAlive[i]) {
         Args.push_back(*I);
         // Get original parameter attributes, but skip return attributes.
-        AttributeSetNode *Attrs = CallPAL.getParamAttributes(i + 1);
-        if (NRetTy != RetTy && Attrs &&
-            Attrs->hasAttribute(Attribute::Returned)) {
+        if (CallPAL.hasAttributes(i + 1)) {
+          AttrBuilder B(CallPAL, i + 1);
           // 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
-          AttributesVec.push_back(AttributeSetNode::get(
-              F->getContext(),
-              AttrBuilder(Attrs).removeAttribute(Attribute::Returned)));
-        } else {
-          // Otherwise, use the original attributes.
-          AttributesVec.push_back(Attrs);
+          // 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));
         }
       }
 
     // 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);
-      AttributesVec.push_back(CallPAL.getParamAttributes(i + 1));
+      if (CallPAL.hasAttributes(i + 1)) {
+        AttrBuilder B(CallPAL, i + 1);
+        AttributesVec.push_back(
+            AttributeList::get(F->getContext(), Args.size(), B));
+      }
     }
 
-    AttributesVec.push_back(CallPAL.getFnAttributes());
+    if (CallPAL.hasAttributes(AttributeList::FunctionIndex))
+      AttributesVec.push_back(
+          AttributeList::get(Call->getContext(), CallPAL.getFnAttributes()));
 
     // Reconstruct the AttributesList based on the vector we constructed.
     AttributeList NewCallPAL =

Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Mon Apr 10 15:34:19 2017
@@ -439,7 +439,8 @@ void MergeFunctions::replaceDirectCaller
           Context, AttributeList::ReturnIndex, NewFuncAttrs.getRetAttributes());
 
       for (unsigned argIdx = 0; argIdx < CS.arg_size(); argIdx++) {
-        if (AttributeSetNode *Attrs = NewFuncAttrs.getParamAttributes(argIdx))
+        AttributeList Attrs = NewFuncAttrs.getParamAttributes(argIdx);
+        if (Attrs.getNumSlots())
           CallSiteAttrs = CallSiteAttrs.addAttributes(Context, argIdx, Attrs);
       }
 

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Mon Apr 10 15:34:19 2017
@@ -23,7 +23,6 @@
 #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"
@@ -3993,7 +3992,7 @@ bool InstCombiner::transformConstExprCas
     if (!CastInst::isBitOrNoopPointerCastable(ActTy, ParamTy, DL))
       return false;   // Cannot transform this parameter value.
 
-    if (AttrBuilder(CallerPAL.getParamAttributes(i + 1)).
+    if (AttrBuilder(CallerPAL.getParamAttributes(i + 1), i + 1).
           overlaps(AttributeFuncs::typeIncompatible(ParamTy)))
       return false;   // Attribute not compatible with transformed value.
 
@@ -4002,7 +4001,9 @@ 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.hasAttribute(i + 1, Attribute::ByVal)) {
+    if (ParamTy != ActTy &&
+        CallerPAL.getParamAttributes(i + 1).hasAttribute(i + 1,
+                                                         Attribute::ByVal)) {
       PointerType *ParamPTy = dyn_cast<PointerType>(ParamTy);
       if (!ParamPTy || !ParamPTy->getElementType()->isSized())
         return false;
@@ -4083,7 +4084,7 @@ bool InstCombiner::transformConstExprCas
     }
 
     // Add any parameter attributes.
-    AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1));
+    AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1), i + 1);
     if (PAttrs.hasAttributes())
       attrVec.push_back(
           AttributeList::get(Caller->getContext(), i + 1, PAttrs));
@@ -4111,7 +4112,7 @@ bool InstCombiner::transformConstExprCas
         }
 
         // Add any parameter attributes.
-        AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1));
+        AttrBuilder PAttrs(CallerPAL.getParamAttributes(i + 1), i + 1);
         if (PAttrs.hasAttributes())
           attrVec.push_back(
               AttributeList::get(FT->getContext(), i + 1, PAttrs));
@@ -4119,11 +4120,9 @@ bool InstCombiner::transformConstExprCas
     }
   }
 
-  AttributeSetNode *FnAttrs = CallerPAL.getFnAttributes();
+  AttributeList FnAttrs = CallerPAL.getFnAttributes();
   if (CallerPAL.hasAttributes(AttributeList::FunctionIndex))
-    attrVec.push_back(AttributeList::get(Callee->getContext(),
-                                         AttributeList::FunctionIndex,
-                                         AttrBuilder(FnAttrs)));
+    attrVec.push_back(AttributeList::get(Callee->getContext(), FnAttrs));
 
   if (NewRetTy->isVoidTy())
     Caller->setName("");   // Void type should not have a name.
@@ -4201,7 +4200,7 @@ InstCombiner::transformCallThroughTrampo
   Value *Callee = CS.getCalledValue();
   PointerType *PTy = cast<PointerType>(Callee->getType());
   FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
-  AttributeList Attrs = CS.getAttributes();
+  const 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.
@@ -4214,11 +4213,11 @@ InstCombiner::transformCallThroughTrampo
   Function *NestF =cast<Function>(Tramp->getArgOperand(1)->stripPointerCasts());
   FunctionType *NestFTy = cast<FunctionType>(NestF->getValueType());
 
-  AttributeList NestAttrs = NestF->getAttributes();
+  const AttributeList &NestAttrs = NestF->getAttributes();
   if (!NestAttrs.isEmpty()) {
     unsigned NestIdx = 1;
     Type *NestTy = nullptr;
-    AttributeSetNode *NestAttr;
+    AttributeList NestAttr;
 
     // Look for a parameter marked with the 'nest' attribute.
     for (FunctionType::param_iterator I = NestFTy->param_begin(),
@@ -4233,15 +4232,18 @@ InstCombiner::transformCallThroughTrampo
     if (NestTy) {
       Instruction *Caller = CS.getInstruction();
       std::vector<Value*> NewArgs;
-      std::vector<AttributeSetNode *> NewAttrs;
       NewArgs.reserve(CS.arg_size() + 1);
-      NewAttrs.reserve(CS.arg_size() + 2);
+
+      SmallVector<AttributeList, 8> NewAttrs;
+      NewAttrs.reserve(Attrs.getNumSlots() + 1);
 
       // Insert the nest argument into the call argument list, which may
       // mean appending it.  Likewise for attributes.
 
       // Add any result attributes.
-      NewAttrs.push_back(Attrs.getRetAttributes());
+      if (Attrs.hasAttributes(AttributeList::ReturnIndex))
+        NewAttrs.push_back(
+            AttributeList::get(Caller->getContext(), Attrs.getRetAttributes()));
 
       {
         unsigned Idx = 1;
@@ -4253,7 +4255,8 @@ InstCombiner::transformCallThroughTrampo
             if (NestVal->getType() != NestTy)
               NestVal = Builder->CreateBitCast(NestVal, NestTy, "nest");
             NewArgs.push_back(NestVal);
-            NewAttrs.push_back(NestAttr);
+            NewAttrs.push_back(
+                AttributeList::get(Caller->getContext(), NestAttr));
           }
 
           if (I == E)
@@ -4261,7 +4264,12 @@ InstCombiner::transformCallThroughTrampo
 
           // Add the original argument and attributes.
           NewArgs.push_back(*I);
-          NewAttrs.push_back(Attrs.getParamAttributes(Idx));
+          AttributeList Attr = Attrs.getParamAttributes(Idx);
+          if (Attr.hasAttributes(Idx)) {
+            AttrBuilder B(Attr, Idx);
+            NewAttrs.push_back(AttributeList::get(Caller->getContext(),
+                                                  Idx + (Idx >= NestIdx), B));
+          }
 
           ++Idx;
           ++I;
@@ -4269,7 +4277,9 @@ InstCombiner::transformCallThroughTrampo
       }
 
       // Add any function attributes.
-      NewAttrs.push_back(Attrs.getFnAttributes());
+      if (Attrs.hasAttributes(AttributeList::FunctionIndex))
+        NewAttrs.push_back(
+            AttributeList::get(FTy->getContext(), Attrs.getFnAttributes()));
 
       // The trampoline may have been bitcast to a bogus type (FTy).
       // Handle this by synthesizing a new function type, equal to FTy
@@ -4309,7 +4319,8 @@ InstCombiner::transformCallThroughTrampo
         NestF->getType() == PointerType::getUnqual(NewFTy) ?
         NestF : ConstantExpr::getBitCast(NestF,
                                          PointerType::getUnqual(NewFTy));
-      AttributeList NewPAL = AttributeList::get(FTy->getContext(), NewAttrs);
+      const AttributeList &NewPAL =
+          AttributeList::get(FTy->getContext(), NewAttrs);
 
       SmallVector<OperandBundleDef, 1> OpBundles;
       CS.getOperandBundlesAsDefs(OpBundles);

Modified: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp Mon Apr 10 15:34:19 2017
@@ -1392,6 +1392,7 @@ 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(
@@ -1406,9 +1407,8 @@ makeStatepointExplicitImpl(const CallSit
     AttributeList NewAttrs = legalizeCallAttributes(ToReplace->getAttributes());
     // In case if we can handle this set of attributes - set up function attrs
     // directly on statepoint and return attrs later for gc_result intrinsic.
-    Call->setAttributes(AttributeList::get(Call->getContext(),
-                                           AttributeList::FunctionIndex,
-                                           NewAttrs.getFnAttributes()));
+    Call->setAttributes(NewAttrs.getFnAttributes());
+    ReturnAttrs = NewAttrs.getRetAttributes();
 
     Token = Call;
 
@@ -1435,9 +1435,8 @@ makeStatepointExplicitImpl(const CallSit
     AttributeList NewAttrs = legalizeCallAttributes(ToReplace->getAttributes());
     // In case if we can handle this set of attributes - set up function attrs
     // directly on statepoint and return attrs later for gc_result intrinsic.
-    Invoke->setAttributes(AttributeList::get(Invoke->getContext(),
-                                             AttributeList::FunctionIndex,
-                                             NewAttrs.getFnAttributes()));
+    Invoke->setAttributes(NewAttrs.getFnAttributes());
+    ReturnAttrs = NewAttrs.getRetAttributes();
 
     Token = Invoke;
 
@@ -1483,9 +1482,7 @@ makeStatepointExplicitImpl(const CallSit
       StringRef Name =
           CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : "";
       CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(), Name);
-      GCResult->setAttributes(
-          AttributeList::get(GCResult->getContext(), AttributeList::ReturnIndex,
-                             CS.getAttributes().getRetAttributes()));
+      GCResult->setAttributes(CS.getAttributes().getRetAttributes());
 
       // We cannot RAUW or delete CS.getInstruction() because it could be in the
       // live set of some other safepoint, in which case that safepoint's

Modified: llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp Mon Apr 10 15:34:19 2017
@@ -103,25 +103,21 @@ 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])) {
-      if (auto *ParmAttrs = OldAttrs.getParamAttributes(OldArg.getArgNo() + 1))
-        AttrVec.emplace_back(NewArg->getArgNo() + 1, ParmAttrs);
+      AttributeList attrs = OldAttrs.getParamAttributes(OldArg.getArgNo() + 1);
+      if (attrs.getNumSlots() > 0)
+        NewArg->addAttr(attrs);
     }
 
-  // Copy any function attributes.
-  if (auto *FnAttrs = OldAttrs.getFnAttributes())
-    AttrVec.emplace_back(AttributeList::FunctionIndex, FnAttrs);
-
-  NewFunc->setAttributes(AttributeList::get(NewFunc->getContext(), AttrVec));
+  NewFunc->setAttributes(
+      NewFunc->getAttributes()
+          .addAttributes(NewFunc->getContext(), AttributeList::ReturnIndex,
+                         OldAttrs.getRetAttributes())
+          .addAttributes(NewFunc->getContext(), AttributeList::FunctionIndex,
+                         OldAttrs.getFnAttributes()));
 
   SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
   OldFunc->getAllMetadata(MDs);

Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=299878&r1=299877&r2=299878&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Mon Apr 10 15:34:19 2017
@@ -362,7 +362,8 @@ 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.
-  AttrBuilder AB(oldFunction->getAttributes().getFnAttributes());
+  AttributeList OldFnAttrs = oldFunction->getAttributes().getFnAttributes();
+  AttrBuilder AB(OldFnAttrs, AttributeList::FunctionIndex);
   for (const auto &Attr : AB.td_attrs())
     newFunction->addFnAttr(Attr.first, Attr.second);
 




More information about the llvm-commits mailing list