[llvm] r258774 - Use binary search for intrinsic ID lookups

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 25 18:06:41 PST 2016


Author: rnk
Date: Mon Jan 25 20:06:41 2016
New Revision: 258774

URL: http://llvm.org/viewvc/llvm-project?rev=258774&view=rev
Log:
Use binary search for intrinsic ID lookups

This improves compile time of Function.cpp from 57s to 37s for me
locally.  Intrinsic IDs are cached on the Function object, so this
shouldn't regress performance.

Modified:
    llvm/trunk/lib/IR/Function.cpp

Modified: llvm/trunk/lib/IR/Function.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Function.cpp?rev=258774&r1=258773&r2=258774&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Function.cpp (original)
+++ llvm/trunk/lib/IR/Function.cpp Mon Jan 25 20:06:41 2016
@@ -406,17 +406,69 @@ void Function::copyAttributesFrom(const
     setPrologueData(SrcF->getPrologueData());
 }
 
+/// Table of string intrinsic names indexed by enum value.
+static const char * const IntrinsicNameTable[] = {
+  "not_intrinsic",
+#define GET_INTRINSIC_NAME_TABLE
+#include "llvm/IR/Intrinsics.gen"
+#undef GET_INTRINSIC_NAME_TABLE
+};
+
+static int lookupLLVMIntrinsicByName(ArrayRef<const char *> NameTable,
+                                     StringRef Name) {
+  // Do a binary search over the table of intrinsic names.
+  const char *const *NameEntry =
+      std::lower_bound(NameTable.begin(), NameTable.end(), Name.data(),
+                       [](const char *LHS, const char *RHS) {
+                         // Don't compare the first 5 characters, they are
+                         // always "llvm.".
+                         return strcmp(LHS + 5, RHS + 5) < 0;
+                       });
+  unsigned Idx = NameEntry - NameTable.begin();
+
+  // Check if this is a direct match.
+  if (Idx < NameTable.size() && strcmp(Name.data(), NameTable[Idx]) == 0)
+    return Idx;
+
+  // Otherwise, back up one entry to look for a prefix of Name where the next
+  // character in Name is a dot.
+  if (Idx == 0)
+    return -1;
+  --Idx;
+  bool CheckPrefixes = true;
+  while (CheckPrefixes) {
+    StringRef FoundName = NameTable[Idx];
+    if (Name.startswith(FoundName) && Name[FoundName.size()] == '.')
+      return Idx;
+    if (Idx == 0)
+      return -1;
+    --Idx;
+    // We have to keep scanning backwards until the previous entry is not a
+    // prefix of the current entry. Consider a key of llvm.foo.f64 and a table
+    // of llvm.foo and llvm.foo.bar.
+    CheckPrefixes = FoundName.startswith(NameTable[Idx]);
+  }
+
+  return -1;
+}
+
 /// \brief This does the actual lookup of an intrinsic ID which
 /// matches the given function name.
 static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
-  unsigned Len = ValName->getKeyLength();
-  const char *Name = ValName->getKeyData();
-
-#define GET_FUNCTION_RECOGNIZER
-#include "llvm/IR/Intrinsics.gen"
-#undef GET_FUNCTION_RECOGNIZER
+  StringRef Name = ValName->getKey();
+  assert(Name.data()[Name.size()] == '\0' && "non-null terminated ValueName");
 
-  return Intrinsic::not_intrinsic;
+  ArrayRef<const char *> NameTable(&IntrinsicNameTable[1],
+                                   std::end(IntrinsicNameTable));
+  int Idx = lookupLLVMIntrinsicByName(NameTable, Name);
+  Intrinsic::ID ID = static_cast<Intrinsic::ID>(Idx + 1);
+  if (ID == Intrinsic::not_intrinsic)
+    return ID;
+
+  // If the intrinsic is not overloaded, require an exact match. If it is
+  // overloaded, require a prefix match.
+  bool IsPrefixMatch = Name.size() > strlen(NameTable[Idx]);
+  return IsPrefixMatch == isOverloaded(ID) ? ID : Intrinsic::not_intrinsic;
 }
 
 void Function::recalculateIntrinsicID() {
@@ -471,15 +523,9 @@ static std::string getMangledTypeStr(Typ
 
 std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
   assert(id < num_intrinsics && "Invalid intrinsic ID!");
-  static const char * const Table[] = {
-    "not_intrinsic",
-#define GET_INTRINSIC_NAME_TABLE
-#include "llvm/IR/Intrinsics.gen"
-#undef GET_INTRINSIC_NAME_TABLE
-  };
   if (Tys.empty())
-    return Table[id];
-  std::string Result(Table[id]);
+    return IntrinsicNameTable[id];
+  std::string Result(IntrinsicNameTable[id]);
   for (unsigned i = 0; i < Tys.size(); ++i) {
     Result += "." + getMangledTypeStr(Tys[i]);
   }




More information about the llvm-commits mailing list