[llvm] 3e5d8a1 - Reapply "RuntimeLibcalls: Generate table of libcall name lengths (#153… (#153864)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 15 17:53:56 PDT 2025


Author: Matt Arsenault
Date: 2025-08-16T09:53:50+09:00
New Revision: 3e5d8a1439afb784dee1a12a878fa0a533a6d4c6

URL: https://github.com/llvm/llvm-project/commit/3e5d8a1439afb784dee1a12a878fa0a533a6d4c6
DIFF: https://github.com/llvm/llvm-project/commit/3e5d8a1439afb784dee1a12a878fa0a533a6d4c6.diff

LOG: Reapply "RuntimeLibcalls: Generate table of libcall name lengths (#153… (#153864)

This reverts commit 334e9bf2dd01fbbfe785624c0de477b725cde6f2.

Check if llvm-nm exists before building the benchmark.

Added: 
    llvm/benchmarks/RuntimeLibcalls.cpp
    llvm/unittests/IR/RuntimeLibcallsTest.cpp

Modified: 
    llvm/benchmarks/CMakeLists.txt
    llvm/include/llvm/CodeGen/TargetLowering.h
    llvm/include/llvm/IR/RuntimeLibcalls.h
    llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
    llvm/lib/IR/RuntimeLibcalls.cpp
    llvm/lib/LTO/LTO.cpp
    llvm/lib/Object/IRSymtab.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
    llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp
    llvm/test/TableGen/RuntimeLibcallEmitter.td
    llvm/unittests/IR/CMakeLists.txt
    llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/benchmarks/CMakeLists.txt b/llvm/benchmarks/CMakeLists.txt
index 1078efa55f497..14cccd9c8ed55 100644
--- a/llvm/benchmarks/CMakeLists.txt
+++ b/llvm/benchmarks/CMakeLists.txt
@@ -11,3 +11,24 @@ add_benchmark(FormatVariadicBM FormatVariadicBM.cpp PARTIAL_SOURCES_INTENDED)
 add_benchmark(GetIntrinsicInfoTableEntriesBM GetIntrinsicInfoTableEntriesBM.cpp PARTIAL_SOURCES_INTENDED)
 add_benchmark(SandboxIRBench SandboxIRBench.cpp PARTIAL_SOURCES_INTENDED)
 
+add_benchmark(RuntimeLibcallsBench RuntimeLibcalls.cpp PARTIAL_SOURCES_INTENDED)
+
+
+if(TARGET llvm-nm)
+  # Extract the list of symbols in a random utility as sample data.
+  set(SYMBOL_TEST_DATA_FILE "sample_symbol_list.txt")
+  set(SYMBOL_TEST_DATA_SOURCE_BINARY $<TARGET_FILE:llc>)
+
+  add_custom_command(OUTPUT ${SYMBOL_TEST_DATA_FILE}
+    COMMAND $<TARGET_FILE:llvm-nm> --no-demangle --no-sort
+    --format=just-symbols
+    ${SYMBOL_TEST_DATA_SOURCE_BINARY} > ${SYMBOL_TEST_DATA_FILE}
+    DEPENDS "$<TARGET_FILE:llvm-nm>" "$<TARGET_FILE:llc>")
+
+  add_custom_target(generate-runtime-libcalls-sample-symbol-list
+                    DEPENDS ${SYMBOL_TEST_DATA_FILE})
+
+  add_dependencies(RuntimeLibcallsBench generate-runtime-libcalls-sample-symbol-list)
+  target_compile_definitions(RuntimeLibcallsBench PRIVATE
+    -DSYMBOL_TEST_DATA_FILE="${CMAKE_CURRENT_BINARY_DIR}/${SYMBOL_TEST_DATA_FILE}")
+endif()

