From 06090406b0c6c43623a16b9f6be7e9114e43c193 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 12 Apr 2017 00:38:00 +0000 Subject: [PATCH] [IR] Add AttributeSet to hide AttributeSetNode* again, NFC Summary: For now, it just wraps AttributeSetNode*. Eventually, it will hold AvailableAttrs as an inline bitset, and adding and removing enum attributes will be super cheap. This sinks AttributeSetNode back down to lib/IR/AttributeImpl.h. Reviewers: pete, chandlerc Subscribers: llvm-commits, jfb Differential Revision: https://reviews.llvm.org/D31940 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300014 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/AttributeSetNode.h | 93 -------- include/llvm/IR/Attributes.h | 97 ++++++++- lib/AsmParser/LLParser.cpp | 27 ++- lib/AsmParser/LLParser.h | 8 +- lib/IR/AsmWriter.cpp | 44 ++-- lib/IR/AttributeImpl.h | 91 ++++++-- lib/IR/Attributes.cpp | 205 +++++++++++------- lib/IR/Core.cpp | 25 +-- lib/Transforms/IPO/ArgumentPromotion.cpp | 12 +- .../IPO/DeadArgumentElimination.cpp | 16 +- lib/Transforms/IPO/MergeFunctions.cpp | 3 +- .../InstCombine/InstCombineCalls.cpp | 7 +- lib/Transforms/Utils/CloneFunction.cpp | 12 +- 13 files changed, 356 insertions(+), 284 deletions(-) delete mode 100644 include/llvm/IR/AttributeSetNode.h diff --git a/include/llvm/IR/AttributeSetNode.h b/include/llvm/IR/AttributeSetNode.h deleted file mode 100644 index 7dcb9f67d71..00000000000 --- a/include/llvm/IR/AttributeSetNode.h +++ /dev/null @@ -1,93 +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 -#include -#include -#include -#include - -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 { - 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 Attrs); - -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 Attrs); - - /// \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> getAllocSizeArgs() const; - std::string getAsString(bool InAttrGrp) const; - - typedef const Attribute *iterator; - iterator begin() const { return getTrailingObjects(); } - iterator end() const { return begin() + NumAttrs; } - - void Profile(FoldingSetNodeID &ID) const { - Profile(ID, makeArrayRef(begin(), end())); - } - static void Profile(FoldingSetNodeID &ID, ArrayRef AttrList) { - for (const auto &Attr : AttrList) - Attr.Profile(ID); - } -}; - -} // end namespace llvm - -#endif // LLVM_IR_ATTRIBUTESETNODE_H diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 6cc856d61e2..457682b9b2e 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -195,6 +195,84 @@ inline Attribute unwrap(LLVMAttributeRef Attr) { return Attribute::fromRawPointer(Attr); } +//===----------------------------------------------------------------------===// +/// \class +/// This class holds the attributes for a particular argument, parameter, +/// function, or return value. It is an immutable value type that is cheap to +/// copy. Adding and removing enum attributes is intended to be fast, but adding +/// and removing string or integer attributes involves a FoldingSet lookup. +class AttributeSet { + // TODO: Extract AvailableAttrs from AttributeSetNode and store them here. + // This will allow an efficient implementation of addAttribute and + // removeAttribute for enum attrs. + + /// Private implementation pointer. + AttributeSetNode *SetNode = nullptr; + + friend AttributeListImpl; + template friend struct DenseMapInfo; + +private: + AttributeSet(AttributeSetNode *ASN) : SetNode(ASN) {} + +public: + /// AttributeSet is a trivially copyable value type. + AttributeSet() = default; + AttributeSet(const AttributeSet &) = default; + ~AttributeSet() = default; + + static AttributeSet get(LLVMContext &C, const AttrBuilder &B); + static AttributeSet get(LLVMContext &C, ArrayRef Attrs); + + bool operator==(const AttributeSet &O) { return SetNode == O.SetNode; } + bool operator!=(const AttributeSet &O) { return !(*this == O); } + + unsigned getNumAttributes() const; + + bool hasAttributes() const { return SetNode != nullptr; } + + bool hasAttribute(Attribute::AttrKind Kind) const; + bool hasAttribute(StringRef Kind) const; + + 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> getAllocSizeArgs() const; + std::string getAsString(bool InAttrGrp) const; + + typedef const Attribute *iterator; + iterator begin() const; + iterator end() const; +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief Provide DenseMapInfo for AttributeSet. +template <> struct DenseMapInfo { + static inline AttributeSet getEmptyKey() { + uintptr_t Val = static_cast(-1); + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast(Val)); + } + + static inline AttributeSet getTombstoneKey() { + uintptr_t Val = static_cast(-2); + Val <<= PointerLikeTypeTraits::NumLowBitsAvailable; + return AttributeSet(reinterpret_cast(Val)); + } + + static unsigned getHashValue(AttributeSet AS) { + return (unsigned((uintptr_t)AS.SetNode) >> 4) ^ + (unsigned((uintptr_t)AS.SetNode) >> 9); + } + + static bool isEqual(AttributeSet LHS, AttributeSet RHS) { return LHS == RHS; } +}; + //===----------------------------------------------------------------------===// /// \class /// \brief This class holds the attributes for a function, its return value, and @@ -213,6 +291,7 @@ public: private: friend class AttrBuilder; friend class AttributeListImpl; + friend class AttributeSet; friend class AttributeSetNode; template friend struct DenseMapInfo; @@ -226,7 +305,7 @@ public: static AttributeList get(LLVMContext &C, ArrayRef> Attrs); static AttributeList - get(LLVMContext &C, ArrayRef> Attrs); + 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: @@ -234,11 +313,11 @@ public: /// 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 get(LLVMContext &C, ArrayRef Attrs); static AttributeList getImpl(LLVMContext &C, - ArrayRef> Attrs); + ArrayRef> Attrs); private: explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {} @@ -280,7 +359,7 @@ public: AttributeList Attrs) const; AttributeList addAttributes(LLVMContext &C, unsigned Index, - AttributeSetNode *AS) const; + AttributeSet AS) const; AttributeList addAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &B) const; @@ -339,16 +418,16 @@ public: LLVMContext &getContext() const; /// \brief The attributes for the specified index are returned. - AttributeSetNode *getAttributes(unsigned Index) const; + AttributeSet getAttributes(unsigned Index) const; /// \brief The attributes for the specified index are returned. - AttributeSetNode *getParamAttributes(unsigned Index) const; + AttributeSet getParamAttributes(unsigned Index) const; /// \brief The attributes for the ret value are returned. - AttributeSetNode *getRetAttributes() const; + AttributeSet getRetAttributes() const; /// \brief The function attributes are returned. - AttributeSetNode *getFnAttributes() const; + AttributeSet getFnAttributes() const; /// \brief Return true if the attribute exists at the given index. bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const; @@ -483,7 +562,7 @@ public: addAttribute(A); } AttrBuilder(AttributeList AS, unsigned Idx); - AttrBuilder(AttributeSetNode *AS); + AttrBuilder(AttributeSet AS); void clear(); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index ffe620348fb..68d448ed7e0 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" @@ -2155,7 +2154,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl &ArgList, return true; } ArgList.push_back(ParamInfo( - ArgLoc, V, AttributeSetNode::get(V->getContext(), ArgAttrs))); + ArgLoc, V, AttributeSet::get(V->getContext(), ArgAttrs))); } if (IsMustTailCall && InVarArgsFunc) @@ -2261,7 +2260,7 @@ bool LLParser::ParseArgumentList(SmallVectorImpl &ArgList, return Error(TypeLoc, "invalid type for function argument"); ArgList.emplace_back(TypeLoc, ArgTy, - AttributeSetNode::get(ArgTy->getContext(), Attrs), + AttributeSet::get(ArgTy->getContext(), Attrs), std::move(Name)); while (EatIfPresent(lltok::comma)) { @@ -2289,7 +2288,7 @@ bool LLParser::ParseArgumentList(SmallVectorImpl &ArgList, return Error(TypeLoc, "invalid type for function argument"); ArgList.emplace_back(TypeLoc, ArgTy, - AttributeSetNode::get(ArgTy->getContext(), Attrs), + AttributeSet::get(ArgTy->getContext(), Attrs), std::move(Name)); } } @@ -2314,7 +2313,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()) return Error(ArgList[i].Loc, "argument attributes invalid in function type"); } @@ -4763,16 +4762,16 @@ 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)); + Attrs.push_back(AttributeSet::get(Context, RetAttrs)); for (unsigned i = 0, e = ArgList.size(); i != e; ++i) { ParamTypeList.push_back(ArgList[i].Ty); Attrs.push_back(ArgList[i].Attrs); } - Attrs.push_back(AttributeSetNode::get(Context, FuncAttrs)); + Attrs.push_back(AttributeSet::get(Context, FuncAttrs)); AttributeList PAL = AttributeList::get(Context, Attrs); @@ -5384,8 +5383,8 @@ 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; + Attrs.push_back(AttributeSet::get(Context, RetAttrs)); SmallVector Args; @@ -5414,7 +5413,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) { if (FnAttrs.hasAlignmentAttr()) return Error(CallLoc, "invoke instructions may not have an alignment"); - Attrs.push_back(AttributeSetNode::get(Context, FnAttrs)); + Attrs.push_back(AttributeSet::get(Context, FnAttrs)); // Finish off the Attribute and check them AttributeList PAL = AttributeList::get(Context, Attrs); @@ -5978,8 +5977,8 @@ 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; + Attrs.push_back(AttributeSet::get(Context, RetAttrs)); SmallVector Args; @@ -6008,7 +6007,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, if (FnAttrs.hasAlignmentAttr()) return Error(CallLoc, "call instructions may not have an alignment"); - Attrs.push_back(AttributeSetNode::get(Context, FnAttrs)); + Attrs.push_back(AttributeSet::get(Context, 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 2b693331548..4616c2e8694 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -397,8 +397,8 @@ namespace llvm { struct ParamInfo { LocTy Loc; Value *V; - AttributeSetNode *Attrs; - ParamInfo(LocTy loc, Value *v, AttributeSetNode *attrs) + AttributeSet Attrs; + ParamInfo(LocTy loc, Value *v, AttributeSet attrs) : Loc(loc), V(v), Attrs(attrs) {} }; bool ParseParameterList(SmallVectorImpl &ArgList, @@ -450,9 +450,9 @@ namespace llvm { struct ArgInfo { LocTy Loc; Type *Ty; - AttributeSetNode *Attrs; + AttributeSet Attrs; std::string Name; - ArgInfo(LocTy L, Type *ty, AttributeSetNode *Attr, const std::string &N) + ArgInfo(LocTy L, Type *ty, AttributeSet 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 e995a586b7c..50774a395b5 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -21,7 +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" @@ -606,7 +605,7 @@ private: unsigned mdnNext; /// asMap - The slot map for attribute sets. - DenseMap asMap; + DenseMap asMap; unsigned asNext; public: /// Construct from a module. @@ -629,7 +628,7 @@ public: int getLocalSlot(const Value *V); int getGlobalSlot(const GlobalValue *V); int getMetadataSlot(const MDNode *N); - int getAttributeGroupSlot(AttributeSetNode *AS); + int getAttributeGroupSlot(AttributeSet 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 +651,8 @@ public: unsigned mdn_size() const { return mdnMap.size(); } bool mdn_empty() const { return mdnMap.empty(); } - /// AttributeSetNode map iterators. - typedef DenseMap::iterator as_iterator; + /// AttributeSet 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 +672,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 AttributeSet into the slot table. + void CreateAttributeSetSlot(AttributeSet AS); /// Add all of the module level global variables (and their initializers) /// and function declarations, but not the contents of those functions. @@ -833,8 +832,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) + AttributeSet FnAttrs = F.getAttributes().getFnAttributes(); + if (FnAttrs.hasAttributes()) CreateAttributeSetSlot(FnAttrs); } @@ -869,15 +868,10 @@ void SlotTracker::processFunction() { // We allow direct calls to any llvm.foo function here, because the // target may not be linked into the optimizer. - if (const CallInst *CI = dyn_cast(&I)) { + if (auto CS = ImmutableCallSite(&I)) { // Add all the call attributes to the table. - AttributeSetNode *Attrs = CI->getAttributes().getFnAttributes(); - if (Attrs) - 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) + AttributeSet Attrs = CS.getAttributes().getFnAttributes(); + if (Attrs.hasAttributes()) CreateAttributeSetSlot(Attrs); } } @@ -963,11 +957,11 @@ int SlotTracker::getLocalSlot(const Value *V) { return FI == fMap.end() ? -1 : (int)FI->second; } -int SlotTracker::getAttributeGroupSlot(AttributeSetNode *AS) { +int SlotTracker::getAttributeGroupSlot(AttributeSet AS) { // Check for uninitialized state and do lazy initialization. initialize(); - // Find the AttributeSetNode in the module map. + // Find the AttributeSet in the module map. as_iterator AI = asMap.find(AS); return AI == asMap.end() ? -1 : (int)AI->second; } @@ -1017,8 +1011,8 @@ void SlotTracker::CreateMetadataSlot(const MDNode *N) { CreateMetadataSlot(Op); } -void SlotTracker::CreateAttributeSetSlot(AttributeSetNode *AS) { - assert(AS && "Doesn't need a slot!"); +void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) { + assert(AS.hasAttributes() && "Doesn't need a slot!"); as_iterator I = asMap.find(AS); if (I != asMap.end()) @@ -2607,10 +2601,10 @@ void AssemblyWriter::printFunction(const Function *F) { const AttributeList &Attrs = F->getAttributes(); if (Attrs.hasAttributes(AttributeList::FunctionIndex)) { - AttributeSetNode *AS = Attrs.getFnAttributes(); + AttributeSet AS = Attrs.getFnAttributes(); std::string AttrStr; - for (const Attribute &Attr : *AS) { + for (const Attribute &Attr : AS) { if (!Attr.isStringAttribute()) { if (!AttrStr.empty()) AttrStr += ' '; AttrStr += Attr.getAsString(); @@ -3250,7 +3244,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(); @@ -3259,7 +3253,7 @@ void AssemblyWriter::writeAllAttributeGroups() { for (const auto &I : asVec) Out << "attributes #" << I.second << " = { " - << I.first->getAsString(true) << " }\n"; + << I.first.getAsString(true) << " }\n"; } void AssemblyWriter::printUseListOrder(const UseListOrder &Order) { diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 0cd53f1de00..09f03736579 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -19,7 +19,6 @@ #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 @@ -144,7 +143,65 @@ public: StringRef getStringValue() const { return Val; } }; -typedef std::pair IndexAttrPair; +//===----------------------------------------------------------------------===// +/// \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 { + friend TrailingObjects; + + /// Bitset with a bit for each available attribute Attribute::AttrKind. + uint64_t AvailableAttrs; + unsigned NumAttrs; ///< Number of attributes in this node. + + AttributeSetNode(ArrayRef Attrs); + +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 Attrs); + + /// \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> getAllocSizeArgs() const; + std::string getAsString(bool InAttrGrp) const; + + typedef const Attribute *iterator; + iterator begin() const { return getTrailingObjects(); } + iterator end() const { return begin() + NumAttrs; } + + void Profile(FoldingSetNodeID &ID) const { + Profile(ID, makeArrayRef(begin(), end())); + } + static void Profile(FoldingSetNodeID &ID, ArrayRef AttrList) { + for (const auto &Attr : AttrList) + Attr.Profile(ID); + } +}; + +typedef std::pair IndexAttrPair; //===----------------------------------------------------------------------===// /// \class @@ -166,13 +223,13 @@ private: size_t numTrailingObjects(OverloadToken) { return NumSlots; } /// \brief Return a pointer to the IndexAttrPair for the specified slot. - const IndexAttrPair *getNode(unsigned Slot) const { + const IndexAttrPair *getSlotPair(unsigned Slot) const { return getTrailingObjects() + Slot; } public: AttributeListImpl(LLVMContext &C, - ArrayRef> Slots); + ArrayRef> Slots); // AttributesSetImpt is uniqued, these should not be available. AttributeListImpl(const AttributeListImpl &) = delete; @@ -193,35 +250,35 @@ public: /// attributes are applied to, not the index into the AttrNodes list where the /// attributes reside. unsigned getSlotIndex(unsigned Slot) const { - return getNode(Slot)->first; + return getSlotPair(Slot)->first; + } + + /// \brief Retrieve the attribute set node for the given "slot" in the + /// AttrNode list. + AttributeSet getSlotNode(unsigned Slot) const { + return getSlotPair(Slot)->second; } /// \brief Retrieve the attributes for the given "slot" in the AttrNode list. /// \p Slot is an index into the AttrNodes list, not the index of the return / /// parameter/ function which the attributes apply to. AttributeList getSlotAttributes(unsigned Slot) const { - return AttributeList::get(Context, *getNode(Slot)); + return AttributeList::get(Context, *getSlotPair(Slot)); } - /// \brief Retrieve the attribute set node for the given "slot" in the - /// AttrNode list. - AttributeSetNode *getSlotNode(unsigned Slot) const { - return getNode(Slot)->second; - } - - /// \brief Return true if the AttributeSetNode for the FunctionIndex has an + /// \brief Return true if the AttributeSet or the FunctionIndex has an /// enum attribute of the given kind. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AvailableFunctionAttrs & ((uint64_t)1) << Kind; } - typedef AttributeSetNode::iterator iterator; - iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); } - iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); } + typedef AttributeSet::iterator iterator; + iterator begin(unsigned Slot) const { return getSlotNode(Slot).begin(); } + iterator end(unsigned Slot) const { return getSlotNode(Slot).end(); } void Profile(FoldingSetNodeID &ID) const; static void Profile(FoldingSetNodeID &ID, - ArrayRef> Nodes); + ArrayRef> Nodes); void dump() const; }; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 7077da14a18..4b840c36ccb 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -23,7 +23,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" @@ -491,14 +490,76 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const { return getKindAsString() < AI.getKindAsString(); } +//===----------------------------------------------------------------------===// +// AttributeSet Definition +//===----------------------------------------------------------------------===// + +AttributeSet AttributeSet::get(LLVMContext &C, const AttrBuilder &B) { + return AttributeSet(AttributeSetNode::get(C, B)); +} + +AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef Attrs) { + return AttributeSet(AttributeSetNode::get(C, Attrs)); +} + +unsigned AttributeSet::getNumAttributes() const { + return SetNode ? SetNode->getNumAttributes() : 0; +} + +bool AttributeSet::hasAttribute(Attribute::AttrKind Kind) const { + return SetNode ? SetNode->hasAttribute(Kind) : 0; +} + +bool AttributeSet::hasAttribute(StringRef Kind) const { + return SetNode ? SetNode->hasAttribute(Kind) : 0; +} + +Attribute AttributeSet::getAttribute(Attribute::AttrKind Kind) const { + return SetNode ? SetNode->getAttribute(Kind) : Attribute(); +} + +Attribute AttributeSet::getAttribute(StringRef Kind) const { + return SetNode ? SetNode->getAttribute(Kind) : Attribute(); +} + +unsigned AttributeSet::getAlignment() const { + return SetNode ? SetNode->getAlignment() : 0; +} + +unsigned AttributeSet::getStackAlignment() const { + return SetNode ? SetNode->getStackAlignment() : 0; +} + +uint64_t AttributeSet::getDereferenceableBytes() const { + return SetNode ? SetNode->getDereferenceableBytes() : 0; +} + +uint64_t AttributeSet::getDereferenceableOrNullBytes() const { + return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0; +} + +std::pair> AttributeSet::getAllocSizeArgs() const { + return SetNode ? SetNode->getAllocSizeArgs() : std::make_pair(0, 0); +} + +std::string AttributeSet::getAsString(bool InAttrGrp) const { + return SetNode ? SetNode->getAsString(InAttrGrp) : ""; +} + +AttributeSet::iterator AttributeSet::begin() const { + return SetNode ? SetNode->begin() : nullptr; +} + +AttributeSet::iterator AttributeSet::end() const { + return SetNode ? SetNode->end() : nullptr; +} + //===----------------------------------------------------------------------===// // AttributeSetNode Definition //===----------------------------------------------------------------------===// AttributeSetNode::AttributeSetNode(ArrayRef Attrs) - : NumAttrs(Attrs.size()), AvailableAttrs(0) { - static_assert(Attribute::EndAttrKinds <= sizeof(AvailableAttrs) * CHAR_BIT, - "Too many attributes for AvailableAttrs"); + : AvailableAttrs(0), NumAttrs(Attrs.size()) { // There's memory after the node where we can store the entries in. std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects()); @@ -657,7 +718,7 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const { //===----------------------------------------------------------------------===// AttributeListImpl::AttributeListImpl( - LLVMContext &C, ArrayRef> Slots) + LLVMContext &C, ArrayRef> Slots) : Context(C), NumSlots(Slots.size()), AvailableFunctionAttrs(0) { #ifndef NDEBUG if (Slots.size() >= 2) { @@ -678,10 +739,10 @@ AttributeListImpl::AttributeListImpl( "Too many attributes"); static_assert(AttributeList::FunctionIndex == ~0u, "FunctionIndex should be biggest possible index"); - const std::pair &Last = Slots.back(); + const auto &Last = Slots.back(); if (Last.first == AttributeList::FunctionIndex) { - const AttributeSetNode *Node = Last.second; - for (Attribute I : *Node) { + AttributeSet Node = Last.second; + for (Attribute I : Node) { if (!I.isStringAttribute()) AvailableFunctionAttrs |= ((uint64_t)1) << I.getKindAsEnum(); } @@ -690,15 +751,14 @@ AttributeListImpl::AttributeListImpl( } void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { - Profile(ID, makeArrayRef(getNode(0), getNumSlots())); + Profile(ID, makeArrayRef(getSlotPair(0), getNumSlots())); } void AttributeListImpl::Profile( - FoldingSetNodeID &ID, - ArrayRef> Nodes) { + FoldingSetNodeID &ID, ArrayRef> Nodes) { for (const auto &Node : Nodes) { ID.AddInteger(Node.first); - ID.AddPointer(Node.second); + ID.AddPointer(Node.second.SetNode); } } @@ -713,7 +773,7 @@ LLVM_DUMP_METHOD void AttributeListImpl::dump() const { //===----------------------------------------------------------------------===// AttributeList AttributeList::getImpl( - LLVMContext &C, ArrayRef> Attrs) { + LLVMContext &C, ArrayRef> Attrs) { assert(!Attrs.empty() && "creating pointless AttributeList"); #ifndef NDEBUG unsigned LastIndex = 0; @@ -721,7 +781,7 @@ AttributeList AttributeList::getImpl( for (const auto &AttrPair : Attrs) { assert((IsFirst || LastIndex < AttrPair.first) && "unsorted or duplicate AttributeList indices"); - assert(AttrPair.second && "pointless AttributeList slot"); + assert(AttrPair.second.hasAttributes() && "pointless AttributeList slot"); LastIndex = AttrPair.first; IsFirst = false; } @@ -769,7 +829,7 @@ AttributeList::get(LLVMContext &C, // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes // list. - SmallVector, 8> AttrPairVec; + SmallVector, 8> AttrPairVec; for (ArrayRef>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ) { unsigned Index = I->first; @@ -779,7 +839,7 @@ AttributeList::get(LLVMContext &C, ++I; } - AttrPairVec.emplace_back(Index, AttributeSetNode::get(C, AttrVec)); + AttrPairVec.emplace_back(Index, AttributeSet::get(C, AttrVec)); } return getImpl(C, AttrPairVec); @@ -787,7 +847,7 @@ AttributeList::get(LLVMContext &C, AttributeList AttributeList::get(LLVMContext &C, - ArrayRef> Attrs) { + ArrayRef> Attrs) { // If there are no attributes then return a null AttributesList pointer. if (Attrs.empty()) return AttributeList(); @@ -795,13 +855,13 @@ AttributeList::get(LLVMContext &C, return getImpl(C, Attrs); } -AttributeList AttributeList::get(LLVMContext &C, ArrayRef Attrs) { +AttributeList AttributeList::get(LLVMContext &C, ArrayRef Attrs) { assert(Attrs.size() >= 2 && "should always have function and return attr slots"); - SmallVector, 8> AttrPairs; + SmallVector, 8> AttrPairs; size_t Index = 0; - for (AttributeSetNode *AS : Attrs) { - if (AS) { + for (AttributeSet AS : Attrs) { + if (AS.hasAttributes()) { // If this is the last AttributeSetNode, it's for the function. if (Index == Attrs.size() - 1) Index = AttributeList::FunctionIndex; @@ -818,8 +878,8 @@ 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}}; + AttributeSet AS = AttributeSet::get(C, B); + std::pair Arr[1] = {{Index, AS}}; return getImpl(C, Arr); } @@ -845,21 +905,21 @@ AttributeList AttributeList::get(LLVMContext &C, return AttributeList(); if (Attrs.size() == 1) return Attrs[0]; - SmallVector, 8> AttrNodeVec; + SmallVector, 8> AttrNodeVec; AttributeListImpl *A0 = Attrs[0].pImpl; if (A0) - AttrNodeVec.append(A0->getNode(0), A0->getNode(A0->getNumSlots())); + AttrNodeVec.append(A0->getSlotPair(0), A0->getSlotPair(A0->getNumSlots())); // Copy all attributes from Attrs into AttrNodeVec while keeping AttrNodeVec // ordered by index. Because we know that each list in Attrs is ordered by // index we only need to merge each successive list in rather than doing a // full sort. for (unsigned I = 1, E = Attrs.size(); I != E; ++I) { - AttributeListImpl *AS = Attrs[I].pImpl; - if (!AS) continue; - SmallVector, 8>::iterator + AttributeListImpl *ALI = Attrs[I].pImpl; + if (!ALI) continue; + SmallVector, 8>::iterator ANVI = AttrNodeVec.begin(), ANVE; - for (const IndexAttrPair *AI = AS->getNode(0), - *AE = AS->getNode(AS->getNumSlots()); + for (const IndexAttrPair *AI = ALI->getSlotPair(0), + *AE = ALI->getSlotPair(ALI->getNumSlots()); AI != AE; ++AI) { ANVE = AttrNodeVec.end(); while (ANVI != ANVE && ANVI->first <= AI->first) @@ -905,7 +965,7 @@ AttributeList AttributeList::addAttribute(LLVMContext &C, ++I; } B.addAttribute(A); - AttrVec.emplace_back(Index, AttributeSetNode::get(C, B)); + AttrVec.emplace_back(Index, AttributeSet::get(C, B)); } // Add remaining attributes. @@ -924,20 +984,20 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, } AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, - AttributeSetNode *AS) const { - if (!AS) + AttributeSet AS) const { + if (!AS.hasAttributes()) 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 = AS.getAlignment(); assert((!OldAlign || !NewAlign || OldAlign == NewAlign) && "Attempt to change alignment!"); #endif - SmallVector, 4> AttrSet; + SmallVector, 4> AttrSet; uint64_t NumAttrs = pImpl->getNumSlots(); unsigned I; @@ -949,8 +1009,8 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, } if (I < NumAttrs && getSlotIndex(I) == Index) { - // We need to merge two AttributeSetNodes. - AttributeSetNode *Merged = AttributeSetNode::get( + // We need to merge two AttributeSets. + AttributeSet Merged = AttributeSet::get( C, AttrBuilder(pImpl->getSlotNode(I)).merge(AttrBuilder(AS))); AttrSet.emplace_back(Index, Merged); ++I; @@ -969,7 +1029,7 @@ AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, AttributeList AttributeList::addAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &B) const { - return get(C, Index, AttributeSetNode::get(C, B)); + return get(C, Index, AttributeSet::get(C, B)); } AttributeList AttributeList::removeAttribute(LLVMContext &C, unsigned Index, @@ -998,11 +1058,11 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, // Add the attribute slots before the one we're trying to add. SmallVector AttrSet; uint64_t NumAttrs = pImpl->getNumSlots(); - AttributeList AS; + AttributeList AL; uint64_t LastIndex = 0; for (unsigned I = 0, E = NumAttrs; I != E; ++I) { if (getSlotIndex(I) >= Index) { - if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); + if (getSlotIndex(I) == Index) AL = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; @@ -1011,7 +1071,7 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, // Now remove the attribute from the correct slot. There may already be an // AttributeList there. - AttrBuilder B(AS, Index); + AttrBuilder B(AL, Index); for (unsigned I = 0, E = Attrs.pImpl->getNumSlots(); I != E; ++I) if (Attrs.getSlotIndex(I) == Index) { @@ -1040,11 +1100,11 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, // Add the attribute slots before the one we're trying to add. SmallVector AttrSet; uint64_t NumAttrs = pImpl->getNumSlots(); - AttributeList AS; + AttributeList AL; uint64_t LastIndex = 0; for (unsigned I = 0, E = NumAttrs; I != E; ++I) { if (getSlotIndex(I) >= Index) { - if (getSlotIndex(I) == Index) AS = getSlotAttributes(LastIndex++); + if (getSlotIndex(I) == Index) AL = getSlotAttributes(LastIndex++); break; } LastIndex = I + 1; @@ -1053,7 +1113,7 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned Index, // Now remove the attribute from the correct slot. There may already be an // AttributeList there. - AttrBuilder B(AS, Index); + AttrBuilder B(AL, Index); B.remove(Attrs); AttrSet.push_back(AttributeList::get(C, Index, B)); @@ -1070,7 +1130,7 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, if (!pImpl) return AttributeList(); - SmallVector, 4> AttrSet; + SmallVector, 4> AttrSet; for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) { unsigned Index = getSlotIndex(I); if (Index != WithoutIndex) @@ -1110,32 +1170,29 @@ AttributeList::addAllocSizeAttr(LLVMContext &C, unsigned Index, LLVMContext &AttributeList::getContext() const { return pImpl->getContext(); } -AttributeSetNode *AttributeList::getParamAttributes(unsigned Index) const { +AttributeSet AttributeList::getParamAttributes(unsigned Index) const { return getAttributes(Index); } -AttributeSetNode *AttributeList::getRetAttributes() const { +AttributeSet AttributeList::getRetAttributes() const { return getAttributes(ReturnIndex); } -AttributeSetNode *AttributeList::getFnAttributes() const { +AttributeSet AttributeList::getFnAttributes() const { return getAttributes(FunctionIndex); } bool AttributeList::hasAttribute(unsigned Index, Attribute::AttrKind Kind) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN && ASN->hasAttribute(Kind); + return getAttributes(Index).hasAttribute(Kind); } bool AttributeList::hasAttribute(unsigned Index, StringRef Kind) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN && ASN->hasAttribute(Kind); + return getAttributes(Index).hasAttribute(Kind); } bool AttributeList::hasAttributes(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN && ASN->hasAttributes(); + return getAttributes(Index).hasAttributes(); } bool AttributeList::hasFnAttribute(Attribute::AttrKind Kind) const { @@ -1163,55 +1220,47 @@ bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, Attribute AttributeList::getAttribute(unsigned Index, Attribute::AttrKind Kind) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAttribute(Kind) : Attribute(); + return getAttributes(Index).getAttribute(Kind); } Attribute AttributeList::getAttribute(unsigned Index, StringRef Kind) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAttribute(Kind) : Attribute(); + return getAttributes(Index).getAttribute(Kind); } unsigned AttributeList::getParamAlignment(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAlignment() : 0; + return getAttributes(Index).getAlignment(); } unsigned AttributeList::getStackAlignment(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getStackAlignment() : 0; + return getAttributes(Index).getStackAlignment(); } uint64_t AttributeList::getDereferenceableBytes(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getDereferenceableBytes() : 0; + return getAttributes(Index).getDereferenceableBytes(); } uint64_t AttributeList::getDereferenceableOrNullBytes(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getDereferenceableOrNullBytes() : 0; + return getAttributes(Index).getDereferenceableOrNullBytes(); } std::pair> AttributeList::getAllocSizeArgs(unsigned Index) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAllocSizeArgs() : std::make_pair(0u, Optional(0u)); + return getAttributes(Index).getAllocSizeArgs(); } std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const { - AttributeSetNode *ASN = getAttributes(Index); - return ASN ? ASN->getAsString(InAttrGrp) : std::string(""); + return getAttributes(Index).getAsString(InAttrGrp); } -AttributeSetNode *AttributeList::getAttributes(unsigned Index) const { - if (!pImpl) return nullptr; +AttributeSet AttributeList::getAttributes(unsigned Index) const { + if (!pImpl) return AttributeSet(); // Loop through to find the attribute node we want. for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) if (pImpl->getSlotIndex(I) == Index) return pImpl->getSlotNode(I); - return nullptr; + return AttributeSet(); } AttributeList::iterator AttributeList::begin(unsigned Slot) const { @@ -1268,8 +1317,8 @@ LLVM_DUMP_METHOD void AttributeList::dump() const { // AttrBuilder Method Implementations //===----------------------------------------------------------------------===// -AttrBuilder::AttrBuilder(AttributeList AS, unsigned Index) { - AttributeListImpl *pImpl = AS.pImpl; +AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) { + AttributeListImpl *pImpl = AL.pImpl; if (!pImpl) return; for (unsigned I = 0, E = pImpl->getNumSlots(); I != E; ++I) { @@ -1283,9 +1332,9 @@ AttrBuilder::AttrBuilder(AttributeList AS, unsigned Index) { } } -AttrBuilder::AttrBuilder(AttributeSetNode *AS) { - if (AS) { - for (const Attribute &A : *AS) +AttrBuilder::AttrBuilder(AttributeSet AS) { + if (AS.hasAttributes()) { + for (const Attribute &A : AS) addAttribute(A); } } diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 2636ca1a724..b5ed30b85c8 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -16,7 +16,6 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/Attributes.h" -#include "llvm/IR/AttributeSetNode.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" @@ -1847,18 +1846,14 @@ void LLVMAddAttributeAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, } unsigned LLVMGetAttributeCountAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx) { - auto *ASN = unwrap(F)->getAttributes().getAttributes(Idx); - if (!ASN) - return 0; - return ASN->getNumAttributes(); + auto AS = unwrap(F)->getAttributes().getAttributes(Idx); + return AS.getNumAttributes(); } void LLVMGetAttributesAtIndex(LLVMValueRef F, LLVMAttributeIndex Idx, LLVMAttributeRef *Attrs) { - auto *ASN = unwrap(F)->getAttributes().getAttributes(Idx); - if (!ASN) - return; - for (auto A: make_range(ASN->begin(), ASN->end())) + auto AS = unwrap(F)->getAttributes().getAttributes(Idx); + for (auto A : AS) *Attrs++ = wrap(A); } @@ -2178,19 +2173,15 @@ void LLVMAddCallSiteAttribute(LLVMValueRef C, LLVMAttributeIndex Idx, unsigned LLVMGetCallSiteAttributeCount(LLVMValueRef C, LLVMAttributeIndex Idx) { auto CS = CallSite(unwrap(C)); - auto *ASN = CS.getAttributes().getAttributes(Idx); - if (!ASN) - return 0; - return ASN->getNumAttributes(); + auto AS = CS.getAttributes().getAttributes(Idx); + return AS.getNumAttributes(); } void LLVMGetCallSiteAttributes(LLVMValueRef C, LLVMAttributeIndex Idx, LLVMAttributeRef *Attrs) { auto CS = CallSite(unwrap(C)); - auto *ASN = CS.getAttributes().getAttributes(Idx); - if (!ASN) - return; - for (auto A: make_range(ASN->begin(), ASN->end())) + auto AS = CS.getAttributes().getAttributes(Idx); + for (auto A : AS) *Attrs++ = wrap(A); } diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 1646237b096..c43557b4e1a 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,7 +102,7 @@ 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. @@ -118,7 +117,8 @@ 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); + AttributesVec.insert(AttributesVec.end(), STy->getNumElements(), + AttributeSet()); ++NumByValArgsPromoted; } else if (!ArgsToPromote.count(&*I)) { // Unchanged argument @@ -168,7 +168,7 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, Params.push_back(GetElementPtrInst::getIndexedType( cast(I->getType()->getScalarType())->getElementType(), ArgIndex.second)); - AttributesVec.push_back(nullptr); + AttributesVec.push_back(AttributeSet()); assert(Params.back()); } @@ -240,7 +240,7 @@ 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); + AttributesVec.push_back(AttributeSet()); } } else if (!I->use_empty()) { // Non-dead argument: insert GEPs and loads as appropriate. @@ -283,7 +283,7 @@ doPromotion(Function *F, SmallPtrSetImpl &ArgsToPromote, newLoad->setAAMetadata(AAInfo); Args.push_back(newLoad); - AttributesVec.push_back(nullptr); + AttributesVec.push_back(AttributeSet()); } } diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index c7138bfbc8b..66eb33f246a 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" @@ -686,12 +685,12 @@ 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); + AttributesVec.push_back(AttributeSet()); // Remember which arguments are still alive. SmallVector ArgAlive(FTy->getNumParams(), false); @@ -792,7 +791,7 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { assert(!RAttrs.overlaps(AttributeFuncs::typeIncompatible(NRetTy)) && "Return attributes no longer compatible?"); - AttributesVec[0] = AttributeSetNode::get(F->getContext(), RAttrs); + AttributesVec[0] = AttributeSet::get(F->getContext(), RAttrs); // Transfer the function attributes, if any. AttributesVec.push_back(PAL.getFnAttributes()); @@ -833,7 +832,7 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { // return void. AttrBuilder RAttrs(CallPAL.getRetAttributes()); RAttrs.remove(AttributeFuncs::typeIncompatible(NRetTy)); - AttributesVec.push_back(AttributeSetNode::get(F->getContext(), RAttrs)); + AttributesVec.push_back(AttributeSet::get(F->getContext(), RAttrs)); // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. @@ -845,15 +844,14 @@ 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)) { + AttributeSet Attrs = CallPAL.getParamAttributes(i + 1); + if (NRetTy != RetTy && Attrs.hasAttribute(Attribute::Returned)) { // If the return type has changed, then get rid of 'returned' on the // call site. The alternative is to make all 'returned' attributes on // call sites keep the return value alive just like 'returned' // attributes on function declaration but it's less clearly a win and // this is not an expected case anyway - AttributesVec.push_back(AttributeSetNode::get( + AttributesVec.push_back(AttributeSet::get( F->getContext(), AttrBuilder(Attrs).removeAttribute(Attribute::Returned))); } else { diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 5d41ca9f9fc..4ce4de13c93 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)) + AttributeSet Attrs = NewFuncAttrs.getParamAttributes(argIdx); + if (Attrs.hasAttributes()) CallSiteAttrs = CallSiteAttrs.addAttributes(Context, argIdx, Attrs); } diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index c850e2e7393..cdae9571851 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" @@ -4119,7 +4118,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { } } - AttributeSetNode *FnAttrs = CallerPAL.getFnAttributes(); + AttributeSet FnAttrs = CallerPAL.getFnAttributes(); if (CallerPAL.hasAttributes(AttributeList::FunctionIndex)) attrVec.push_back(AttributeList::get(Callee->getContext(), AttributeList::FunctionIndex, @@ -4218,7 +4217,7 @@ InstCombiner::transformCallThroughTrampoline(CallSite CS, if (!NestAttrs.isEmpty()) { unsigned NestIdx = 1; Type *NestTy = nullptr; - AttributeSetNode *NestAttr; + AttributeSet NestAttr; // Look for a parameter marked with the 'nest' attribute. for (FunctionType::param_iterator I = NestFTy->param_begin(), @@ -4233,7 +4232,7 @@ InstCombiner::transformCallThroughTrampoline(CallSite CS, if (NestTy) { Instruction *Caller = CS.getInstruction(); std::vector NewArgs; - std::vector NewAttrs; + std::vector NewAttrs; NewArgs.reserve(CS.arg_size() + 1); NewAttrs.reserve(CS.arg_size() + 2); diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index f4803028f3c..3a78158478c 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -103,23 +103,21 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer)); - SmallVector, 4> AttrVec; + SmallVector AttrVec(NewFunc->arg_size() + 2); AttributeList OldAttrs = OldFunc->getAttributes(); // Copy the return attributes. - if (auto *RetAttrs = OldAttrs.getRetAttributes()) - AttrVec.emplace_back(AttributeList::ReturnIndex, RetAttrs); + AttrVec[0] = OldAttrs.getRetAttributes(); // 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); + AttrVec[NewArg->getArgNo() + 1] = + OldAttrs.getParamAttributes(OldArg.getArgNo() + 1); } // Copy any function attributes. - if (auto *FnAttrs = OldAttrs.getFnAttributes()) - AttrVec.emplace_back(AttributeList::FunctionIndex, FnAttrs); + AttrVec.back() = OldAttrs.getFnAttributes(); NewFunc->setAttributes(AttributeList::get(NewFunc->getContext(), AttrVec));