[llvm] Analysis: Move LibcallLoweringInfo from CodeGen to Analysis (PR #210322)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 06:10:14 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/210322

Middle end passes need to be able to reason about library call
availability and potentially emit them without depending on codegen.
TargetLibraryInfo already lives in Analysis, and this is a step towards
the eventual merger. For now this is a mostly mechanical move, type erasing
the reference to TargetSubtargetInfo.

The per-subtarget customization (TargetSubtargetInfo::initLibcallLoweringInfo)
is inverted into a caller-supplied function_ref, so the Analysis types carry
no CodeGen/TargetSubtargetInfo reference. The module map is keyed on an opaque
erased pointer. CodeGen continues looking up based on the subtarget.

It is not yet in a state where it is usable from middle end passes; that will come
later. In principle we should be able to write arbitrary rules based on a function's
ABI attributes for which calls can be used.

Co-authored-by: Claude (Claude Opus 4.8) <noreply at anthropic.com>

>From 581b505ee5988f81901c79ed9b1cc66a8d2c632e Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 17 Jul 2026 11:25:27 +0200
Subject: [PATCH] Analysis: Move LibcallLoweringInfo from CodeGen to Analysis

Middle end passes need to be able to reason about library call
availability and potentially emit them without depending on codegen.
TargetLibraryInfo already lives in Analysis, and this is a step towards
the eventual merger. For now this is a mostly mechanical move, type erasing
the reference to TargetSubtargetInfo.

The per-subtarget customization (TargetSubtargetInfo::initLibcallLoweringInfo)
is inverted into a caller-supplied function_ref, so the Analysis types carry
no CodeGen/TargetSubtargetInfo reference. The module map is keyed on an opaque
erased pointer. CodeGen continues looking up based on the subtarget.

It is not yet in a state where it is usable from middle end passes; that will come
later. In principle we should be able to write arbitrary rules based on a function's
ABI attributes for which calls can be used.

Co-authored-by: Claude (Claude Opus 4.8) <noreply at anthropic.com>
---
 .../llvm/Analysis/LibcallLoweringInfo.h       | 160 ++++++++++++++++++
 .../llvm/CodeGen/LibcallLoweringInfo.h        | 127 ++------------
 llvm/lib/Analysis/CMakeLists.txt              |   1 +
 llvm/lib/Analysis/LibcallLoweringInfo.cpp     |  49 ++++++
 llvm/lib/CodeGen/AtomicExpandPass.cpp         |   2 +-
 llvm/lib/CodeGen/DwarfEHPrepare.cpp           |   2 +-
 llvm/lib/CodeGen/ExpandIRInsts.cpp            |   2 +-
 llvm/lib/CodeGen/LibcallLoweringInfo.cpp      |  58 +++----
 llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp |   4 +-
 llvm/lib/CodeGen/SafeStack.cpp                |   2 +-
 .../CodeGen/SelectionDAG/SelectionDAGISel.cpp |   2 +-
 llvm/lib/CodeGen/StackProtector.cpp           |   2 +-
 llvm/lib/CodeGen/TargetLoweringBase.cpp       |   4 +-
 llvm/lib/Passes/PassBuilder.cpp               |   1 +
 .../GISel/AArch64O0PreLegalizerCombiner.cpp   |   2 +-
 .../GISel/AArch64PreLegalizerCombiner.cpp     |   2 +-
 .../CodeGen/GlobalISel/GISelMITest.h          |   5 +-
 17 files changed, 264 insertions(+), 161 deletions(-)
 create mode 100644 llvm/include/llvm/Analysis/LibcallLoweringInfo.h
 create mode 100644 llvm/lib/Analysis/LibcallLoweringInfo.cpp

diff --git a/llvm/include/llvm/Analysis/LibcallLoweringInfo.h b/llvm/include/llvm/Analysis/LibcallLoweringInfo.h
new file mode 100644
index 0000000000000..efd8a5a13016b
--- /dev/null
+++ b/llvm/include/llvm/Analysis/LibcallLoweringInfo.h
@@ -0,0 +1,160 @@
+//===- LibcallLoweringInfo.h ------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Tracks which library function implementations to use for depending on a
+// calling context (e.g., which library function a particular subtarget should
+// use).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LIBCALLLOWERINGINFO_H
+#define LLVM_ANALYSIS_LIBCALLLOWERINGINFO_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/Analysis/RuntimeLibcallInfo.h"
+#include "llvm/IR/RuntimeLibcalls.h"
+#include "llvm/Pass.h"
+
+namespace llvm {
+
+/// Tracks which library functions to use for a particular subtarget or
+/// function.
+class LibcallLoweringInfo {
+private:
+  const RTLIB::RuntimeLibcallsInfo &RTLCI;
+  /// Stores the implementation choice for each libcall.
+  RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
+      RTLIB::Unsupported};
+
+public:
+  /// Callback applying the caller's context-specific (e.g. subtarget) libcall
+  /// rules on top of the module-level defaults.
+  using ApplyContextRulesFn = function_ref<void(LibcallLoweringInfo &)>;
+
+  /// Construct the lowering info from the module-level \p RTLCI, seeding the
+  /// default implementation for every available libcall, then applying the
+  /// optional \p ApplyContextRules callback for the caller's context-specific
+  /// libcall rules.
+  LLVM_ABI LibcallLoweringInfo(const RTLIB::RuntimeLibcallsInfo &RTLCI,
+                               ApplyContextRulesFn ApplyContextRules = {});
+
+  const RTLIB::RuntimeLibcallsInfo &getRuntimeLibcallsInfo() const {
+    return RTLCI;
+  }
+
+  /// 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 {
+    // FIXME: Return StringRef
+    return RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpls[Call])
+        .data();
+  }
+
+  /// Return the lowering's selection of implementation call for \p Call
+  RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
+    return LibcallImpls[Call];
+  }
+
+  /// Rename the default libcall routine name for the specified libcall.
+  void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
+    LibcallImpls[Call] = Impl;
+  }
+
+  // FIXME: Remove this wrapper in favor of directly using
+  // getLibcallImplCallingConv
+  CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
+    return RTLCI.LibcallImplCallingConvs[LibcallImpls[Call]];
+  }
+
+  /// Get the CallingConv that should be used for the specified libcall.
+  CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
+    return RTLCI.LibcallImplCallingConvs[Call];
+  }
+
+  /// Return a function impl compatible with RTLIB::MEMCPY, or
+  /// RTLIB::Unsupported if fully unsupported.
+  RTLIB::LibcallImpl getMemcpyImpl() const {
+    RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY);
+    if (Memcpy == RTLIB::Unsupported) {
+      // Fallback to memmove if memcpy isn't available.
+      return getLibcallImpl(RTLIB::MEMMOVE);
+    }
+
+    return Memcpy;
+  }
+};
+
+/// Records a mapping from an opaque lowering context to its
+/// LibcallLoweringInfo.
+///
+/// The context is identified by an opaque key (which should be
+/// TargetSubtargetInfo*)
+class ModuleLibcallLoweringInfo {
+private:
+  using LibcallLoweringMap = DenseMap<const void *, LibcallLoweringInfo>;
+  mutable LibcallLoweringMap LoweringMap;
+  const RTLIB::RuntimeLibcallsInfo *RTLCI = nullptr;
+
+public:
+  ModuleLibcallLoweringInfo() = default;
+  ModuleLibcallLoweringInfo(RTLIB::RuntimeLibcallsInfo &RTLCI)
+      : RTLCI(&RTLCI) {}
+
+  void init(const RTLIB::RuntimeLibcallsInfo *RT) { RTLCI = RT; }
+
+  void clear() {
+    RTLCI = nullptr;
+    LoweringMap.clear();
+  }
+
+  operator bool() const { return RTLCI != nullptr; }
+
+  LLVM_ABI bool invalidate(Module &, const PreservedAnalyses &,
+                           ModuleAnalysisManager::Invalidator &);
+
+  /// Return the LibcallLoweringInfo for the context identified by \p Key,
+  /// creating it (via \p ApplyContextRules) on first request. \p Key should be
+  /// TargetSubtargetInfo*.
+  template <typename KeyT>
+  const LibcallLoweringInfo &getLibcallLowering(
+      const KeyT *Key,
+      LibcallLoweringInfo::ApplyContextRulesFn ApplyContextRules = {}) const {
+    return getLibcallLoweringForKey(static_cast<const void *>(Key),
+                                    ApplyContextRules);
+  }
+
+private:
+  const LibcallLoweringInfo &getLibcallLoweringForKey(
+      const void *Key,
+      LibcallLoweringInfo::ApplyContextRulesFn ApplyContextRules) const {
+    auto It = LoweringMap.find(Key);
+    if (It != LoweringMap.end())
+      return It->second;
+    return LoweringMap.try_emplace(Key, *RTLCI, ApplyContextRules)
+        .first->second;
+  }
+};
+
+class LibcallLoweringModuleAnalysis
+    : public AnalysisInfoMixin<LibcallLoweringModuleAnalysis> {
+private:
+  friend AnalysisInfoMixin<LibcallLoweringModuleAnalysis>;
+  LLVM_ABI static AnalysisKey Key;
+
+  ModuleLibcallLoweringInfo LibcallLoweringMap;
+
+public:
+  using Result = ModuleLibcallLoweringInfo;
+
+  LLVM_ABI Result run(Module &M, ModuleAnalysisManager &);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_ANALYSIS_LIBCALLLOWERINGINFO_H
diff --git a/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h b/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
index 6adf669b10ab2..437627045611e 100644
--- a/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
+++ b/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
@@ -5,122 +5,27 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+//
+// Legacy-pass-manager wrapper around the Analysis-layer libcall lowering info,
+// which is aware of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CODEGEN_LIBCALLLOWERINGINFO_H
 #define LLVM_CODEGEN_LIBCALLLOWERINGINFO_H
 
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Analysis/RuntimeLibcallInfo.h"
-#include "llvm/IR/RuntimeLibcalls.h"
+#include "llvm/Analysis/LibcallLoweringInfo.h"
 #include "llvm/Pass.h"
 
 namespace llvm {
 class RuntimeLibraryInfoWrapper;
 class TargetSubtargetInfo;
-class TargetMachine;
-
-/// Tracks which library functions to use for a particular subtarget.
-class LibcallLoweringInfo {
-private:
-  const RTLIB::RuntimeLibcallsInfo &RTLCI;
-  /// Stores the implementation choice for each each libcall.
-  RTLIB::LibcallImpl LibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {
-      RTLIB::Unsupported};
-
-public:
-  LLVM_ABI LibcallLoweringInfo(const RTLIB::RuntimeLibcallsInfo &RTLCI,
-                               const TargetSubtargetInfo &Subtarget);
-
-  const RTLIB::RuntimeLibcallsInfo &getRuntimeLibcallsInfo() const {
-    return RTLCI;
-  }
-
-  /// 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 {
-    // FIXME: Return StringRef
-    return RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpls[Call])
-        .data();
-  }
-
-  /// Return the lowering's selection of implementation call for \p Call
-  RTLIB::LibcallImpl getLibcallImpl(RTLIB::Libcall Call) const {
-    return LibcallImpls[Call];
-  }
-
-  /// Rename the default libcall routine name for the specified libcall.
-  void setLibcallImpl(RTLIB::Libcall Call, RTLIB::LibcallImpl Impl) {
-    LibcallImpls[Call] = Impl;
-  }
-
-  // FIXME: Remove this wrapper in favor of directly using
-  // getLibcallImplCallingConv
-  CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const {
-    return RTLCI.LibcallImplCallingConvs[LibcallImpls[Call]];
-  }
-
-  /// Get the CallingConv that should be used for the specified libcall.
-  CallingConv::ID getLibcallImplCallingConv(RTLIB::LibcallImpl Call) const {
-    return RTLCI.LibcallImplCallingConvs[Call];
-  }
-
-  /// Return a function impl compatible with RTLIB::MEMCPY, or
-  /// RTLIB::Unsupported if fully unsupported.
-  RTLIB::LibcallImpl getMemcpyImpl() const {
-    RTLIB::LibcallImpl Memcpy = getLibcallImpl(RTLIB::MEMCPY);
-    if (Memcpy == RTLIB::Unsupported) {
-      // Fallback to memmove if memcpy isn't available.
-      return getLibcallImpl(RTLIB::MEMMOVE);
-    }
-
-    return Memcpy;
-  }
-};
 
