[PATCH] D81867: [IR] Store attributes that are available "somewhere" (NFC)

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 15 13:14:18 PDT 2020


nikic created this revision.
nikic added reviewers: bkramer, rnk.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.

I noticed that for some benchmarks we spend quite a bit of time inside `AttributeList::hasAttrSomewhere()`, mainly when checking for the `returned` attribute. Most of the time the attribute will not be present, in which case this function has to walk through the whole attribute list and check for the attribute at each index.

This patch proposes to add a cache of all "available somewhere" attributes inside AttributeListImpl. This makes the structure 12 bytes larger, but I don't think that's problematic, as attribute lists are uniqued. Compile-time <https://llvm-compile-time-tracker.com/compare.php?from=5184857c62c5be5ed5d089efef09020236a45ad5&to=0d1c415b035acbc9947f8106129454e7a18ca831&stat=instructions> improves by 0.4% on average, but >1% for sqlite.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81867

Files:
  llvm/lib/IR/AttributeImpl.h
  llvm/lib/IR/Attributes.cpp


Index: llvm/lib/IR/Attributes.cpp
===================================================================
--- llvm/lib/IR/Attributes.cpp
+++ llvm/lib/IR/Attributes.cpp
@@ -979,13 +979,18 @@
   // There's memory after the node where we can store the entries in.
   llvm::copy(Sets, getTrailingObjects<AttributeSet>());
 
-  // Initialize AvailableFunctionAttrs summary bitset.
+  // Initialize AvailableFunctionAttrs and AvailableSomewhereAttrs
+  // summary bitsets.
   static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
                 "function should be stored in slot 0");
-  for (const auto &I : Sets[0]) {
+  for (const auto &I : Sets[0])
     if (!I.isStringAttribute())
       AvailableFunctionAttrs.addAttribute(I.getKindAsEnum());
-  }
+
+  for (const auto &Set : Sets)
+    for (const auto &I : Set)
+      if (!I.isStringAttribute())
+        AvailableSomewhereAttrs.addAttribute(I.getKindAsEnum());
 }
 
 void AttributeListImpl::Profile(FoldingSetNodeID &ID) const {
@@ -998,6 +1003,24 @@
     ID.AddPointer(Set.SetNode);
 }
 
+bool AttributeListImpl::hasAttrSomewhere(Attribute::AttrKind Kind,
+                                        unsigned *Index) const {
+  if (!AvailableSomewhereAttrs.hasAttribute(Kind))
+    return false;
+
+  if (Index) {
+    for (unsigned I = 0, E = NumAttrSets; I != E; ++I) {
+      if (begin()[I].hasAttribute(Kind)) {
+        *Index = I - 1;
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
+
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 LLVM_DUMP_METHOD void AttributeListImpl::dump() const {
   AttributeList(const_cast<AttributeListImpl *>(this)).dump();
@@ -1403,17 +1426,7 @@
 
 bool AttributeList::hasAttrSomewhere(Attribute::AttrKind Attr,
                                      unsigned *Index) const {
-  if (!pImpl) return false;
-
-  for (unsigned I = index_begin(), E = index_end(); I != E; ++I) {
-    if (hasAttribute(I, Attr)) {
-      if (Index)
-        *Index = I;
-      return true;
-    }
-  }
-
-  return false;
+  return pImpl && pImpl->hasAttrSomewhere(Attr, Index);
 }
 
 Attribute AttributeList::getAttribute(unsigned Index,
Index: llvm/lib/IR/AttributeImpl.h
===================================================================
--- llvm/lib/IR/AttributeImpl.h
+++ llvm/lib/IR/AttributeImpl.h
@@ -282,6 +282,8 @@
   unsigned NumAttrSets; ///< Number of entries in this set.
   /// Available enum function attributes.
   AttributeBitSet AvailableFunctionAttrs;
+  /// Union of enum attributes available at any index.
+  AttributeBitSet AvailableSomewhereAttrs;
 
   // Helper fn for TrailingObjects class.
   size_t numTrailingObjects(OverloadToken<AttributeSet>) { return NumAttrSets; }
@@ -299,6 +301,12 @@
     return AvailableFunctionAttrs.hasAttribute(Kind);
   }
 
+  /// Return true if the specified attribute is set for at least one
+  /// parameter or for the return value. If Index is not nullptr, the index
+  /// of a parameter with the specified attribute is provided.
+  bool hasAttrSomewhere(Attribute::AttrKind Kind,
+                        unsigned *Index = nullptr) const;
+
   using iterator = const AttributeSet *;
 
   iterator begin() const { return getTrailingObjects<AttributeSet>(); }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D81867.270828.patch
Type: text/x-patch
Size: 3215 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200615/4a6d520e/attachment.bin>


More information about the llvm-commits mailing list