[IR] Since AttributeSets are sorted, binary search them.

Not likely to make a big difference, but there's a fair bit of pointer
chasing in large sets.
This commit is contained in:
Benjamin Kramer 2020-04-26 20:03:29 +02:00
parent a3c964a278
commit e3306c56b3
2 changed files with 32 additions and 23 deletions

View File

@ -188,6 +188,7 @@ class AttributeSetNode final
static AttributeSetNode *getSorted(LLVMContext &C,
ArrayRef<Attribute> SortedAttrs);
Optional<Attribute> findEnumAttribute(Attribute::AttrKind Kind) const;
public:
// AttributesSetNode is uniqued, these should not be available.

View File

@ -867,12 +867,26 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const {
return StringAttrs.count(Kind);
}
Optional<Attribute>
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<unsigned, Optional<unsigned>>
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);
}