AttributeSetImpl: Summarize existing function attributes in a bitset.
authorMatthias Braun <matze@braunis.de>
Fri, 29 Jan 2016 22:25:19 +0000 (22:25 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 29 Jan 2016 22:25:19 +0000 (22:25 +0000)
The majority of attribute queries checks for the existence of an enum
attribute in the FunctionIndex slot. We only have 48 of those and can
therefore summarize them in an uint64_t bitset which measurably improves
compile time.

Differential Revision: http://reviews.llvm.org/D16618

llvm-svn: 259252

llvm/include/llvm/IR/Attributes.h
llvm/include/llvm/IR/Function.h
llvm/lib/IR/AttributeImpl.h
llvm/lib/IR/Attributes.cpp

index a1af1fd..8b17862 100644 (file)
@@ -292,6 +292,10 @@ public:
   /// \brief Return true if attribute exists at the given index.
   bool hasAttributes(unsigned Index) const;
 
+  /// \brief Equivalent to hasAttribute(AttributeSet::FunctionIndex, Kind) but
+  /// may be faster.
+  bool hasFnAttribute(Attribute::AttrKind Kind) const;
+
   /// \brief Return true if the specified attribute is set for at least one
   /// parameter or for the return value.
   bool hasAttrSomewhere(Attribute::AttrKind Attr) const;
index fae7b39..7575808 100644 (file)
@@ -199,7 +199,7 @@ public:
 
   /// @brief Return true if the function has the attribute.
   bool hasFnAttribute(Attribute::AttrKind Kind) const {
-    return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
+    return AttributeSets.hasFnAttribute(Kind);
   }
   bool hasFnAttribute(StringRef Kind) const {
     return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind);
@@ -207,6 +207,8 @@ public:
 
   /// @brief Return the attribute for the given attribute kind.
   Attribute getFnAttribute(Attribute::AttrKind Kind) const {
+    if (!hasFnAttribute(Kind))
+      return Attribute();
     return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind);
   }
   Attribute getFnAttribute(StringRef Kind) const {
@@ -215,6 +217,8 @@ public:
 
   /// \brief Return the stack alignment for the function.
   unsigned getFnStackAlignment() const {
+    if (!hasFnAttribute(Attribute::StackAlignment))
+      return 0;
     return AttributeSets.getStackAlignment(AttributeSet::FunctionIndex);
   }
 
index 59d09c3..3d295e6 100644 (file)
@@ -214,6 +214,11 @@ class AttributeSetImpl final
 private:
   LLVMContext &Context;
   unsigned NumAttrs; ///< Number of entries in this set.
+  /// Bitset with a bit for each available attribute Attribute::AttrKind.
+  uint64_t AvailableFunctionAttrs;
+  static_assert(Attribute::EndAttrKinds
+                <= sizeof(AvailableFunctionAttrs)*CHAR_BIT,
+                "Too many attributes");
 
   // Helper fn for TrailingObjects class.
   size_t numTrailingObjects(OverloadToken<IndexAttrPair>) { return NumAttrs; }
@@ -229,7 +234,7 @@ private:
 public:
   AttributeSetImpl(LLVMContext &C,
                    ArrayRef<std::pair<unsigned, AttributeSetNode *> > Attrs)
-      : Context(C), NumAttrs(Attrs.size()) {
+      : Context(C), NumAttrs(Attrs.size()), AvailableFunctionAttrs(0) {
 
 #ifndef NDEBUG
     if (Attrs.size() >= 2) {
@@ -242,6 +247,21 @@ public:
 #endif
     // There's memory after the node where we can store the entries in.
     std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<IndexAttrPair>());
+
+    // Initialize AvailableFunctionAttrs summary bitset.
+    if (NumAttrs > 0) {
+      static_assert(AttributeSet::FunctionIndex == ~0u,
+                    "FunctionIndex should be biggest possible index");
+      const std::pair<unsigned, AttributeSetNode *> &Last = Attrs.back();
+      if (Last.first == AttributeSet::FunctionIndex) {
+        const AttributeSetNode *Node = Last.second;
+        for (AttributeSetNode::iterator I = Node->begin(), E = Node->end();
+             I != E; ++I) {
+          if (!I->isStringAttribute())
+            AvailableFunctionAttrs |= ((uint64_t)1) << I->getKindAsEnum();
+        }
+      }
+    }
   }
 
   /// \brief Get the context that created this AttributeSetImpl.
@@ -271,6 +291,12 @@ public:
     return getNode(Slot)->second;
   }
 
+  /// \brief Return true if the AttributeSetNode for the FunctionIndex has an
+  /// enum attribute of the given kind.
+  bool hasFnAttribute(Attribute::AttrKind Kind) const {
+    return AvailableFunctionAttrs & ((uint64_t)1) << Kind;
+  }
+
   typedef AttributeSetNode::iterator iterator;
   iterator begin(unsigned Slot) const { return getSlotNode(Slot)->begin(); }
   iterator end(unsigned Slot) const { return getSlotNode(Slot)->end(); }
index af5fe85..f9d98eb 100644 (file)
@@ -999,6 +999,10 @@ bool AttributeSet::hasAttributes(unsigned Index) const {
   return ASN && ASN->hasAttributes();
 }
 
+bool AttributeSet::hasFnAttribute(Attribute::AttrKind Kind) const {
+  return pImpl && pImpl->hasFnAttribute(Kind);
+}
+
 bool AttributeSet::hasAttrSomewhere(Attribute::AttrKind Attr) const {
   if (!pImpl) return false;