aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2022-01-15 10:05:22 +0100
committerNikita Popov <npopov@redhat.com>2022-01-19 12:29:04 +0100
commit42a68215a1291981d0f7d32c397eb64fd1ff0b11 (patch)
tree0454d6093fc3fa1fbc739d649c6bff47b56640bb /llvm/lib/IR/Attributes.cpp
parentd8bff13a8a681ea8af34556f5b00409389dc64d5 (diff)
downloadllvm-42a68215a1291981d0f7d32c397eb64fd1ff0b11.zip
llvm-42a68215a1291981d0f7d32c397eb64fd1ff0b11.tar.gz
llvm-42a68215a1291981d0f7d32c397eb64fd1ff0b11.tar.bz2
[AttrBuilder] Change storage to sorted vector (NFC)
This follows up on the work in D116599, which changed AttrBuilder to store string attributes as SmallVector<Attribute>. This patch changes the implementation to store *all* attributes as a sorted vector. This both makes the implementation simpler and improves compile-time. We get a -0.5% geomean compile-time improvement on CTMark at O0. Differential Revision: https://reviews.llvm.org/D117558
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp208
1 files changed, 77 insertions, 131 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 6220a39..c92baca 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -815,28 +815,7 @@ AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
}
AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
- // Add target-independent attributes.
- SmallVector<Attribute, 8> Attrs;
- for (Attribute::AttrKind Kind = Attribute::None;
- Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
- if (!B.contains(Kind))
- continue;
-
- Attribute Attr;
- if (Attribute::isTypeAttrKind(Kind))
- Attr = Attribute::get(C, Kind, B.getTypeAttr(Kind));
- else if (Attribute::isIntAttrKind(Kind))
- Attr = Attribute::get(C, Kind, B.getRawIntAttr(Kind));
- else
- Attr = Attribute::get(C, Kind);
- Attrs.push_back(Attr);
- }
-
- // Add target-dependent (string) attributes.
- for (const auto &TDA : B.td_attrs())
- Attrs.push_back(TDA);
-
- return getSorted(C, Attrs);
+ return getSorted(C, B.attrs());
}
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
@@ -1538,98 +1517,92 @@ LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
//===----------------------------------------------------------------------===//
AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
- for (const auto &A : AS)
- addAttribute(A);
+ append_range(Attrs, AS);
+ assert(is_sorted(Attrs) && "AttributeSet should be sorted");
}
-void AttrBuilder::clear() {
- Attrs.reset();
- TargetDepAttrs.clear();
- IntAttrs = {};
- TypeAttrs = {};
-}
-
-Optional<unsigned>
-AttrBuilder::kindToIntIndex(Attribute::AttrKind Kind) const {
- if (Attribute::isIntAttrKind(Kind))
- return Kind - Attribute::FirstIntAttr;
- return None;
-}
-
-Optional<unsigned>
-AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const {
- if (Attribute::isTypeAttrKind(Kind))
- return Kind - Attribute::FirstTypeAttr;
- return None;
-}
+void AttrBuilder::clear() { Attrs.clear(); }
-struct StringAttributeComparator {
+/// Attribute comparator that only compares attribute keys. Enum attributes are
+/// sorted before string attributes.
+struct AttributeComparator {
bool operator()(Attribute A0, Attribute A1) const {
- return A0.getKindAsString() < A1.getKindAsString();
+ bool A0IsString = A0.isStringAttribute();
+ bool A1IsString = A1.isStringAttribute();
+ if (A0IsString) {
+ if (A1IsString)
+ return A0.getKindAsString() < A1.getKindAsString();
+ else
+ return false;
+ }
+ if (A1IsString)
+ return true;
+ return A0.getKindAsEnum() < A1.getKindAsEnum();
+ }
+ bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
+ if (A0.isStringAttribute())
+ return false;
+ return A0.getKindAsEnum() < Kind;
}
bool operator()(Attribute A0, StringRef Kind) const {
- return A0.getKindAsString() < Kind;
+ if (A0.isStringAttribute())
+ return A0.getKindAsString() < Kind;
+ return true;
}
};
-AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
- if (Attr.isStringAttribute()) {
- auto It = lower_bound(TargetDepAttrs, Attr, StringAttributeComparator());
- if (It != TargetDepAttrs.end() && It->hasAttribute(Attr.getKindAsString()))
- std::swap(*It, Attr);
- else
- TargetDepAttrs.insert(It, Attr);
- return *this;
- }
-
- Attribute::AttrKind Kind = Attr.getKindAsEnum();
- Attrs[Kind] = true;
+template <typename K>
+static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
+ Attribute Attr) {
+ auto It = lower_bound(Attrs, Kind, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(Kind))
+ std::swap(*It, Attr);
+ else
+ Attrs.insert(It, Attr);
+}
- if (Optional<unsigned> TypeIndex = kindToTypeIndex(Kind))
- TypeAttrs[*TypeIndex] = Attr.getValueAsType();
- else if (Optional<unsigned> IntIndex = kindToIntIndex(Kind))
- IntAttrs[*IntIndex] = Attr.getValueAsInt();
+AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
+ if (Attr.isStringAttribute())
+ addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
+ else
+ addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
+ return *this;
+}
+AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
+ addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
return *this;
}
AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
- return addAttribute(Attribute::get(Ctx, A, V));
+ addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
+ return *this;
}
AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
- Attrs[Val] = false;
-
- if (Optional<unsigned> TypeIndex = kindToTypeIndex(Val))
- TypeAttrs[*TypeIndex] = nullptr;
- else if (Optional<unsigned> IntIndex = kindToIntIndex(Val))
- IntAttrs[*IntIndex] = 0;
-
+ auto It = lower_bound(Attrs, Val, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(Val))
+ Attrs.erase(It);
return *this;
}
AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
- auto It = lower_bound(TargetDepAttrs, A, StringAttributeComparator());
- if (It != TargetDepAttrs.end() && It->hasAttribute(A))
- TargetDepAttrs.erase(It);
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
+ Attrs.erase(It);
return *this;
}
uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
- Optional<unsigned> IntIndex = kindToIntIndex(Kind);
- assert(IntIndex && "Not an int attribute");
- return IntAttrs[*IntIndex];
+ assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
+ Attribute A = getAttribute(Kind);
+ return A.isValid() ? A.getValueAsInt() : 0;
}
AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
uint64_t Value) {
- Optional<unsigned> IntIndex = kindToIntIndex(Kind);
- assert(IntIndex && "Not an int attribute");
- assert(Value && "Value cannot be zero");
- Attrs[Kind] = true;
- IntAttrs[*IntIndex] = Value;
- return *this;
+ return addAttribute(Attribute::get(Ctx, Kind, Value));
}
std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
@@ -1699,17 +1672,13 @@ AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
}
Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
- Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
- assert(TypeIndex && "Not a type attribute");
- return TypeAttrs[*TypeIndex];
+ assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
+ Attribute A = getAttribute(Kind);
+ return A.isValid() ? A.getValueAsType() : nullptr;
}
AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
- Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
- assert(TypeIndex && "Not a type attribute");
- Attrs[Kind] = true;
- TypeAttrs[*TypeIndex] = Ty;
- return *this;
+ return addAttribute(Attribute::get(Ctx, Kind, Ty));
}
AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
@@ -1733,65 +1702,43 @@ AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
}
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
- for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index)
- if (B.IntAttrs[Index])
- IntAttrs[Index] = B.IntAttrs[Index];
-
- for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
- if (B.TypeAttrs[Index])
- TypeAttrs[Index] = B.TypeAttrs[Index];
-
- Attrs |= B.Attrs;
-
- // TODO: could merge both lists in one loop
- for (const auto &I : B.td_attrs())
+ // TODO: Could make this O(n) as we're merging two sorted lists.
+ for (const auto &I : B.attrs())
addAttribute(I);
return *this;
}
AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
- for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index)
- if (AM.contains((Attribute::AttrKind)Index))
- IntAttrs[Index] = 0;
-
- for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
- if (AM.contains((Attribute::AttrKind)Index))
- TypeAttrs[Index] = nullptr;
-
- Attrs &= ~AM.attrs();
-
- erase_if(TargetDepAttrs,
- [&AM](Attribute A) { return AM.contains(A.getKindAsString()); });
-
+ erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
return *this;
}
bool AttrBuilder::overlaps(const AttributeMask &AM) const {
- // First check if any of the target independent attributes overlap.
- if ((Attrs & AM.attrs()).any())
- return true;
+ return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
+}
- // Then check if any target dependent ones do.
- for (const auto &I : td_attrs())
- if (AM.contains(I.getKindAsString()))
- return true;
- return false;
+Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
+ assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
+ return *It;
+ return {};
}
Attribute AttrBuilder::getAttribute(StringRef A) const {
- auto It = lower_bound(TargetDepAttrs, A, StringAttributeComparator());
- if (It != TargetDepAttrs.end() && It->hasAttribute(A))
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
return *It;
return {};
}
-bool AttrBuilder::contains(StringRef A) const {
+bool AttrBuilder::contains(Attribute::AttrKind A) const {
return getAttribute(A).isValid();
}
-bool AttrBuilder::hasAttributes() const {
- return !Attrs.none() || !TargetDepAttrs.empty();
+bool AttrBuilder::contains(StringRef A) const {
+ return getAttribute(A).isValid();
}
bool AttrBuilder::hasAlignmentAttr() const {
@@ -1799,8 +1746,7 @@ bool AttrBuilder::hasAlignmentAttr() const {
}
bool AttrBuilder::operator==(const AttrBuilder &B) const {
- return Attrs == B.Attrs && IntAttrs == B.IntAttrs &&
- TypeAttrs == B.TypeAttrs && TargetDepAttrs == B.TargetDepAttrs;
+ return Attrs == B.Attrs;
}
//===----------------------------------------------------------------------===//