[llvm] [IR][Attribute] Add support for intersecting AttributeLists; NFC (PR #109719)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 12:49:26 PDT 2024
================
@@ -903,6 +956,112 @@ AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
return get(C, B);
}
+std::optional<AttributeSet>
+AttributeSet::intersectWith(LLVMContext &C, AttributeSet Other) const {
+ if (*this == Other)
+ return *this;
+
+ AttrBuilder Intersected(C);
+ // Iterate over both attr sets at once.
+ auto ItBegin0 = begin();
+ auto ItEnd0 = end();
+ auto ItBegin1 = Other.begin();
+ auto ItEnd1 = Other.end();
+
+ while (ItBegin0 != ItEnd0 || ItBegin1 != ItEnd1) {
+ std::optional<Attribute> Attr0, Attr1;
+ if (ItBegin1 == ItEnd1)
+ Attr0 = *ItBegin0++;
+ else if (ItBegin0 == ItEnd0)
+ Attr1 = *ItBegin1++;
+ else {
+ int Cmp = ItBegin0->cmpKind(*ItBegin1);
+ if (Cmp == 0) {
+ Attr0 = *ItBegin0++;
+ Attr1 = *ItBegin1++;
+ } else if (Cmp < 0)
+ Attr0 = *ItBegin0++;
+ else
+ Attr1 = *ItBegin1++;
+ }
+ Attribute Attr = Attr0 ? *Attr0 : *Attr1;
+ auto IntersectEq = [&]() {
+ if (!Attr0 || !Attr1)
+ return false;
+ if (*Attr0 != *Attr1)
+ return false;
+ Intersected.addAttribute(Attr);
+ return true;
+ };
+
+ if (!Attr.hasKindAsEnum()) {
+ if (!IntersectEq())
+ return std::nullopt;
+ continue;
+ }
+
+ Attribute::AttrKind Kind = Attr.getKindAsEnum();
+ bool BothValid = Attr0 && Attr1 && Attr0->isValid() && Attr1->isValid();
+ // Attribute we can intersect with "and"
+ if (Attribute::intersectWithAnd(Kind)) {
+ assert(Attribute::isEnumAttrKind(Kind) &&
+ "Invalid attr type of intersectAnd");
+ if (BothValid)
+ Intersected.addAttribute(Kind);
+ continue;
+ }
+
+ // Attribute we can intersect with "min"
+ if (Attribute::intersectWithMin(Kind)) {
+ assert(Attribute::isIntAttrKind(Kind) &&
+ "Invalid attr type of intersectMin");
+ if (BothValid) {
+ uint64_t NewVal =
+ std::min(Attr0->getValueAsInt(), Attr1->getValueAsInt());
+ Intersected.addRawIntAttr(Kind, NewVal);
+ }
+ continue;
+ }
+ // Attribute we can intersect but need a custom rule for.
+ if (Attribute::intersectWithCustom(Kind)) {
+ if (BothValid) {
+ switch (Kind) {
+ case Attribute::Alignment:
+ Intersected.addAlignmentAttr(
+ std::min(Attr0->getAlignment().valueOrOne(),
+ Attr1->getAlignment().valueOrOne()));
----------------
nikic wrote:
Alignment is a bit of a special case. If we have *both* byval and align, then it's not legal to change align to a different value.
(We should really split align on byval into two attributes, the current overloaded meaning is confusing.)
https://github.com/llvm/llvm-project/pull/109719
More information about the llvm-commits
mailing list