Index: include/llvm/IR/Attributes.h =================================================================== --- include/llvm/IR/Attributes.h +++ include/llvm/IR/Attributes.h @@ -292,6 +292,10 @@ /// \brief Return true if attribute exists at the given index. bool hasAttributes(unsigned Index) const; + /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but + /// may be faster. + bool hasFnAttribute(Attribute::AttrKind Kind) const; + /// \brief Return true if the specified attribute is set for at least one /// parameter or for the return value. bool hasAttrSomewhere(Attribute::AttrKind Attr) const; Index: include/llvm/IR/Function.h =================================================================== --- include/llvm/IR/Function.h +++ include/llvm/IR/Function.h @@ -199,7 +199,7 @@ /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { - return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); + return AttributeSets.hasFnAttribute(Kind); } bool hasFnAttribute(StringRef Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); @@ -207,6 +207,8 @@ /// @brief Return the attribute for the given attribute kind. Attribute getFnAttribute(Attribute::AttrKind Kind) const { + if (!hasFnAttribute(Kind)) + return Attribute(); return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); } Attribute getFnAttribute(StringRef Kind) const { @@ -215,6 +217,8 @@ /// \brief Return the stack alignment for the function. unsigned getFnStackAlignment() const { + if (!hasFnAttribute(Attribute::StackAlignment)) + return 0; return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex); } Index: lib/IR/AttributeImpl.h =================================================================== --- lib/IR/AttributeImpl.h +++ lib/IR/AttributeImpl.h @@ -214,6 +214,11 @@ private: LLVMContext &Context; unsigned NumAttrs; ///< Number of entries in this set. + /// Bitset with a bit for each available attribute Attribute::AttrKind. + uint64_t AvailableFunctionAttrs; + static_assert(Attribute::EndAttrKinds + <= sizeof(AvailableFunctionAttrs)*CHAR_BIT, + "Too many attributes"); // Helper fn for TrailingObjects class. size_t numTrailingObjects(OverloadToken) { return NumAttrs; } @@ -229,7 +234,7 @@ public: AttributeSetImpl(LLVMContext &C, ArrayRef > Attrs) - : Context(C), NumAttrs(Attrs.size()) { + : Context(C), NumAttrs(Attrs.size()), AvailableFunctionAttrs(0) { #ifndef NDEBUG if (Attrs.size() >= 2) { @@ -242,6 +247,21 @@ #endif // There's memory after the node where we can store the entries in. std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects()); + + // Initialize AvailableFunctionAttrs summary bitset. + if (NumAttrs > 0) { + static_assert(AttributeSet::FunctionIndex == ~0u, + "FunctionIndex should be biggest possible index"); + const std::pair &Last = Attrs.back(); + if (Last.first == AttributeSet::FunctionIndex) { + const AttributeSetNode *Node = Last.second; + for (AttributeSetNode::iterator I = Node->begin(), E = Node->end(); + I != E; ++I) { + if (!I->isStringAttribute()) + AvailableFunctionAttrs |= ((uint64_t)1) << I->getKindAsEnum(); + } + } + } } /// \brief Get the context that created this AttributeSetImpl. @@ -271,6 +291,12 @@ return getNode(Slot)->second; } + /// \brief Return true if the AttributeSetNode for 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(); } Index: lib/IR/Attributes.cpp =================================================================== --- lib/IR/Attributes.cpp +++ lib/IR/Attributes.cpp @@ -999,6 +999,10 @@ return ASN && ASN->hasAttributes(); } +bool AttributeSet::hasFnAttribute(Attribute::AttrKind Kind) const { + return pImpl && pImpl->hasFnAttribute(Kind); +} + bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const { if (!pImpl) return false;