[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