diff --git a/llvm/lib/IR/AttributeImpl.h b/llvm/lib/IR/AttributeImpl.h index 8cea7bf03dd3..44c35ca36045 100644 --- a/llvm/lib/IR/AttributeImpl.h +++ b/llvm/lib/IR/AttributeImpl.h @@ -188,6 +188,7 @@ class AttributeSetNode final static AttributeSetNode *getSorted(LLVMContext &C, ArrayRef SortedAttrs); + Optional findEnumAttribute(Attribute::AttrKind Kind) const; public: // AttributesSetNode is uniqued, these should not be available. diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index 40952a1d5e51..7c6ce2c78a66 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -867,12 +867,26 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const { return StringAttrs.count(Kind); } +Optional +AttributeSetNode::findEnumAttribute(Attribute::AttrKind Kind) const { + // Do a quick presence check. + if (!hasAttribute(Kind)) + return None; + + // Attributes in a set are sorted by enum value, followed by string + // attributes. Binary search the one we want. + const Attribute *I = + std::lower_bound(begin(), end() - StringAttrs.size(), Kind, + [](Attribute A, Attribute::AttrKind Kind) { + return A.getKindAsEnum() < Kind; + }); + assert(I != end() && I->hasAttribute(Kind) && "Presence check failed?"); + return *I; +} + Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { - if (hasAttribute(Kind)) { - for (const auto &I : *this) - if (I.hasAttribute(Kind)) - return I; - } + if (auto A = findEnumAttribute(Kind)) + return *A; return {}; } @@ -881,45 +895,39 @@ Attribute AttributeSetNode::getAttribute(StringRef Kind) const { } MaybeAlign AttributeSetNode::getAlignment() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::Alignment)) - return I.getAlignment(); + if (auto A = findEnumAttribute(Attribute::Alignment)) + return A->getAlignment(); return None; } MaybeAlign AttributeSetNode::getStackAlignment() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::StackAlignment)) - return I.getStackAlignment(); + if (auto A = findEnumAttribute(Attribute::StackAlignment)) + return A->getStackAlignment(); return None; } Type *AttributeSetNode::getByValType() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::ByVal)) - return I.getValueAsType(); + if (auto A = findEnumAttribute(Attribute::ByVal)) + return A->getValueAsType(); return 0; } uint64_t AttributeSetNode::getDereferenceableBytes() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::Dereferenceable)) - return I.getDereferenceableBytes(); + if (auto A = findEnumAttribute(Attribute::Dereferenceable)) + return A->getDereferenceableBytes(); return 0; } uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::DereferenceableOrNull)) - return I.getDereferenceableOrNullBytes(); + if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull)) + return A->getDereferenceableOrNullBytes(); return 0; } std::pair> AttributeSetNode::getAllocSizeArgs() const { - for (const auto &I : *this) - if (I.hasAttribute(Attribute::AllocSize)) - return I.getAllocSizeArgs(); + if (auto A = findEnumAttribute(Attribute::AllocSize)) + return A->getAllocSizeArgs(); return std::make_pair(0, 0); }