diff  --git a/llvm/benchmarks/RuntimeLibcalls.cpp b/llvm/benchmarks/RuntimeLibcalls.cpp
new file mode 100644
index 0000000000000..9ac77bb74a3df
--- /dev/null
+++ b/llvm/benchmarks/RuntimeLibcalls.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/RuntimeLibcalls.h"
+#include "benchmark/benchmark.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TargetParser/Triple.h"
+#include <random>
+#include <string>
+using namespace llvm;
+
+static constexpr unsigned MaxFuncNameSize = 53;
+
+static std::vector<StringRef> getLibcallNameStringRefs() {
+  std::vector<StringRef> Names(RTLIB::NumLibcallImpls);
+  // Keep the strlens on the StringRef construction out of the benchmark loop.
+  for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls())
+    Names[LC] = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LC);
+
+  return Names;
+}
+
+static std::vector<std::string> getRandomFuncNames() {
+  std::mt19937_64 Rng;
+  std::uniform_int_distribution<> StringLengthDistribution(1, MaxFuncNameSize);
+  std::uniform_int_distribution<> CharDistribution(1, 255);
+  int NumTestFuncs = 1 << 10;
+  std::vector<std::string> TestFuncNames(NumTestFuncs);
+
+  for (std::string &TestFuncName : TestFuncNames) {
+    for (int I = 0, E = StringLengthDistribution(Rng); I != E; ++I)
+      TestFuncName += static_cast<char>(CharDistribution(Rng));
+  }
+
+  return TestFuncNames;
+}
+
+#ifdef SYMBOL_TEST_DATA_FILE
+static std::vector<std::string> readSymbolsFromFile(StringRef InputFile) {
+  auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFile, /*IsText=*/true);
+  if (!BufOrError) {
+    reportFatalUsageError("failed to open \'" + Twine(InputFile) +
+                          "\': " + BufOrError.getError().message());
+  }
+
+  // Hackily figure out if there's a prefix on the symbol names - llvm-nm
+  // appears to not have a flag to skip this.
+  llvm::Triple HostTriple(LLVM_HOST_TRIPLE);
+  std::string DummyDatalayout = "e";
+  DummyDatalayout += DataLayout::getManglingComponent(HostTriple);
+
+  DataLayout DL(DummyDatalayout);
+  char GlobalPrefix = DL.getGlobalPrefix();
+
+  std::vector<std::string> Lines;
+  for (line_iterator LineIt(**BufOrError, /*SkipBlanks=*/true);
+       !LineIt.is_at_eof(); ++LineIt) {
+    StringRef SymbolName = *LineIt;
+    SymbolName.consume_front(StringRef(&GlobalPrefix, 1));
+
+    Lines.push_back(SymbolName.str());
+  }
+  return Lines;
+}
+#endif
+
+static void BM_LookupRuntimeLibcallByNameKnownCalls(benchmark::State &State) {
+  std::vector<StringRef> Names = getLibcallNameStringRefs();
+
+  for (auto _ : State) {
+    for (StringRef Name : Names) {
+      benchmark::DoNotOptimize(
+          RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name).empty());
+    }
+  }
+}
+
+static void BM_LookupRuntimeLibcallByNameRandomCalls(benchmark::State &State) {
+  std::vector<std::string> TestFuncNames = getRandomFuncNames();
+
+  for (auto _ : State) {
+    for (const std::string &Name : TestFuncNames) {
+      benchmark::DoNotOptimize(
+          RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name))
+              .empty());
+    }
+  }
+}
+
+#ifdef SYMBOL_TEST_DATA_FILE
+// This isn't fully representative, it doesn't include any anonymous functions.
+// nm -n --no-demangle --format=just-symbols sample-binary > sample.txt
+static void BM_LookupRuntimeLibcallByNameSampleData(benchmark::State &State) {
+  std::vector<std::string> TestFuncNames =
+      readSymbolsFromFile(SYMBOL_TEST_DATA_FILE);
+  for (auto _ : State) {
+    for (const std::string &Name : TestFuncNames) {
+      benchmark::DoNotOptimize(
+          RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name))
+              .empty());
+    }
+  }
+}
+#endif
+
+BENCHMARK(BM_LookupRuntimeLibcallByNameKnownCalls);
+BENCHMARK(BM_LookupRuntimeLibcallByNameRandomCalls);
+
+#ifdef SYMBOL_TEST_DATA_FILE
+BENCHMARK(BM_LookupRuntimeLibcallByNameSampleData);
+#endif
+
+BENCHMARK_MAIN();

