[IR] Make AttributeSetNode public, avoid temporary AttributeList copies

Summary:
AttributeList::get(Fn|Ret|Param)Attributes no longer creates a temporary
AttributeList just to hide the AttributeSetNode type.

I've also added a factory method to create AttributeLists from a
parallel array of AttributeSetNodes. I think this simplifies
construction of AttributeLists when rewriting function prototypes.
Previously we would test if a particular index had attributes, and
conditionally add a temporary attribute list to a vector. Now the
attribute set vector is parallel to the argument vector already that
these passes already construct.

My long term vision is to wrap AttributeSetNode* inside an AttributeSet
type that holds the enum attributes, but that will come in a follow up
change.

I haven't done any performance measurements for this change because
profiling hasn't shown that any of the affected code is hot.

Reviewers: pete, chandlerc, sanjoy, hfinkel

Reviewed By: pete

Subscribers: jfb, llvm-commits

Differential Revision: https://reviews.llvm.org/D31198

llvm-svn: 299875
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index d8f6c1c..78de0d6 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/AsmParser/SlotMapping.h"
 #include "llvm/IR/Argument.h"
+#include "llvm/IR/AttributeSetNode.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CallingConv.h"
@@ -131,9 +132,8 @@
 
     if (Function *Fn = dyn_cast<Function>(V)) {
       AttributeList AS = Fn->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
-                               AS.getFnAttributes());
+      AttrBuilder FnAttrs(AS.getFnAttributes());
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
 
       FnAttrs.merge(B);
 
@@ -150,9 +150,8 @@
       Fn->setAttributes(AS);
     } else if (CallInst *CI = dyn_cast<CallInst>(V)) {
       AttributeList AS = CI->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
-                               AS.getFnAttributes());
+      AttrBuilder FnAttrs(AS.getFnAttributes());
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
       FnAttrs.merge(B);
       AS = AS.addAttributes(
           Context, AttributeList::FunctionIndex,
@@ -160,9 +159,8 @@
       CI->setAttributes(AS);
     } else if (InvokeInst *II = dyn_cast<InvokeInst>(V)) {
       AttributeList AS = II->getAttributes();
-      AttrBuilder FnAttrs(AS.getFnAttributes(), AttributeList::FunctionIndex);
-      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex,
-                               AS.getFnAttributes());
+      AttrBuilder FnAttrs(AS.getFnAttributes());
+      AS = AS.removeAttributes(Context, AttributeList::FunctionIndex);
       FnAttrs.merge(B);
       AS = AS.addAttributes(
           Context, AttributeList::FunctionIndex,
@@ -2095,7 +2093,6 @@
   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() &&
@@ -2130,7 +2127,7 @@
         return true;
     }
     ArgList.push_back(ParamInfo(
-        ArgLoc, V, AttributeList::get(V->getContext(), AttrIndex++, ArgAttrs)));
+        ArgLoc, V, AttributeSetNode::get(V->getContext(), ArgAttrs)));
   }
 
   if (IsMustTailCall && InVarArgsFunc)
@@ -2235,9 +2232,8 @@
     if (!FunctionType::isValidArgumentType(ArgTy))
       return Error(TypeLoc, "invalid type for function argument");
 
-    unsigned AttrIndex = 1;
-    ArgList.emplace_back(TypeLoc, ArgTy, AttributeList::get(ArgTy->getContext(),
-                                                            AttrIndex++, Attrs),
+    ArgList.emplace_back(TypeLoc, ArgTy,
+                         AttributeSetNode::get(ArgTy->getContext(), Attrs),
                          std::move(Name));
 
     while (EatIfPresent(lltok::comma)) {
@@ -2264,10 +2260,9 @@
       if (!ArgTy->isFirstClassType())
         return Error(TypeLoc, "invalid type for function argument");
 
-      ArgList.emplace_back(
-          TypeLoc, ArgTy,
-          AttributeList::get(ArgTy->getContext(), AttrIndex++, Attrs),
-          std::move(Name));
+      ArgList.emplace_back(TypeLoc, ArgTy,
+                           AttributeSetNode::get(ArgTy->getContext(), Attrs),
+                           std::move(Name));
     }
   }
 
@@ -2291,7 +2286,7 @@
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
     if (!ArgList[i].Name.empty())
       return Error(ArgList[i].Loc, "argument name invalid in function type");
-    if (ArgList[i].Attrs.hasAttributes(i + 1))
+    if (ArgList[i].Attrs)
       return Error(ArgList[i].Loc,
                    "argument attributes invalid in function type");
   }
