diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -282,6 +282,8 @@ unsigned NumAttrSets; ///< Number of entries in this set. /// Available enum function attributes. AttributeBitSet AvailableFunctionAttrs; + /// Union of enum attributes available at any index. + AttributeBitSet AvailableSomewhereAttrs; // Helper fn for TrailingObjects class. size_t numTrailingObjects(OverloadToken) { return NumAttrSets; } @@ -299,6 +301,12 @@ return AvailableFunctionAttrs.hasAttribute(Kind); } + /// Return true if the specified attribute is set for at least one + /// parameter or for the return value. If Index is not nullptr, the index + /// of a parameter with the specified attribute is provided. + bool hasAttrSomewhere(Attribute::AttrKind Kind, + unsigned *Index = nullptr) const; + using iterator = const AttributeSet *; iterator begin() const { return getTrailingObjects(); } diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -977,13 +977,18 @@ // There's memory after the node where we can store the entries in. llvm::copy(Sets, getTrailingObjects()); - // Initialize AvailableFunctionAttrs summary bitset. + // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs + // summary bitsets. static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, "function should be stored in slot 0"); - for (const auto &I : Sets[0]) { + for (const auto &I : Sets[0]) if (!I.isStringAttribute()) AvailableFunctionAttrs.addAttribute(I.getKindAsEnum()); - } + + for (const auto &Set : Sets) + for (const auto &I : Set) + if (!I.isStringAttribute()) + AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum()); } void AttributeListImpl::Profile(FoldingSetNodeID &ID) const { @@ -996,6 +1001,24 @@ ID.AddPointer(Set.SetNode); } +bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind, + unsigned *Index) const { + if (!AvailableSomewhereAttrs.hasAttribute(Kind)) + return false; + + if (Index) { + for (unsigned I = 0, E = NumAttrSets; I != E; ++I) { + if (begin()[I].hasAttribute(Kind)) { + *Index = I - 1; + break; + } + } + } + + return true; +} + + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void AttributeListImpl::dump() const { AttributeList(const_cast(this)).dump(); @@ -1401,17 +1424,7 @@ bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr, unsigned *Index) const { - if (!pImpl) return false; - - for (unsigned I = index_begin(), E = index_end(); I != E; ++I) { - if (hasAttribute(I, Attr)) { - if (Index) - *Index = I; - return true; - } - } - - return false; + return pImpl && pImpl->hasAttrSomewhere(Attr, Index); } Attribute AttributeList::getAttribute(unsigned Index,