-/// Record a mapping from subtarget to LibcallLoweringInfo.
-class ModuleLibcallLoweringInfo {
-private:
-  using LibcallLoweringMap =
-      DenseMap<const TargetSubtargetInfo *, LibcallLoweringInfo>;
-  mutable LibcallLoweringMap LoweringMap;
-  const RTLIB::RuntimeLibcallsInfo *RTLCI = nullptr;
-
-public:
-  ModuleLibcallLoweringInfo() = default;
-  ModuleLibcallLoweringInfo(RTLIB::RuntimeLibcallsInfo &RTLCI)
-      : RTLCI(&RTLCI) {}
-
-  void init(const RTLIB::RuntimeLibcallsInfo *RT) { RTLCI = RT; }
-
-  void clear() {
-    RTLCI = nullptr;
-    LoweringMap.clear();
-  }
-
-  operator bool() const { return RTLCI != nullptr; }
-
-  LLVM_ABI bool invalidate(Module &, const PreservedAnalyses &,
-                           ModuleAnalysisManager::Invalidator &);
-
-  const LibcallLoweringInfo &
-  getLibcallLowering(const TargetSubtargetInfo &Subtarget) const {
-    return LoweringMap.try_emplace(&Subtarget, *RTLCI, Subtarget).first->second;
-  }
-};
-
-class LibcallLoweringModuleAnalysis
-    : public AnalysisInfoMixin<LibcallLoweringModuleAnalysis> {
-private:
-  friend AnalysisInfoMixin<LibcallLoweringModuleAnalysis>;
-  LLVM_ABI static AnalysisKey Key;
-
-  ModuleLibcallLoweringInfo LibcallLoweringMap;
-
-public:
-  using Result = ModuleLibcallLoweringInfo;
-
-  LLVM_ABI Result run(Module &M, ModuleAnalysisManager &);
-};
+/// Resolve the LibcallLoweringInfo for \p Subtarget from the module-level \p
+/// ModuleInfo, applying the subtarget's libcall overrides.
+LLVM_ABI const LibcallLoweringInfo &
+getLibcallLowering(const ModuleLibcallLoweringInfo &ModuleInfo,
+                   const TargetSubtargetInfo &Subtarget);
 
 class LLVM_ABI LibcallLoweringInfoWrapper : public ImmutablePass {
   ModuleLibcallLoweringInfo Result;
@@ -131,15 +36,9 @@ class LLVM_ABI LibcallLoweringInfoWrapper : public ImmutablePass {
   LibcallLoweringInfoWrapper();
 
   const LibcallLoweringInfo &
-  getLibcallLowering(const Module &M, const TargetSubtargetInfo &Subtarget) {
-    return getResult(M).getLibcallLowering(Subtarget);
-  }
+  getLibcallLowering(const Module &M, const TargetSubtargetInfo &Subtarget);
 
-  const ModuleLibcallLoweringInfo &getResult(const Module &M) {
-    if (!Result)
-      Result.init(&RuntimeLibcallsWrapper->getRTLCI(M));
-    return Result;
-  }
+  const ModuleLibcallLoweringInfo &getResult(const Module &M);
 
   void initializePass() override;
   void getAnalysisUsage(AnalysisUsage &AU) const override;
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index f3586c66cb056..6c3996ea8d885 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -103,6 +103,7 @@ add_llvm_component_library(LLVMAnalysis
   LazyBlockFrequencyInfo.cpp
   LazyCallGraph.cpp
   LazyValueInfo.cpp
+  LibcallLoweringInfo.cpp
   Lint.cpp
   Loads.cpp
   Local.cpp
diff --git a/llvm/lib/Analysis/LibcallLoweringInfo.cpp b/llvm/lib/Analysis/LibcallLoweringInfo.cpp
new file mode 100644
index 0000000000000..95b3b0fce6a8d
--- /dev/null
+++ b/llvm/lib/Analysis/LibcallLoweringInfo.cpp
@@ -0,0 +1,49 @@
+//===- LibcallLoweringInfo.cpp - Runtime libcall lowering info ------------===//
+//
+// 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/Analysis/LibcallLoweringInfo.h"
+#include "llvm/Analysis/RuntimeLibcallInfo.h"
+
+using namespace llvm;
+
+LibcallLoweringInfo::LibcallLoweringInfo(
+    const RTLIB::RuntimeLibcallsInfo &RTLCI,
+    ApplyContextRulesFn ApplyContextRules)
+    : RTLCI(RTLCI) {
+  // TODO: This should be generated with lowering predicates, and assert the
+  // call is available.
+  for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
+    if (RTLCI.isAvailable(Impl)) {
+      RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
+      // FIXME: Hack, assume the first available libcall wins.
+      if (LibcallImpls[LC] == RTLIB::Unsupported)
+        LibcallImpls[LC] = Impl;
+    }
+  }
+
+  // Apply the caller's context-specific (e.g. subtarget) libcall rules.
+  if (ApplyContextRules)
+    ApplyContextRules(*this);
+}
+
+AnalysisKey LibcallLoweringModuleAnalysis::Key;
+
+bool ModuleLibcallLoweringInfo::invalidate(
+    Module &, const PreservedAnalyses &PA,
+    ModuleAnalysisManager::Invalidator &) {
+  // Passes that change the runtime libcall set must explicitly invalidate this
+  // pass.
+  auto PAC = PA.getChecker<LibcallLoweringModuleAnalysis>();
+  return !PAC.preservedWhenStateless();
+}
+
+ModuleLibcallLoweringInfo
+LibcallLoweringModuleAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
+  LibcallLoweringMap.init(&MAM.getResult<RuntimeLibraryAnalysis>(M));
+  return LibcallLoweringMap;
+}
diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp
index 8f75462250f82..a2e8e859faa17 100644
--- a/llvm/lib/CodeGen/AtomicExpandPass.cpp
+++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp
@@ -461,7 +461,7 @@ bool AtomicExpandImpl::run(Function &F,
   if (!Subtarget->enableAtomicExpand())
     return false;
   TLI = Subtarget->getTargetLowering();
-  LibcallLowering = &LibcallResult.getLibcallLowering(*Subtarget);
+  LibcallLowering = &getLibcallLowering(LibcallResult, *Subtarget);
   DL = &F.getDataLayout();
 
   bool MadeChange = false;
diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
index f8627727154da..5fa590a88c436 100644
--- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
@@ -405,7 +405,7 @@ PreservedAnalyses DwarfEHPreparePass::run(Function &F,
 
   const TargetSubtargetInfo *Subtarget = TM->getSubtargetImpl(F);
   const LibcallLoweringInfo &Libcalls =
-      LibcallLowering->getLibcallLowering(*Subtarget);
+      getLibcallLowering(*LibcallLowering, *Subtarget);
 
   bool Changed =
       prepareDwarfEH(OptLevel, F, Libcalls, DT, TTI, TM->getTargetTriple());
diff --git a/llvm/lib/CodeGen/ExpandIRInsts.cpp b/llvm/lib/CodeGen/ExpandIRInsts.cpp
index b8503b958f76b..edbf8b3efaadc 100644
--- a/llvm/lib/CodeGen/ExpandIRInsts.cpp
+++ b/llvm/lib/CodeGen/ExpandIRInsts.cpp
@@ -1469,7 +1469,7 @@ PreservedAnalyses ExpandIRInstsPass::run(Function &F,
   }
 
   const LibcallLoweringInfo &Libcalls =
-      LibcallLowering->getLibcallLowering(*STI);
+      getLibcallLowering(*LibcallLowering, *STI);
 
   return runImpl(F, TLI, Libcalls, AC) ? PreservedAnalyses::none()
                                        : PreservedAnalyses::all();
diff --git a/llvm/lib/CodeGen/LibcallLoweringInfo.cpp b/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
index bb406c7f1a5b2..5d99226924421 100644
--- a/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
@@ -1,4 +1,4 @@
-//===- LibcallLoweringInfo.cpp - Interface for runtime libcalls -----------===//
+//===- LibcallLoweringInfo.cpp - Legacy wrapper for libcall lowering ------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -10,43 +10,16 @@
 #include "llvm/Analysis/RuntimeLibcallInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/InitializePasses.h"
-#include "llvm/Target/TargetMachine.h"
 
 using namespace llvm;
 
-LibcallLoweringInfo::LibcallLoweringInfo(
-    const RTLIB::RuntimeLibcallsInfo &RTLCI,
-    const TargetSubtargetInfo &Subtarget)
-    : RTLCI(RTLCI) {
-  // TODO: This should be generated with lowering predicates, and assert the
-  // call is available.
-  for (RTLIB::LibcallImpl Impl : RTLIB::libcall_impls()) {
-    if (RTLCI.isAvailable(Impl)) {
-      RTLIB::Libcall LC = RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl);
-      // FIXME: Hack, assume the first available libcall wins.
-      if (LibcallImpls[LC] == RTLIB::Unsupported)
-        LibcallImpls[LC] = Impl;
-    }
-  }
-
-  Subtarget.initLibcallLoweringInfo(*this);
-}
-
-AnalysisKey LibcallLoweringModuleAnalysis::Key;
-
-bool ModuleLibcallLoweringInfo::invalidate(
-    Module &, const PreservedAnalyses &PA,
-    ModuleAnalysisManager::Invalidator &) {
-  // Passes that change the runtime libcall set must explicitly invalidate this
-  // pass.
-  auto PAC = PA.getChecker<LibcallLoweringModuleAnalysis>();
-  return !PAC.preservedWhenStateless();
-}
-
-ModuleLibcallLoweringInfo
-LibcallLoweringModuleAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
-  LibcallLoweringMap.init(&MAM.getResult<RuntimeLibraryAnalysis>(M));
-  return LibcallLoweringMap;
+const LibcallLoweringInfo &
+llvm::getLibcallLowering(const ModuleLibcallLoweringInfo &ModuleInfo,
+                         const TargetSubtargetInfo &Subtarget) {
+  return ModuleInfo.getLibcallLowering(
+      &Subtarget, [&](LibcallLoweringInfo &Info) {
+        Subtarget.initLibcallLoweringInfo(Info);
+      });
 }
 
 INITIALIZE_PASS_BEGIN(LibcallLoweringInfoWrapper, "libcall-lowering-info",
@@ -59,6 +32,21 @@ char LibcallLoweringInfoWrapper::ID = 0;
 
 LibcallLoweringInfoWrapper::LibcallLoweringInfoWrapper() : ImmutablePass(ID) {}
 
+const LibcallLoweringInfo &LibcallLoweringInfoWrapper::getLibcallLowering(
+    const Module &M, const TargetSubtargetInfo &Subtarget) {
+  return getResult(M).getLibcallLowering(
+      &Subtarget, [&](LibcallLoweringInfo &Info) {
+        Subtarget.initLibcallLoweringInfo(Info);
+      });
+}
+
+const ModuleLibcallLoweringInfo &
+LibcallLoweringInfoWrapper::getResult(const Module &M) {
+  if (!Result)
+    Result.init(&RuntimeLibcallsWrapper->getRTLCI(M));
+  return Result;
+}
+
 void LibcallLoweringInfoWrapper::initializePass() {
   RuntimeLibcallsWrapper = &getAnalysis<RuntimeLibraryInfoWrapper>();
 }
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 4b5c97a23b091..24788148b9f15 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -248,7 +248,7 @@ static bool canEmitLibcall(const ModuleLibcallLoweringInfo &ModuleLowering,
   if (!TM)
     return true;
   const LibcallLoweringInfo &Lowering =
-      ModuleLowering.getLibcallLowering(*TM->getSubtargetImpl(*F));
+      getLibcallLowering(ModuleLowering, *TM->getSubtargetImpl(*F));
   return Lowering.getLibcallImpl(LC) != RTLIB::Unsupported;
 }
 
@@ -258,7 +258,7 @@ static bool canEmitMemcpy(const ModuleLibcallLoweringInfo &ModuleLowering,
   if (!TM)
     return true;
   const LibcallLoweringInfo &Lowering =
-      ModuleLowering.getLibcallLowering(*TM->getSubtargetImpl(*F));
+      getLibcallLowering(ModuleLowering, *TM->getSubtargetImpl(*F));
   return Lowering.getMemcpyImpl() != RTLIB::Unsupported;
 }
 
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp
index f154623879063..ca20503024524 100644
--- a/llvm/lib/CodeGen/SafeStack.cpp
+++ b/llvm/lib/CodeGen/SafeStack.cpp
@@ -980,7 +980,7 @@ PreservedAnalyses SafeStackPass::run(Function &F,
   }
 
   const LibcallLoweringInfo &Libcalls =
-      LibcallLowering->getLibcallLowering(*Subtarget);
+      getLibcallLowering(*LibcallLowering, *Subtarget);
 
   DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 907607045e97f..d62aac0d7c46e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -509,7 +509,7 @@ void SelectionDAGISel::initializeAnalysisResults(
                           "' analysis required");
   }
 
-  LibcallLowering = &LibcallResult->getLibcallLowering(Subtarget);
+  LibcallLowering = &getLibcallLowering(*LibcallResult, Subtarget);
   CurDAG->init(*MF, *ORE, MFAM, LibInfo, LibcallLowering, UA, PSI, BFI, MMI,
                FnVarLocs);
 
diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 90e7a4a9934e7..9ec1d0630952d 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -146,7 +146,7 @@ PreservedAnalyses StackProtectorPass::run(Function &F,
   const TargetSubtargetInfo *STI = TM->getSubtargetImpl(F);
   const TargetLowering *TLI = STI->getTargetLowering();
   const LibcallLoweringInfo &Libcalls =
-      LibcallLowering->getLibcallLowering(*STI);
+      getLibcallLowering(*LibcallLowering, *STI);
 
   ++NumFunProtected;
   bool Changed = InsertStackProtectors(*TLI, Libcalls, &F, DT ? &DTU : nullptr,
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 44ce04e6c4dac..70dabaee0d432 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -1021,7 +1021,9 @@ TargetLoweringBase::TargetLoweringBase(const TargetMachine &tm,
       RuntimeLibcallInfo(TM.getTargetTriple(), TM.Options.ExceptionModel,
                          TM.Options.FloatABIType, TM.Options.EABIVersion,
                          TM.Options.MCOptions.getABIName(), TM.Options.VecLib),
-      Libcalls(RuntimeLibcallInfo, STI) {
+      Libcalls(RuntimeLibcallInfo, [&STI](LibcallLoweringInfo &Info) {
+        STI.initLibcallLoweringInfo(Info);
+      }) {
   initActions();
 
   // Perform these initializations only once.
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 48a5108355c32..462580b5a9a7b 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -51,6 +51,7 @@
 #include "llvm/Analysis/LastRunTrackingAnalysis.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LazyValueInfo.h"
+#include "llvm/Analysis/LibcallLoweringInfo.h"
 #include "llvm/Analysis/Lint.h"
 #include "llvm/Analysis/LoopAccessAnalysis.h"
 #include "llvm/Analysis/LoopCacheAnalysis.h"
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
index 22fcff092dde6..1349664ca89c7 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
@@ -203,7 +203,7 @@ AArch64O0PreLegalizerCombinerPass::run(MachineFunction &MF,
   if (!LibcallResult)
     reportFatalUsageError("LibcallLoweringModuleAnalysis result not available");
 
-  const LibcallLoweringInfo &Libcalls = LibcallResult->getLibcallLowering(ST);
+  const LibcallLoweringInfo &Libcalls = getLibcallLowering(*LibcallResult, ST);
 
   if (!runCombiner(MF, Libcalls, *RuleConfig))
     return PreservedAnalyses::all();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
index 30b05823bc740..e331a265b800a 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
@@ -924,7 +924,7 @@ AArch64PreLegalizerCombinerPass::run(MachineFunction &MF,
   if (!LibcallResult)
     reportFatalUsageError("LibcallLoweringModuleAnalysis result not available");
 
-  const LibcallLoweringInfo &Libcalls = LibcallResult->getLibcallLowering(ST);
+  const LibcallLoweringInfo &Libcalls = getLibcallLowering(*LibcallResult, ST);
 
   bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOptLevel::None;
 
diff --git a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
index dcb0ae1d6766e..012b401a381d0 100644
--- a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
+++ b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
@@ -125,7 +125,10 @@ class GISelMITest : public ::testing::Test {
     MRI = &MF->getRegInfo();
     B.setInsertPt(*EntryMBB, EntryMBB->end());
     RTLCI.emplace(TM->getTargetTriple());
-    LibcallLowering.emplace(*RTLCI, MF->getSubtarget());
+    const TargetSubtargetInfo &STI = MF->getSubtarget();
+    LibcallLowering.emplace(*RTLCI, [&STI](LibcallLoweringInfo &Info) {
+      STI.initLibcallLoweringInfo(Info);
+    });
   }
 
   LLVMContext Context;



More information about the llvm-commits mailing list