From d5d5d0b80ed674d4d17cac11dfec493e41af0a46 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 10 Apr 2017 20:34:19 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299878 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Attributes.h | 36 +-- lib/AsmParser/LLParser.cpp | 88 ++++-- lib/AsmParser/LLParser.h | 8 +- lib/IR/AsmWriter.cpp | 50 ++-- lib/IR/AttributeImpl.h | 2 +- {include/llvm => lib}/IR/AttributeSetNode.h | 8 +- lib/IR/Attributes.cpp | 267 +++++++----------- lib/IR/Core.cpp | 2 +- lib/Transforms/IPO/ArgumentPromotion.cpp | 43 ++- .../IPO/DeadArgumentElimination.cpp | 85 +++--- lib/Transforms/IPO/MergeFunctions.cpp | 3 +- .../InstCombine/InstCombineCalls.cpp | 49 ++-- .../Scalar/RewriteStatepointsForGC.cpp | 15 +- lib/Transforms/Utils/CloneFunction.cpp | 22 +- lib/Transforms/Utils/CodeExtractor.cpp | 3 +- 15 files changed, 339 insertions(+), 342 deletions(-) rename {include/llvm => lib}/IR/AttributeSetNode.h (93%) diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 6cc856d61e2..dd2a94559bc 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -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> Attrs); static AttributeList get(LLVMContext &C, ArrayRef> 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 Attrs); - static AttributeList getImpl(LLVMContext &C, ArrayRef> 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); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 78de0d65f25..d8f6c1c5146 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -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(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(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(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(SmallVectorImpl &ArgList, 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(SmallVectorImpl &ArgList, 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(SmallVectorImpl &ArgList, 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(SmallVectorImpl &ArgList, 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 *&Result) { 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(Function *&Fn, bool isDefine) { // Okay, if we got here, the function is syntactically valid. Convert types // and do semantic checks. std::vector ParamTypeList; - SmallVector Attrs; + SmallVector 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 *&Inst, PerFunctionState &PFS) { return true; // Set up the Attribute for the function. - SmallVector Attrs; - Attrs.push_back(AttributeSetNode::get(Context, RetAttrs)); + SmallVector Attrs; + if (RetAttrs.hasAttributes()) + Attrs.push_back(AttributeList::get(RetType->getContext(), + AttributeList::ReturnIndex, RetAttrs)); SmallVector Args; @@ -5377,16 +5391,22 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { 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 *&Inst, PerFunctionState &PFS, return true; // Set up the Attribute for the function. - SmallVector Attrs; - Attrs.push_back(AttributeSetNode::get(Context, RetAttrs)); + SmallVector Attrs; + if (RetAttrs.hasAttributes()) + Attrs.push_back(AttributeList::get(RetType->getContext(), + AttributeList::ReturnIndex, RetAttrs)); SmallVector Args; @@ -5971,16 +5993,22 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, 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); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index f3e1cc85c8b..3a794142172 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -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 &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 &ArgList, bool &isVarArg); diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index f8481039c66..3afa3986052 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -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 asMap; + DenseMap 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::iterator as_iterator; + /// AttributeList map iterators. + typedef DenseMap::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(&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(&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 Value *V) { 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(const MDNode *N) { 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 Function *F) { 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(const MDNode *Node) { } void AssemblyWriter::writeAllAttributeGroups() { - std::vector> asVec; + std::vector> asVec; asVec.resize(Machine.as_size()); for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end(); @@ -3253,7 +3259,7 @@ void AssemblyWriter::writeAllAttributeGroups() { 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) { diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 77f1067c7ac..01140b70bfc 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -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 diff --git a/include/llvm/IR/AttributeSetNode.h b/lib/IR/AttributeSetNode.h similarity index 93% rename from include/llvm/IR/AttributeSetNode.h rename to lib/IR/AttributeSetNode.h index 8a5bb3f475c..481cf47918c 100644 --- a/include/llvm/IR/AttributeSetNode.h +++ b/lib/IR/AttributeSetNode.h @@ -1,4 +1,5 @@ -//===-- AttributeSetNode.h - AttributeList Internal Node --------*- C++ -*-===// +//===-- AttributeSetNode.h - AttributeList Internal Node ---------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -8,8 +9,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the class that represents a group of attributes -/// that apply to one element: function, return type, or parameter. +/// \brief This file defines the node class used internally by AttributeList. /// //===----------------------------------------------------------------------===// @@ -64,8 +64,6 @@ public: void operator delete(void *p) { ::operator delete(p); } - static AttributeSetNode *get(LLVMContext &C, const AttrBuilder &B); - static AttributeSetNode *get(LLVMContext &C, ArrayRef Attrs); static AttributeSetNode *get(AttributeList AS, unsigned Index) { diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 0cdc48e2d64..c2759849b60 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -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(LLVMContext &C, return PA; } -AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) { - // Add target-independent attributes. - SmallVector 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::dump() const { AttributeList AttributeList::getImpl( LLVMContext &C, ArrayRef> 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 Attrs) { - assert(Attrs.size() >= 2 && - "should always have function and return attr slots"); - SmallVector, 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 Arr[1] = {{Index, ASN}}; - return getImpl(C, Arr); + + // Add target-independent attributes. + SmallVector, 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::addAttribute(LLVMContext &C, unsigned Index, AttributeList AttributeList::addAttribute(LLVMContext &C, ArrayRef Indices, Attribute A) const { - assert(std::is_sorted(Indices.begin(), Indices.end())); - unsigned I = 0, E = pImpl ? pImpl->getNumSlots() : 0; - SmallVector 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)); + auto IdxI = Indices.begin(), IdxE = Indices.end(); + SmallVector AttrSet; - // 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))); + 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,58 +823,51 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, 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, 4> AttrSet; + // Add the attribute slots before the one we're trying to add. + SmallVector 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; + } + + AttrSet.push_back(AttributeList::get(C, Index, 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::addAttributes(LLVMContext &C, unsigned Index, - const AttrBuilder &B) const { - return get(C, Index, AttributeSetNode::get(C, B)); -} - AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const { if (!hasAttribute(Index, Kind)) return *this; @@ -1005,20 +961,6 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, return get(C, AttrSet); } -AttributeList AttributeList::removeAttributes(LLVMContext &C, - unsigned WithoutIndex) const { - if (!pImpl) - return AttributeList(); - - SmallVector, 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(LLVMContext &C, unsigned Index, LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); } -AttributeSetNode *AttributeList::getParamAttributes(unsigned Index) const { - return getAttributes(Index); +AttributeList AttributeList::getParamAttributes(unsigned Index) const { + return pImpl && hasAttributes(Index) + ? AttributeList::get( + pImpl->getContext(), + ArrayRef>( + std::make_pair(Index, getAttributes(Index)))) + : AttributeList(); } -AttributeSetNode *AttributeList::getRetAttributes() const { - return getAttributes(ReturnIndex); +AttributeList AttributeList::getRetAttributes() const { + return pImpl && hasAttributes(ReturnIndex) + ? AttributeList::get( + pImpl->getContext(), + ArrayRef>( + std::make_pair(ReturnIndex, getAttributes(ReturnIndex)))) + : AttributeList(); } -AttributeSetNode *AttributeList::getFnAttributes() const { - return getAttributes(FunctionIndex); +AttributeList AttributeList::getFnAttributes() const { + return pImpl && hasAttributes(FunctionIndex) + ? AttributeList::get( + pImpl->getContext(), + ArrayRef>( + std::make_pair(FunctionIndex, + getAttributes(FunctionIndex)))) + : AttributeList(); } bool AttributeList::hasAttribute(unsigned Index, @@ -1223,13 +1181,6 @@ AttrBuilder::AttrBuilder(AttributeList AS, unsigned Index) { } } -AttrBuilder::AttrBuilder(AttributeSetNode *AS) { - if (AS) { - for (const Attribute &A : *AS) - addAttribute(A); - } -} - void AttrBuilder::clear() { Attrs.reset(); TargetDepAttrs.clear(); diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index f1843593a3b..c5b3d18764d 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -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" diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index b8f92f26b33..cc525ce6e36 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -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 &ArgsToPromote, // 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 AttributesVec; + SmallVector 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 &ArgsToPromote, Type *AgTy = cast(I->getType())->getElementType(); StructType *STy = cast(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 &ArgsToPromote, Params.push_back(GetElementPtrInst::getIndexedType( cast(I->getType()->getScalarType())->getElementType(), ArgIndex.second)); - AttributesVec.push_back(nullptr); assert(Params.back()); } @@ -180,7 +184,9 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, } // 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 &ArgsToPromote, 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 &ArgsToPromote, ++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(I->getType())->getElementType(); @@ -240,7 +253,6 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, 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 &ArgsToPromote, 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 OpBundles; CS.getOperandBundlesAsDefs(OpBundles); diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index c7138bfbc8b..fe79efce290 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -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::DeleteDeadVarargs(Function &Fn) { 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::RemoveDeadStuffFromFunction(Function *F) { bool HasLiveReturnedArg = false; // Set up to build a new list of parameter attributes. - SmallVector AttributesVec; + SmallVector 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 ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct @@ -705,8 +699,16 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { 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::RemoveDeadStuffFromFunction(Function *F) { 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::RemoveDeadStuffFromFunction(Function *F) { 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::RemoveDeadStuffFromFunction(Function *F) { 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 = diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 5d41ca9f9fc..dc7390232c5 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -439,7 +439,8 @@ void MergeFunctions::replaceDirectCallers(Function *Old, Function *New) { 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); } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index c850e2e7393..af4c9ac7537 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -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::transformConstExprCastCall(CallSite CS) { 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::transformConstExprCastCall(CallSite CS) { // 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(ParamTy); if (!ParamPTy || !ParamPTy->getElementType()->isSized()) return false; @@ -4083,7 +4084,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { } // 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::transformConstExprCastCall(CallSite CS) { } // 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::transformConstExprCastCall(CallSite CS) { } } - 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::transformCallThroughTrampoline(CallSite CS, Value *Callee = CS.getCalledValue(); PointerType *PTy = cast(Callee->getType()); FunctionType *FTy = cast(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::transformCallThroughTrampoline(CallSite CS, Function *NestF =cast(Tramp->getArgOperand(1)->stripPointerCasts()); FunctionType *NestFTy = cast(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::transformCallThroughTrampoline(CallSite CS, if (NestTy) { Instruction *Caller = CS.getInstruction(); std::vector NewArgs; - std::vector NewAttrs; NewArgs.reserve(CS.arg_size() + 1); - NewAttrs.reserve(CS.arg_size() + 2); + + SmallVector 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::transformCallThroughTrampoline(CallSite CS, 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::transformCallThroughTrampoline(CallSite CS, // 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::transformCallThroughTrampoline(CallSite CS, } // 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::transformCallThroughTrampoline(CallSite CS, 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 OpBundles; CS.getOperandBundlesAsDefs(OpBundles); diff --git a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index 84f76b6d1b5..95e598a17b1 100644 --- a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1392,6 +1392,7 @@ makeStatepointExplicitImpl(const CallSite CS, /* to replace */ // Create the statepoint given all the arguments Instruction *Token = nullptr; + AttributeList ReturnAttrs; if (CS.isCall()) { CallInst *ToReplace = cast(CS.getInstruction()); CallInst *Call = Builder.CreateGCStatepointCall( @@ -1406,9 +1407,8 @@ makeStatepointExplicitImpl(const CallSite CS, /* to replace */ 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 CallSite CS, /* to replace */ 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 CallSite CS, /* to replace */ 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 diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index f4803028f3c..60b988e880b 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -103,25 +103,21 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer)); - SmallVector, 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(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, 1> MDs; OldFunc->getAllMetadata(MDs); diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp index 3bc33d0c666..755427cace2 100644 --- a/lib/Transforms/Utils/CodeExtractor.cpp +++ b/lib/Transforms/Utils/CodeExtractor.cpp @@ -362,7 +362,8 @@ Function *CodeExtractor::constructFunction(const ValueSet &inputs, // "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);