[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, static AttributeSetNode *getSorted(LLVMContext &C,
ArrayRef<Attribute> SortedAttrs); ArrayRef<Attribute> SortedAttrs);
Optional<Attribute> findEnumAttribute(Attribute::AttrKind Kind) const;
public: public:
// AttributesSetNode is uniqued, these should not be available. // AttributesSetNode is uniqued, these should not be available.

View File

@ -867,12 +867,26 @@ bool AttributeSetNode::hasAttribute(StringRef Kind) const {
return StringAttrs.count(Kind); 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 { Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const {
if (hasAttribute(Kind)) { if (auto A = findEnumAttribute(Kind))
for (const auto &I : *this) return *A;
if (I.hasAttribute(Kind))
return I;
}
return {}; return {};
} }
@ -881,45 +895,39 @@ Attribute AttributeSetNode::getAttribute(StringRef Kind) const {
} }
MaybeAlign AttributeSetNode::getAlignment() const { MaybeAlign AttributeSetNode::getAlignment() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::Alignment))
if (I.hasAttribute(Attribute::Alignment)) return A->getAlignment();
return I.getAlignment();
return None; return None;
} }
MaybeAlign AttributeSetNode::getStackAlignment() const { MaybeAlign AttributeSetNode::getStackAlignment() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::StackAlignment))
if (I.hasAttribute(Attribute::StackAlignment)) return A->getStackAlignment();
return I.getStackAlignment();
return None; return None;
} }
Type *AttributeSetNode::getByValType() const { Type *AttributeSetNode::getByValType() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::ByVal))
if (I.hasAttribute(Attribute::ByVal)) return A->getValueAsType();
return I.getValueAsType();
return 0; return 0;
} }
uint64_t AttributeSetNode::getDereferenceableBytes() const { uint64_t AttributeSetNode::getDereferenceableBytes() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::Dereferenceable))
if (I.hasAttribute(Attribute::Dereferenceable)) return A->getDereferenceableBytes();
return I.getDereferenceableBytes();
return 0; return 0;
} }
uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::DereferenceableOrNull))
if (I.hasAttribute(Attribute::DereferenceableOrNull)) return A->getDereferenceableOrNullBytes();
return I.getDereferenceableOrNullBytes();
return 0; return 0;
} }
std::pair<unsigned, Optional<unsigned>> std::pair<unsigned, Optional<unsigned>>
AttributeSetNode::getAllocSizeArgs() const { AttributeSetNode::getAllocSizeArgs() const {
for (const auto &I : *this) if (auto A = findEnumAttribute(Attribute::AllocSize))
if (I.hasAttribute(Attribute::AllocSize)) return A->getAllocSizeArgs();
return I.getAllocSizeArgs();
return std::make_pair(0, 0); return std::make_pair(0, 0);
} }