diff  --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index ec3104799bfb5..272d7dd5f45e8 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -3557,15 +3557,19 @@ class LLVM_ABI TargetLoweringBase {
 
   /// Get the libcall routine name for the specified libcall.
   const char *getLibcallName(RTLIB::Libcall Call) const {
-    return Libcalls.getLibcallName(Call);
+    // FIXME: Return StringRef
+    return Libcalls.getLibcallName(Call).data();
   }
 
   /// Get the libcall routine name for the specified libcall implementation
-  const char *getLibcallImplName(RTLIB::LibcallImpl Call) const {
-    return Libcalls.getLibcallImplName(Call);
+  static StringRef getLibcallImplName(RTLIB::LibcallImpl Call) {
+    return RTLIB::RuntimeLibcallsInfo::getLibcallImplName(Call);
   }
 
-  const char *getMemcpyName() const { return Libcalls.getMemcpyName(); }
+  const char *getMemcpyName() const {
+    // FIXME: Return StringRef
+    return Libcalls.getMemcpyName().data();
+  }
 
   /// Get the comparison predicate that's to be used to test the result of the
   /// comparison libcall against zero. This should only be used with

diff  --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 2d1d07c5fd81b..308be543de2bd 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -77,17 +77,17 @@ struct RuntimeLibcallsInfo {
 
   /// Get the libcall routine name for the specified libcall.
   // FIXME: This should be removed. Only LibcallImpl should have a name.
-  const char *getLibcallName(RTLIB::Libcall Call) const {
+  StringRef getLibcallName(RTLIB::Libcall Call) const {
     return getLibcallImplName(LibcallImpls[Call]);
   }
 
   /// Get the libcall routine name for the specified libcall implementation.
-  // FIXME: Change to return StringRef
-  static const char *getLibcallImplName(RTLIB::LibcallImpl CallImpl) {
+  static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl) {
     if (CallImpl == RTLIB::Unsupported)
-      return nullptr;
-    return RuntimeLibcallImplNameTable[RuntimeLibcallNameOffsetTable[CallImpl]]
-        .data();
+      return StringRef();
+    return StringRef(RuntimeLibcallImplNameTable.getCString(
+                         RuntimeLibcallNameOffsetTable[CallImpl]),
+                     RuntimeLibcallNameSizeTable[CallImpl]);
   }
 
   /// Return the lowering's selection of implementation call for \p Call
@@ -119,9 +119,10 @@ struct RuntimeLibcallsInfo {
 
   /// Return a function name compatible with RTLIB::MEMCPY, or nullptr if fully
   /// unsupported.
-  const char *getMemcpyName() const {
-    if (const char *Memcpy = getLibcallName(RTLIB::MEMCPY))
-      return Memcpy;
+  StringRef getMemcpyName() const {
+    RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY);
+    if (Memcpy != RTLIB::Unsupported)
+      return getLibcallImplName(Memcpy);
 
     // Fallback to memmove if memcpy isn't available.
     return getLibcallName(RTLIB::MEMMOVE);
@@ -132,11 +133,41 @@ struct RuntimeLibcallsInfo {
     return ImplToLibcall[Impl];
   }
 
+  /// Check if a function name is a recognized runtime call of any kind. This
+  /// does not consider if this call is available for any current compilation,
+  /// just that it is a known call somewhere. This returns the set of all
+  /// LibcallImpls which match the name; multiple implementations with the same
+  /// name may exist but 
diff er in interpretation based on the target context.
+  ///
+  /// Generated by tablegen.
+  LLVM_ABI static inline iota_range<RTLIB::LibcallImpl>
+  lookupLibcallImplName(StringRef Name){
+  // Inlining the early exit on the string name appears to be worthwhile when
+  // querying a real set of symbols
+#define GET_LOOKUP_LIBCALL_IMPL_NAME_BODY
+#include "llvm/IR/RuntimeLibcalls.inc"
+#undef GET_LOOKUP_LIBCALL_IMPL_NAME_BODY
+  }
+
   /// Check if this is valid libcall for the current module, otherwise
   /// RTLIB::Unsupported.
-  LLVM_ABI RTLIB::LibcallImpl getSupportedLibcallImpl(StringRef FuncName) const;
+  LLVM_ABI RTLIB::LibcallImpl
+      getSupportedLibcallImpl(StringRef FuncName) const {
+    for (RTLIB::LibcallImpl Impl : lookupLibcallImplName(FuncName)) {
+      // FIXME: This should not depend on looking up ImplToLibcall, only the
+      // list of libcalls for the module.
+      RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]];
+      if (Recognized != RTLIB::Unsupported)
+        return Recognized;
+    }
+
+    return RTLIB::Unsupported;
+  }
 
 private:
+  LLVM_ABI static iota_range<RTLIB::LibcallImpl>
+  lookupLibcallImplNameImpl(StringRef Name);
+
   /// Stores the implementation choice for each each libcall.
   RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
       RTLIB::Unsupported};
@@ -153,17 +184,16 @@ struct RuntimeLibcallsInfo {
   LLVM_ABI static const char RuntimeLibcallImplNameTableStorage[];
   LLVM_ABI static const StringTable RuntimeLibcallImplNameTable;
   LLVM_ABI static const uint16_t RuntimeLibcallNameOffsetTable[];
+  LLVM_ABI static const uint8_t RuntimeLibcallNameSizeTable[];
 
   /// Map from a concrete LibcallImpl implementation to its RTLIB::Libcall kind.
   LLVM_ABI static const RTLIB::Libcall ImplToLibcall[RTLIB::NumLibcallImpls];
 
-  /// Check if a function name is a recognized runtime call of any kind. This
-  /// does not consider if this call is available for any current compilation,
-  /// just that it is a known call somewhere. This returns the set of all
-  /// LibcallImpls which match the name; multiple implementations with the same
-  /// name may exist but 
diff er in interpretation based on the target context.
-  LLVM_ABI static iterator_range<ArrayRef<uint16_t>::const_iterator>
-  getRecognizedLibcallImpls(StringRef FuncName);
+  /// Utility function for tablegenerated lookup function. Return a range of
+  /// enum values that apply for the function name at \p NameOffsetEntry with
+  /// the value \p StrOffset.
+  static inline iota_range<RTLIB::LibcallImpl>
+  libcallImplNameHit(uint16_t NameOffsetEntry, uint16_t StrOffset);
 
   static bool darwinHasSinCosStret(const Triple &TT) {
     if (!TT.isOSDarwin())

diff  --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 9fa96e7372961..96c9cde622b45 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -145,7 +145,7 @@ static bool lowerObjCCall(Function &F, RTLIB::LibcallImpl NewFn,
 
   // FIXME: When RuntimeLibcalls is an analysis, check if the function is really
   // supported, and go through RTLIB::Libcall.
-  const char *NewFnName = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(NewFn);
+  StringRef NewFnName = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(NewFn);
 
   // If we haven't already looked up this function, check to see if the
   // program already contains a function with this name.

diff  --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index ac845c4998783..88cb192c08781 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -9,6 +9,7 @@
 #include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/ADT/StringTable.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/xxhash.h"
 #include "llvm/TargetParser/ARMTargetParser.h"
 
 #define DEBUG_TYPE "runtime-libcalls-info"
@@ -18,9 +19,11 @@ using namespace RTLIB;
 
 #define GET_INIT_RUNTIME_LIBCALL_NAMES
 #define GET_SET_TARGET_RUNTIME_LIBCALL_SETS
+#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
 #include "llvm/IR/RuntimeLibcalls.inc"
 #undef GET_INIT_RUNTIME_LIBCALL_NAMES
 #undef GET_SET_TARGET_RUNTIME_LIBCALL_SETS
+#undef DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
 
 /// Set default libcall names. If a target wants to opt-out of a libcall it
 /// should be placed here.
@@ -58,49 +61,23 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
   }
 }
 
-RTLIB::LibcallImpl
-RuntimeLibcallsInfo::getSupportedLibcallImpl(StringRef FuncName) const {
-  const ArrayRef<uint16_t> RuntimeLibcallNameOffsets(
-      RuntimeLibcallNameOffsetTable);
-
-  iterator_range<ArrayRef<uint16_t>::const_iterator> Range =
-      getRecognizedLibcallImpls(FuncName);
-
-  for (auto I = Range.begin(); I != Range.end(); ++I) {
-    RTLIB::LibcallImpl Impl =
-        static_cast<RTLIB::LibcallImpl>(I - RuntimeLibcallNameOffsets.begin());
-
-    // FIXME: This should not depend on looking up ImplToLibcall, only the list
-    // of libcalls for the module.
-    RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]];
-    if (Recognized != RTLIB::Unsupported)
-      return Recognized;
+LLVM_ATTRIBUTE_ALWAYS_INLINE
+iota_range<RTLIB::LibcallImpl>
+RuntimeLibcallsInfo::libcallImplNameHit(uint16_t NameOffsetEntry,
+                                        uint16_t StrOffset) {
+  int NumAliases = 1;
+  for (uint16_t Entry : ArrayRef(RuntimeLibcallNameOffsetTable)
+                            .drop_front(NameOffsetEntry + 1)) {
+    if (Entry != StrOffset)
+      break;
+    ++NumAliases;
   }
 
-  return RTLIB::Unsupported;
-}
-
-iterator_range<ArrayRef<uint16_t>::const_iterator>
-RuntimeLibcallsInfo::getRecognizedLibcallImpls(StringRef FuncName) {
-  StringTable::Iterator It = lower_bound(RuntimeLibcallImplNameTable, FuncName);
-  if (It == RuntimeLibcallImplNameTable.end() || *It != FuncName)
-    return iterator_range(ArrayRef<uint16_t>());
-
-  uint16_t IndexVal = It.offset().value();
-  const ArrayRef<uint16_t> TableRef(RuntimeLibcallNameOffsetTable);
-
-  ArrayRef<uint16_t>::const_iterator E = TableRef.end();
-  ArrayRef<uint16_t>::const_iterator EntriesBegin =
-      std::lower_bound(TableRef.begin(), E, IndexVal);
-  ArrayRef<uint16_t>::const_iterator EntriesEnd = EntriesBegin;
-
-  while (EntriesEnd != E && *EntriesEnd == IndexVal)
-    ++EntriesEnd;
-
-  assert(EntriesBegin != E &&
-         "libcall found in name table but not offset table");
-
-  return make_range(EntriesBegin, EntriesEnd);
+  RTLIB::LibcallImpl ImplStart = static_cast<RTLIB::LibcallImpl>(
+      &RuntimeLibcallNameOffsetTable[NameOffsetEntry] -
+      &RuntimeLibcallNameOffsetTable[0]);
+  return enum_seq(ImplStart,
+                  static_cast<RTLIB::LibcallImpl>(ImplStart + NumAliases));
 }
 
 bool RuntimeLibcallsInfo::isAAPCS_ABI(const Triple &TT, StringRef ABIName) {

diff  --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index 0323b4d433b87..35d24c17bbd93 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -1422,7 +1422,7 @@ SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
 
   for (RTLIB::LibcallImpl Impl : LibcallImpls) {
     if (Impl != RTLIB::Unsupported)
-      LibcallSymbols.push_back(Libcalls.getLibcallImplName(Impl));
+      LibcallSymbols.push_back(Libcalls.getLibcallImplName(Impl).data());
   }
 
   return LibcallSymbols;

diff  --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp
index 0f194953787e6..0043f02107fb8 100644
--- a/llvm/lib/Object/IRSymtab.cpp
+++ b/llvm/lib/Object/IRSymtab.cpp
@@ -46,7 +46,7 @@ static cl::opt<bool> DisableBitcodeVersionUpgrade(
     "disable-bitcode-version-upgrade", cl::Hidden,
     cl::desc("Disable automatic bitcode upgrade for version mismatch"));
 
-static const char *PreservedSymbols[] = {
+static constexpr StringLiteral PreservedSymbols[] = {
     // There are global variables, so put it here instead of in
     // RuntimeLibcalls.td.
     // TODO: Are there similar such variables?
@@ -54,6 +54,10 @@ static const char *PreservedSymbols[] = {
     "__stack_chk_guard",
 };
 
+static bool isPreservedGlobalVarName(StringRef Name) {
+  return PreservedSymbols[0] == Name || PreservedSymbols[1] == Name;
+}
+
 namespace {
 
 const char *getExpectedProducerName() {
@@ -81,12 +85,16 @@ struct Builder {
   // The StringTableBuilder does not create a copy of any strings added to it,
   // so this provides somewhere to store any strings that we create.
   Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
-          BumpPtrAllocator &Alloc)
-      : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc) {}
+          BumpPtrAllocator &Alloc, const Triple &TT)
+      : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
+        Libcalls(TT) {}
 
   DenseMap<const Comdat *, int> ComdatMap;
   Mangler Mang;
-  Triple TT;
+  const Triple &TT;
+
+  // FIXME: This shouldn't be here.
+  RTLIB::RuntimeLibcallsInfo Libcalls;
 
   std::vector<storage::Comdat> Comdats;
   std::vector<storage::Module> Mods;
@@ -98,6 +106,10 @@ struct Builder {
 
   std::vector<storage::Str> DependentLibraries;
 
+  bool isPreservedLibFuncName(StringRef Name) {
+    return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
+  }
+
   void setStr(storage::Str &S, StringRef Value) {
     S.Offset = StrtabBuilder.add(Value);
     S.Size = Value.size();
@@ -213,19 +225,6 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) {
   return P.first->second;
 }
 
-static StringSet<> buildPreservedSymbolsSet(const Triple &TT) {
-  StringSet<> PreservedSymbolSet;
-  PreservedSymbolSet.insert(std::begin(PreservedSymbols),
-                            std::end(PreservedSymbols));
-  // FIXME: Do we need to pass in ABI fields from TargetOptions?
-  RTLIB::RuntimeLibcallsInfo Libcalls(TT);
-  for (RTLIB::LibcallImpl Impl : Libcalls.getLibcallImpls()) {
-    if (Impl != RTLIB::Unsupported)
-      PreservedSymbolSet.insert(Libcalls.getLibcallImplName(Impl));
-  }
-  return PreservedSymbolSet;
-}
-
 Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
                          const SmallPtrSet<GlobalValue *, 4> &Used,
                          ModuleSymbolTable::Symbol Msym) {
@@ -279,13 +278,11 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
     return Error::success();
   }
 
-  setStr(Sym.IRName, GV->getName());
-
-  static const StringSet<> PreservedSymbolsSet =
-      buildPreservedSymbolsSet(GV->getParent()->getTargetTriple());
-  bool IsPreservedSymbol = PreservedSymbolsSet.contains(GV->getName());
+  StringRef GVName = GV->getName();
+  setStr(Sym.IRName, GVName);
 
-  if (Used.count(GV) || IsPreservedSymbol)
+  if (Used.count(GV) || isPreservedLibFuncName(GVName) ||
+      isPreservedGlobalVarName(GVName))
     Sym.Flags |= 1 << storage::Symbol::FB_used;
   if (GV->isThreadLocal())
     Sym.Flags |= 1 << storage::Symbol::FB_tls;
@@ -352,7 +349,6 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
   setStr(Hdr.Producer, kExpectedProducerName);
   setStr(Hdr.TargetTriple, IRMods[0]->getTargetTriple().str());
   setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName());
-  TT = IRMods[0]->getTargetTriple();
 
   for (auto *M : IRMods)
     if (Error Err = addModule(M))
@@ -378,7 +374,8 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
 Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
                       StringTableBuilder &StrtabBuilder,
                       BumpPtrAllocator &Alloc) {
-  return Builder(Symtab, StrtabBuilder, Alloc).build(Mods);
+  const Triple &TT = Mods[0]->getTargetTriple();
+  return Builder(Symtab, StrtabBuilder, Alloc, TT).build(Mods);
 }
 
 // Upgrade a vector of bitcode modules created by an old version of LLVM by

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
index 4548a7520b3b4..45b0e7dc12263 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
@@ -533,8 +533,8 @@ struct StaticLibcallNameMap {
     // 
diff erent libcalls.
     RTLIB::RuntimeLibcallsInfo RTCI(TT);
     for (RTLIB::Libcall LC : RTLIB::libcalls()) {
-      const char *NameLibcall = RTCI.getLibcallName(LC);
-      if (NameLibcall != nullptr &&
+      StringRef NameLibcall = RTCI.getLibcallName(LC);
+      if (!NameLibcall.empty() &&
           getRuntimeLibcallSignatures().Table[LC] != unsupported) {
         assert(!Map.contains(NameLibcall) &&
                "duplicate libcall names in name map");

diff  --git a/llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp b/llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp
index 540039b7d2cbd..0642d51cd2c21 100644
--- a/llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp
+++ b/llvm/lib/Transforms/Utils/DeclareRuntimeLibcalls.cpp
@@ -30,7 +30,7 @@ PreservedAnalyses DeclareRuntimeLibcallsPass::run(Module &M,
     FunctionType *FuncTy =
         FunctionType::get(Type::getVoidTy(Ctx), {}, /*IsVarArgs=*/true);
 
-    const char *FuncName = RTLCI.getLibcallImplName(Impl);
+    StringRef FuncName = RTLCI.getLibcallImplName(Impl);
     M.getOrInsertFunction(FuncName, FuncTy);
   }
 

diff  --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index a2d946f3aa84f..7c62402227f7d 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -137,6 +137,19 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // CHECK-NEXT:   54, // sqrtl
 // CHECK-NEXT:   54, // sqrtl
 // CHECK-NEXT: };
+// CHECK-EMPTY:
+// CHECK-NEXT: const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
+// CHECK-NEXT:   0,
+// CHECK-NEXT:   9,
+// CHECK-NEXT:   9,
+// CHECK-NEXT:   9,
+// CHECK-NEXT:   9,
+// CHECK-NEXT:   5,
+// CHECK-NEXT:   6,
+// CHECK-NEXT:   5,
+// CHECK-NEXT:   5,
+// CHECK-NEXT: };
+// CHECK-EMPTY:
 // CHECK-NEXT: const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::ImplToLibcall[RTLIB::NumLibcallImpls] = {
 // CHECK-NEXT: RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported
 // CHECK-NEXT: RTLIB::MEMCPY, // RTLIB::___memcpy
@@ -149,6 +162,32 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
 // CHECK-NEXT: RTLIB::SQRT_F80, // RTLIB::sqrtl_f80
 // CHECK-NEXT: };
 
+// CHECK: #ifdef GET_LOOKUP_LIBCALL_IMPL_NAME_BODY
+// CHECK-NEXT: size_t Size = Name.size();
+// CHECK-NEXT: if (Size == 0 || Size > 9)
+// CHECK-NEXT:   return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);
+// CHECK-NEXT: return lookupLibcallImplNameImpl(Name);
+// CHECK-NEXT: #endif
+
+// CHECK: #ifdef DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME
+// CHECK-NEXT: static inline uint64_t hash(StringRef Str) {
+// CHECK-NEXT: return static_cast<uint32_t>(xxh3_64bits(Str));
+// CHECK-NEXT: }
+
+// CHECK: iota_range<RTLIB::LibcallImpl> RTLIB::RuntimeLibcallsInfo::lookupLibcallImplNameImpl(StringRef Name) {
+// CHECK: static constexpr uint16_t HashTableNameToEnum[16] = {
+// CHECK: 2, // 0x000000705301b8, ___memset
+// CHECK: 0,
+// CHECK: 6, // 0x0000001417a2af, calloc
+// CHECK: 0,
+// CHECK: };
+
+// CHECK: unsigned Idx = (hash(Name) % 8) * 2;
+// CHECK: for (int I = 0; I != 2; ++I) {
+// CHECK: return libcallImplNameHit(Entry, StrOffset);
+
+// CHECK: return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);
+// CHECK-NEXT: }
 
 // CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) {
 // CHECK-NEXT:  struct LibcallImplPair {

diff  --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index b66eae93f9339..8b7bd3997ea27 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -43,6 +43,7 @@ add_llvm_unittest(IRTests
   PatternMatch.cpp
   ShuffleVectorInstTest.cpp
   StructuralHashTest.cpp
+  RuntimeLibcallsTest.cpp
   TimePassesTest.cpp
   TypesTest.cpp
   UseTest.cpp

diff  --git a/llvm/unittests/IR/RuntimeLibcallsTest.cpp b/llvm/unittests/IR/RuntimeLibcallsTest.cpp
new file mode 100644
index 0000000000000..012316801859c
--- /dev/null
+++ b/llvm/unittests/IR/RuntimeLibcallsTest.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/RuntimeLibcalls.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(RuntimeLibcallsTest, LibcallImplByName) {
+  EXPECT_TRUE(RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("").empty());
+  EXPECT_TRUE(
+      RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("unknown").empty());
+  EXPECT_TRUE(
+      RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("Unsupported").empty());
+  EXPECT_TRUE(
+      RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("unsupported").empty());
+
+  for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls()) {
+    StringRef Name = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LC);
+    EXPECT_TRUE(is_contained(
+        RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name), LC));
+  }
+
+  // Test first libcall name
+  EXPECT_EQ(
+      RTLIB::arm64ec__Unwind_Resume,
+      *RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("#_Unwind_Resume")
+           .begin());
+  // Test longest libcall names
+  EXPECT_EQ(RTLIB::__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes,
+            *RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(
+                 "__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes")
+                 .begin());
+
+  {
+    auto SquirtleSquad =
+        RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("sqrtl");
+    ASSERT_EQ(size(SquirtleSquad), 3);
+    auto I = SquirtleSquad.begin();
+    EXPECT_EQ(*I++, RTLIB::sqrt_f128);
+    EXPECT_EQ(*I++, RTLIB::sqrt_f80);
+    EXPECT_EQ(*I++, RTLIB::sqrt_ppcf128);
+  }
+
+  // Last libcall
+  {
+    auto Truncs = RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName("truncl");
+    ASSERT_EQ(size(Truncs), 3);
+    auto I = Truncs.begin();
+    EXPECT_EQ(*I++, RTLIB::trunc_f128);
+    EXPECT_EQ(*I++, RTLIB::trunc_f80);
+    EXPECT_EQ(*I++, RTLIB::trunc_ppcf128);
+  }
+}
+
+} // namespace

diff  --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 0fc230c4714f0..c305e6323ca9d 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -6,10 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "runtime-libcall-emitter"
+
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/xxhash.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/SetTheory.h"
@@ -215,6 +220,9 @@ class RuntimeLibcallEmitter {
 private:
   void emitGetRuntimeLibcallEnum(raw_ostream &OS) const;
 
+  void emitNameMatchHashTable(raw_ostream &OS,
+                              StringToOffsetTable &OffsetTable) const;
+
   void emitGetInitRuntimeLibcallNames(raw_ostream &OS) const;
 
   void emitSystemRuntimeLibrarySetCalls(raw_ostream &OS) const;
@@ -255,12 +263,9 @@ class RuntimeLibcallEmitter {
       RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,
                                              LibCallImplEnumVal++);
 
-      RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
-
+      const RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
       Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
 
-      // const RuntimeLibcallImpl &LibCallImpl =
-      // RuntimeLibcallImplDefList.back();
       if (LibCallImpl.isDefault()) {
         const RuntimeLibcall *Provides = LibCallImpl.getProvides();
         if (!Provides)
@@ -282,6 +287,13 @@ class RuntimeLibcallEmitter {
   void run(raw_ostream &OS);
 };
 
+/// Helper struct for the name hash table.
+struct LookupEntry {
+  StringRef FuncName;
+  uint64_t Hash = 0;
+  unsigned TableValue = 0;
+};
+
 } // End anonymous namespace.
 
 void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
@@ -295,8 +307,6 @@ void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
     OS << "  " << Name << " = " << LibCall.getEnumVal() << ",\n";
   }
 
-  // TODO: Emit libcall names as string offset table.
-
   OS << "  UNKNOWN_LIBCALL = " << RuntimeLibcallDefList.size()
      << "\n};\n\n"
         "enum LibcallImpl : unsigned short {\n"
@@ -315,8 +325,179 @@ void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
         "#endif\n\n";
 }
 
+// StringMap uses xxh3_64bits, truncated to uint32_t.
+static uint64_t hash(StringRef Str) {
+  return static_cast<uint32_t>(xxh3_64bits(Str));
+}
+
+static void emitHashFunction(raw_ostream &OS) {
+  OS << "static inline uint64_t hash(StringRef Str) {\n"
+        "  return static_cast<uint32_t>(xxh3_64bits(Str));\n"
+        "}\n\n";
+}
+
+/// Return the table size, maximum number of collisions for the set of hashes
+static std::pair<int, int>
+computePerfectHashParameters(ArrayRef<uint64_t> Hashes) {
+  const int SizeOverhead = 10;
+  const int NumHashes = Hashes.size();
+
+  // Index derived from hash -> number of collisions.
+  DenseMap<uint64_t, int> Table;
+
+  for (int MaxCollisions = 1;; ++MaxCollisions) {
+    for (int N = NumHashes; N < SizeOverhead * NumHashes; ++N) {
+      Table.clear();
+
+      bool NeedResize = false;
+      for (uint64_t H : Hashes) {
+        uint64_t Idx = H % static_cast<uint64_t>(N);
+        if (++Table[Idx] > MaxCollisions) {
+          // Need to resize the final table if we increased the collision count.
+          NeedResize = true;
+          break;
+        }
+      }
+
+      if (!NeedResize)
+        return {N, MaxCollisions};
+    }
+  }
+}
+
+static std::vector<LookupEntry>
+constructPerfectHashTable(ArrayRef<RuntimeLibcallImpl> Keywords,
+                          ArrayRef<uint64_t> Hashes, int Size, int Collisions,
+                          StringToOffsetTable &OffsetTable) {
+  DenseSet<StringRef> Seen;
+  std::vector<LookupEntry> Lookup(Size * Collisions);
+
+  for (const RuntimeLibcallImpl &LibCallImpl : Keywords) {
+    StringRef ImplName = LibCallImpl.getLibcallFuncName();
+
+    // We do not want to add repeated entries for cases with the same name, only
+    // an entry for the first, with the name collision enum values immediately
+    // following.
+    if (!Seen.insert(ImplName).second)
+      continue;
+
+    uint64_t HashValue = Hashes[LibCallImpl.getEnumVal() - 1];
+
+    uint64_t Idx = (HashValue % static_cast<uint64_t>(Size)) *
+                   static_cast<uint64_t>(Collisions);
+
+    bool Found = false;
+    for (int J = 0; J < Collisions; ++J) {
+      LookupEntry &Entry = Lookup[Idx + J];
+      if (Entry.TableValue == 0) {
+        Entry.FuncName = ImplName;
+        Entry.TableValue = LibCallImpl.getEnumVal();
+        Entry.Hash = HashValue;
+        Found = true;
+        break;
+      }
+    }
+
+    if (!Found)
+      reportFatalInternalError("failure to hash " + ImplName);
+  }
+
+  return Lookup;
+}
+
+/// Generate hash table based lookup by name.
+void RuntimeLibcallEmitter::emitNameMatchHashTable(
+    raw_ostream &OS, StringToOffsetTable &OffsetTable) const {
+  std::vector<uint64_t> Hashes(RuntimeLibcallImplDefList.size());
+
+  size_t MaxFuncNameSize = 0;
+  size_t Index = 0;
+  for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+    StringRef ImplName = LibCallImpl.getLibcallFuncName();
+    MaxFuncNameSize = std::max(MaxFuncNameSize, ImplName.size());
+    Hashes[Index++] = hash(ImplName);
+  }
+
+  LLVM_DEBUG({
+    for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
+      StringRef ImplName = LibCallImpl.getLibcallFuncName();
+      if (ImplName.size() == MaxFuncNameSize) {
+        dbgs() << "Maximum runtime libcall name size: " << ImplName << '('
+               << MaxFuncNameSize << ")\n";
+      }
+    }
+  });
+
+  // Early exiting on the symbol name provides a significant speedup in the miss
+  // case on the set of symbols in a clang binary. Emit this as an inlinable
+  // precondition in the header.
+  //
+  // The empty check is also used to get sensible behavior on anonymous
+  // functions.
+  //
+  // TODO: It may make more sense to split the search by string size more. There
+  // are a few outliers, most call names are small.
+  OS << "#ifdef GET_LOOKUP_LIBCALL_IMPL_NAME_BODY\n"
+        "  size_t Size = Name.size();\n"
+        "  if (Size == 0 || Size > "
+     << MaxFuncNameSize
+     << ")\n"
+        "    return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);\n"
+        " return lookupLibcallImplNameImpl(Name);\n"
+        "#endif\n";
+
+  auto [Size, Collisions] = computePerfectHashParameters(Hashes);
+  std::vector<LookupEntry> Lookup = constructPerfectHashTable(
+      RuntimeLibcallImplDefList, Hashes, Size, Collisions, OffsetTable);
+
+  LLVM_DEBUG(dbgs() << "Runtime libcall perfect hashing parameters: Size = "
+                    << Size << ", maximum collisions = " << Collisions << '\n');
+
+  OS << "#ifdef DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME\n";
+  emitHashFunction(OS);
+
+  OS << "iota_range<RTLIB::LibcallImpl> RTLIB::RuntimeLibcallsInfo::"
+        "lookupLibcallImplNameImpl(StringRef Name) {\n";
+
+  // Emit RTLIB::LibcallImpl values
+  OS << "  static constexpr uint16_t HashTableNameToEnum[" << Lookup.size()
+     << "] = {\n";
+
+  for (auto [FuncName, Hash, TableVal] : Lookup) {
+    OS << "    " << TableVal << ',';
+    if (TableVal != 0)
+      OS << " // " << format_hex(Hash, 16) << ", " << FuncName;
+
+    OS << '\n';
+  }
+
+  OS << "  };\n\n";
+
+  OS << "  unsigned Idx = (hash(Name) % " << Size << ") * " << Collisions
+     << ";\n\n"
+        "  for (int I = 0; I != "
+     << Collisions << R"(; ++I) {
+    const uint16_t Entry = HashTableNameToEnum[Idx + I];
+    const uint16_t StrOffset = RuntimeLibcallNameOffsetTable[Entry];
+    const uint8_t StrSize = RuntimeLibcallNameSizeTable[Entry];
+    StringRef Str(
+      &RTLIB::RuntimeLibcallsInfo::RuntimeLibcallImplNameTableStorage[StrOffset],
+      StrSize);
+    if (Str == Name)
+      return libcallImplNameHit(Entry, StrOffset);
+  }
+
+  return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);
+}
+)";
+
+  OS << "#endif\n\n";
+}
+
 void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
     raw_ostream &OS) const {
+  OS << "#ifdef GET_INIT_RUNTIME_LIBCALL_NAMES\n";
+
   // Emit the implementation names
   StringToOffsetTable Table(/*AppendZero=*/true,
                             "RTLIB::RuntimeLibcallsInfo::");
@@ -337,6 +518,15 @@ const uint16_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameOffsetTable[] = {
   }
   OS << "};\n";
 
+  OS << R"(
+const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
+)";
+
+  OS << "  0,\n";
+  for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList)
+    OS << "  " << LibCallImpl.getLibcallFuncName().size() << ",\n";
+  OS << "};\n\n";
+
   // Emit the reverse mapping from implementation libraries to RTLIB::Libcall
   OS << "const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::"
         "ImplToLibcall[RTLIB::NumLibcallImpls] = {\n"
@@ -351,6 +541,10 @@ const uint16_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameOffsetTable[] = {
     OS << '\n';
   }
   OS << "};\n\n";
+
+  OS << "#endif\n\n";
+
+  emitNameMatchHashTable(OS, Table);
 }
 
 void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
@@ -531,9 +725,7 @@ void RuntimeLibcallEmitter::run(raw_ostream &OS) {
   emitSourceFileHeader("Runtime LibCalls Source Fragment", OS, Records);
   emitGetRuntimeLibcallEnum(OS);
 
-  OS << "#ifdef GET_INIT_RUNTIME_LIBCALL_NAMES\n";
   emitGetInitRuntimeLibcallNames(OS);
-  OS << "#endif\n\n";
 
   OS << "#ifdef GET_SET_TARGET_RUNTIME_LIBCALL_SETS\n";
   emitSystemRuntimeLibrarySetCalls(OS);


        


More information about the llvm-commits mailing list