@@ -4740,23 +4735,16 @@
   // Okay, if we got here, the function is syntactically valid.  Convert types
   // and do semantic checks.
   std::vector<Type*> ParamTypeList;
-  SmallVector<AttributeList, 8> Attrs;
+  SmallVector<AttributeSetNode *, 8> Attrs;
 
-  if (RetAttrs.hasAttributes())
-    Attrs.push_back(AttributeList::get(RetType->getContext(),
-                                       AttributeList::ReturnIndex, RetAttrs));
+  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
 
   for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
     ParamTypeList.push_back(ArgList[i].Ty);
-    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
-      AttrBuilder B(ArgList[i].Attrs, i + 1);
-      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1, B));
-    }
+    Attrs.push_back(ArgList[i].Attrs);
   }
 
-  if (FuncAttrs.hasAttributes())
-    Attrs.push_back(AttributeList::get(
-        RetType->getContext(), AttributeList::FunctionIndex, FuncAttrs));
+  Attrs.push_back(AttributeSetNode::get(Context, FuncAttrs));
 
   AttributeList PAL = AttributeList::get(Context, Attrs);
 
@@ -5368,10 +5356,8 @@
     return true;
 
   // Set up the Attribute for the function.
-  SmallVector<AttributeList, 8> Attrs;
-  if (RetAttrs.hasAttributes())
-    Attrs.push_back(AttributeList::get(RetType->getContext(),
-                                       AttributeList::ReturnIndex, RetAttrs));
+  SmallVector<AttributeSetNode *, 8> Attrs;
+  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
 
   SmallVector<Value*, 8> Args;
 
@@ -5391,22 +5377,16 @@
       return Error(ArgList[i].Loc, "argument is not of expected type '" +
                    getTypeString(ExpectedTy) + "'");
     Args.push_back(ArgList[i].V);
-    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
-      AttrBuilder B(ArgList[i].Attrs, i + 1);
-      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1, B));
-    }
+    Attrs.push_back(ArgList[i].Attrs);
   }
 
   if (I != E)
     return Error(CallLoc, "not enough parameters specified for call");
 
-  if (FnAttrs.hasAttributes()) {
-    if (FnAttrs.hasAlignmentAttr())
-      return Error(CallLoc, "invoke instructions may not have an alignment");
+  if (FnAttrs.hasAlignmentAttr())
+    return Error(CallLoc, "invoke instructions may not have an alignment");
 
-    Attrs.push_back(AttributeList::get(RetType->getContext(),
-                                       AttributeList::FunctionIndex, FnAttrs));
-  }
+  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
 
   // Finish off the Attribute and check them
   AttributeList PAL = AttributeList::get(Context, Attrs);
@@ -5970,10 +5950,8 @@
     return true;
 
   // Set up the Attribute for the function.
-  SmallVector<AttributeList, 8> Attrs;
-  if (RetAttrs.hasAttributes())
-    Attrs.push_back(AttributeList::get(RetType->getContext(),
-                                       AttributeList::ReturnIndex, RetAttrs));
+  SmallVector<AttributeSetNode *, 8> Attrs;
+  Attrs.push_back(AttributeSetNode::get(Context, RetAttrs));
 
   SmallVector<Value*, 8> Args;
 
@@ -5993,22 +5971,16 @@
       return Error(ArgList[i].Loc, "argument is not of expected type '" +
                    getTypeString(ExpectedTy) + "'");
     Args.push_back(ArgList[i].V);
-    if (ArgList[i].Attrs.hasAttributes(i + 1)) {
-      AttrBuilder B(ArgList[i].Attrs, i + 1);
-      Attrs.push_back(AttributeList::get(RetType->getContext(), i + 1, B));
-    }
+    Attrs.push_back(ArgList[i].Attrs);
   }
 
   if (I != E)
     return Error(CallLoc, "not enough parameters specified for call");
 
-  if (FnAttrs.hasAttributes()) {
-    if (FnAttrs.hasAlignmentAttr())
-      return Error(CallLoc, "call instructions may not have an alignment");
+  if (FnAttrs.hasAlignmentAttr())
+    return Error(CallLoc, "call instructions may not have an alignment");
 
-    Attrs.push_back(AttributeList::get(RetType->getContext(),
-                                       AttributeList::FunctionIndex, FnAttrs));
-  }
+  Attrs.push_back(AttributeSetNode::get(Context, FnAttrs));
 
   // Finish off the Attribute and check them
   AttributeList PAL = AttributeList::get(Context, Attrs);