https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/170328

>From 49b0899068bb9ad83cda0de4fdcbed480a4d1fb3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Mon, 24 Nov 2025 18:15:49 -0500
Subject: [PATCH 1/2] GlobalISel: Use LibcallLoweringInfo analysis in legalizer

This is mostly boilerplate to move various freestanding utility
functions into LegalizerHelper. LibcallLoweringInfo is currently
optional, mostly because threading it through assorted other
uses of LegalizerHelper is more difficult.

I had a lot of trouble getting this to work in the legacy pass
manager with setRequiresCodeGenSCCOrder, and am not happy with the
result. A sub-pass manager is introduced and this is invalidated,
so we're re-computing this unnecessarily.
---
 .../llvm/CodeGen/GlobalISel/Legalizer.h       |  11 +-
 .../llvm/CodeGen/GlobalISel/LegalizerHelper.h |  73 +++++----
 llvm/lib/CodeGen/GlobalISel/Legalizer.cpp     |  24 +--
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    | 149 +++++++++---------
 llvm/lib/Target/ARM/ARMLegalizerInfo.cpp      |  18 +--
 .../CodeGen/GlobalISel/GISelMITest.h          |   4 +
 .../GlobalISel/LegalizerHelperTest.cpp        |  63 ++++----
 .../CodeGen/GlobalISel/LegalizerTest.cpp      |   6 +-
 8 files changed, 183 insertions(+), 165 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h 
b/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h
index a94daa202d856..f8e629bc50a90 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Legalizer.h
@@ -33,6 +33,7 @@ class LegalizerInfo;
 class MachineIRBuilder;
 class MachineInstr;
 class GISelChangeObserver;
+class LibcallLoweringInfo;
 class LostDebugLocObserver;
 
 class LLVM_ABI Legalizer : public MachineFunctionPass {
@@ -70,11 +71,11 @@ class LLVM_ABI Legalizer : public MachineFunctionPass {
 
   bool runOnMachineFunction(MachineFunction &MF) override;
 
-  static MFResult
-  legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo &LI,
-                          ArrayRef<GISelChangeObserver *> AuxObservers,
-                          LostDebugLocObserver &LocObserver,
-                          MachineIRBuilder &MIRBuilder, GISelValueTracking 
*VT);
+  static MFResult legalizeMachineFunction(
+      MachineFunction &MF, const LegalizerInfo &LI,
+      ArrayRef<GISelChangeObserver *> AuxObservers,
+      LostDebugLocObserver &LocObserver, MachineIRBuilder &MIRBuilder,
+      const LibcallLoweringInfo *Libcalls, GISelValueTracking *VT);
 };
 } // End namespace llvm.
 
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h 
b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index a458cbd94ccb1..11f734ec64eb1 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -59,7 +59,10 @@ class LegalizerHelper {
   MachineRegisterInfo &MRI;
   const LegalizerInfo &LI;
   const TargetLowering &TLI;
-  GISelValueTracking *VT;
+
+  // FIXME: Should probably make Libcalls mandatory
+  const LibcallLoweringInfo *Libcalls = nullptr;
+  GISelValueTracking *VT = nullptr;
 
 public:
   enum LegalizeResult {
@@ -78,12 +81,15 @@ class LegalizerHelper {
   /// Expose LegalizerInfo so the clients can re-use.
   const LegalizerInfo &getLegalizerInfo() const { return LI; }
   const TargetLowering &getTargetLowering() const { return TLI; }
+  const LibcallLoweringInfo *getLibcallLoweringInfo() { return Libcalls; }
   GISelValueTracking *getValueTracking() const { return VT; }
 
   LLVM_ABI LegalizerHelper(MachineFunction &MF, GISelChangeObserver &Observer,
-                           MachineIRBuilder &B);
+                           MachineIRBuilder &B,
+                           const LibcallLoweringInfo *Libcalls = nullptr);
   LLVM_ABI LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
                            GISelChangeObserver &Observer, MachineIRBuilder &B,
+                           const LibcallLoweringInfo *Libcalls = nullptr,
                            GISelValueTracking *VT = nullptr);
 
   /// Replace \p MI by a sequence of legal instructions that can implement the
@@ -178,6 +184,37 @@ class LegalizerHelper {
   /// def by inserting a G_BITCAST from \p CastTy
   LLVM_ABI void bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx);
 
+  // Useful for libcalls where all operands have the same type.
+  LLVM_ABI LegalizeResult
+  simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
+                Type *OpType, LostDebugLocObserver &LocObserver) const;
+
+  LLVM_ABI LegalizeResult conversionLibcall(MachineInstr &MI, Type *ToType,
+                                            Type *FromType,
+                                            LostDebugLocObserver &LocObserver,
+                                            bool IsSigned = false) const;
+
+  /// Helper function that creates a libcall to the given \p Name using the
+  /// given calling convention \p CC.
+  LLVM_ABI LegalizeResult createLibcall(const char *Name,
+                                        const CallLowering::ArgInfo &Result,
+                                        ArrayRef<CallLowering::ArgInfo> Args,
+                                        CallingConv::ID CC,
+                                        LostDebugLocObserver &LocObserver,
+                                        MachineInstr *MI = nullptr) const;
+
+  /// Helper function that creates the given libcall.
+  LLVM_ABI LegalizeResult createLibcall(RTLIB::Libcall Libcall,
+                                        const CallLowering::ArgInfo &Result,
+                                        ArrayRef<CallLowering::ArgInfo> Args,
+                                        LostDebugLocObserver &LocObserver,
+                                        MachineInstr *MI = nullptr) const;
+
+  /// Create a libcall to memcpy et al.
+  LLVM_ABI LegalizeResult
+  createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI,
+                   LostDebugLocObserver &LocObserver) const;
+
 private:
   LegalizeResult
   widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
@@ -278,17 +315,13 @@ class LegalizerHelper {
                               bool IsVolatile);
 
   // Implements floating-point environment read/write via library function 
call.
-  LegalizeResult createGetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                       MachineInstr &MI,
+  LegalizeResult createGetStateLibcall(MachineInstr &MI,
                                        LostDebugLocObserver &LocObserver);
-  LegalizeResult createSetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                       MachineInstr &MI,
+  LegalizeResult createSetStateLibcall(MachineInstr &MI,
                                        LostDebugLocObserver &LocObserver);
-  LegalizeResult createResetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                         MachineInstr &MI,
+  LegalizeResult createResetStateLibcall(MachineInstr &MI,
                                          LostDebugLocObserver &LocObserver);
-  LegalizeResult createFCMPLibcall(MachineIRBuilder &MIRBuilder,
-                                   MachineInstr &MI,
+  LegalizeResult createFCMPLibcall(MachineInstr &MI,
                                    LostDebugLocObserver &LocObserver);
 
   MachineInstrBuilder
@@ -539,26 +572,6 @@ class LegalizerHelper {
   LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI);
 };
 
-/// Helper function that creates a libcall to the given \p Name using the given
-/// calling convention \p CC.
-LLVM_ABI LegalizerHelper::LegalizeResult
-createLibcall(MachineIRBuilder &MIRBuilder, const char *Name,
-              const CallLowering::ArgInfo &Result,
-              ArrayRef<CallLowering::ArgInfo> Args, CallingConv::ID CC,
-              LostDebugLocObserver &LocObserver, MachineInstr *MI = nullptr);
-
-/// Helper function that creates the given libcall.
-LLVM_ABI LegalizerHelper::LegalizeResult
-createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
-              const CallLowering::ArgInfo &Result,
-              ArrayRef<CallLowering::ArgInfo> Args,
-              LostDebugLocObserver &LocObserver, MachineInstr *MI = nullptr);
-
-/// Create a libcall to memcpy et al.
-LLVM_ABI LegalizerHelper::LegalizeResult
-createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
-                 MachineInstr &MI, LostDebugLocObserver &LocObserver);
-
 } // End namespace llvm.
 
 #endif
diff --git a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp 
b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
index 0f0656aaa4f45..ce2d9749f3fdc 100644
--- a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
@@ -73,6 +73,7 @@ char Legalizer::ID = 0;
 INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,
                       "Legalize the Machine IR a function's Machine IR", false,
                       false)
+INITIALIZE_PASS_DEPENDENCY(LibcallLoweringInfoWrapper)
 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
 INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
@@ -83,6 +84,7 @@ INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,
 Legalizer::Legalizer() : MachineFunctionPass(ID) { }
 
 void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
+  AU.addRequired<LibcallLoweringInfoWrapper>();
   AU.addRequired<TargetPassConfig>();
   AU.addRequired<GISelCSEAnalysisWrapperPass>();
   AU.addPreserved<GISelCSEAnalysisWrapperPass>();
@@ -172,12 +174,11 @@ class LegalizerWorkListManager : public 
GISelChangeObserver {
 };
 } // namespace
 
-Legalizer::MFResult
-Legalizer::legalizeMachineFunction(MachineFunction &MF, const LegalizerInfo 
&LI,
-                                   ArrayRef<GISelChangeObserver *> 
AuxObservers,
-                                   LostDebugLocObserver &LocObserver,
-                                   MachineIRBuilder &MIRBuilder,
-                                   GISelValueTracking *VT) {
+Legalizer::MFResult Legalizer::legalizeMachineFunction(
+    MachineFunction &MF, const LegalizerInfo &LI,
+    ArrayRef<GISelChangeObserver *> AuxObservers,
+    LostDebugLocObserver &LocObserver, MachineIRBuilder &MIRBuilder,
+    const LibcallLoweringInfo *Libcalls, GISelValueTracking *VT) {
   MIRBuilder.setMF(MF);
   MachineRegisterInfo &MRI = MF.getRegInfo();
 
@@ -216,7 +217,7 @@ Legalizer::legalizeMachineFunction(MachineFunction &MF, 
const LegalizerInfo &LI,
   // Now install the observer as the delegate to MF.
   // This will keep all the observers notified about new insertions/deletions.
   RAIIMFObsDelInstaller Installer(MF, WrapperObserver);
-  LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder, VT);
+  LegalizerHelper Helper(MF, LI, WrapperObserver, MIRBuilder, Libcalls, VT);
   LegalizationArtifactCombiner ArtCombiner(MIRBuilder, MRI, LI, VT);
   bool Changed = false;
   SmallVector<MachineInstr *, 128> RetryList;
@@ -339,13 +340,18 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) 
{
   if (VerifyDebugLocs > DebugLocVerifyLevel::None)
     AuxObservers.push_back(&LocObserver);
 
+  const TargetSubtargetInfo &Subtarget = MF.getSubtarget();
+
+  const LibcallLoweringInfo &Libcalls =
+      getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(Subtarget);
+
   // This allows Known Bits Analysis in the legalizer.
   GISelValueTracking *VT =
       &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
 
-  const LegalizerInfo &LI = *MF.getSubtarget().getLegalizerInfo();
+  const LegalizerInfo &LI = *Subtarget.getLegalizerInfo();
   MFResult Result = legalizeMachineFunction(MF, LI, AuxObservers, LocObserver,
-                                            *MIRBuilder, VT);
+                                            *MIRBuilder, &Libcalls, VT);
 
   if (Result.FailedOn) {
     reportGISelFailure(MF, MORE, "gisel-legalize",
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp 
b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 1aa1d465d8da6..32cda979a0cda 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -104,16 +104,19 @@ static Type *getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty) 
{
 
 LegalizerHelper::LegalizerHelper(MachineFunction &MF,
                                  GISelChangeObserver &Observer,
-                                 MachineIRBuilder &Builder)
+                                 MachineIRBuilder &Builder,
+                                 const LibcallLoweringInfo *Libcalls)
     : MIRBuilder(Builder), Observer(Observer), MRI(MF.getRegInfo()),
       LI(*MF.getSubtarget().getLegalizerInfo()),
-      TLI(*MF.getSubtarget().getTargetLowering()), VT(nullptr) {}
+      TLI(*MF.getSubtarget().getTargetLowering()), Libcalls(Libcalls) {}
 
 LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
                                  GISelChangeObserver &Observer,
-                                 MachineIRBuilder &B, GISelValueTracking *VT)
+                                 MachineIRBuilder &B,
+                                 const LibcallLoweringInfo *Libcalls,
+                                 GISelValueTracking *VT)
     : MIRBuilder(B), Observer(Observer), MRI(MF.getRegInfo()), LI(LI),
-      TLI(*MF.getSubtarget().getTargetLowering()), VT(VT) {}
+      TLI(*MF.getSubtarget().getTargetLowering()), Libcalls(Libcalls), VT(VT) 
{}
 
 LegalizerHelper::LegalizeResult
 LegalizerHelper::legalizeInstrStep(MachineInstr &MI,
@@ -581,12 +584,10 @@ static bool isLibCallInTailPosition(const 
CallLowering::ArgInfo &Result,
   return true;
 }
 
-LegalizerHelper::LegalizeResult
-llvm::createLibcall(MachineIRBuilder &MIRBuilder, const char *Name,
-                    const CallLowering::ArgInfo &Result,
-                    ArrayRef<CallLowering::ArgInfo> Args,
-                    const CallingConv::ID CC, LostDebugLocObserver 
&LocObserver,
-                    MachineInstr *MI) {
+LegalizerHelper::LegalizeResult LegalizerHelper::createLibcall(
+    const char *Name, const CallLowering::ArgInfo &Result,
+    ArrayRef<CallLowering::ArgInfo> Args, const CallingConv::ID CC,
+    LostDebugLocObserver &LocObserver, MachineInstr *MI) const {
   auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
 
   CallLowering::CallLoweringInfo Info;
@@ -628,31 +629,36 @@ llvm::createLibcall(MachineIRBuilder &MIRBuilder, const 
char *Name,
   return LegalizerHelper::Legalized;
 }
 
-LegalizerHelper::LegalizeResult
-llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
-                    const CallLowering::ArgInfo &Result,
-                    ArrayRef<CallLowering::ArgInfo> Args,
-                    LostDebugLocObserver &LocObserver, MachineInstr *MI) {
-  auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
-  const char *Name = TLI.getLibcallName(Libcall);
-  if (!Name)
+LegalizerHelper::LegalizeResult LegalizerHelper::createLibcall(
+    RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result,
+    ArrayRef<CallLowering::ArgInfo> Args, LostDebugLocObserver &LocObserver,
+    MachineInstr *MI) const {
+  if (!Libcalls)
     return LegalizerHelper::UnableToLegalize;
-  const CallingConv::ID CC = TLI.getLibcallCallingConv(Libcall);
-  return createLibcall(MIRBuilder, Name, Result, Args, CC, LocObserver, MI);
+
+  RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(Libcall);
+  if (LibcallImpl == RTLIB::Unsupported)
+    return LegalizerHelper::UnableToLegalize;
+
+  auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
+
+  StringRef Name = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpl);
+  const CallingConv::ID CC = TLI.getLibcallImplCallingConv(LibcallImpl);
+  return createLibcall(Name.data(), Result, Args, CC, LocObserver, MI);
 }
 
 // Useful for libcalls where all operands have the same type.
-static LegalizerHelper::LegalizeResult
-simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
-              Type *OpType, LostDebugLocObserver &LocObserver) {
+LegalizerHelper::LegalizeResult
+LegalizerHelper::simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
+                               unsigned Size, Type *OpType,
+                               LostDebugLocObserver &LocObserver) const {
   auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
 
   // FIXME: What does the original arg index mean here?
   SmallVector<CallLowering::ArgInfo, 3> Args;
   for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
     Args.push_back({MO.getReg(), OpType, 0});
-  return createLibcall(MIRBuilder, Libcall,
-                       {MI.getOperand(0).getReg(), OpType, 0}, Args,
+  return createLibcall(Libcall, {MI.getOperand(0).getReg(), OpType, 0}, Args,
                        LocObserver, &MI);
 }
 
@@ -681,13 +687,12 @@ LegalizerHelper::LegalizeResult 
LegalizerHelper::emitSincosLibcall(
           .getReg(0);
 
   auto &Ctx = MF.getFunction().getContext();
-  auto LibcallResult =
-      createLibcall(MIRBuilder, getRTLibDesc(MI.getOpcode(), Size),
-                    {{0}, Type::getVoidTy(Ctx), 0},
-                    {{Src, OpType, 0},
-                     {StackPtrSin, PointerType::get(Ctx, AddrSpace), 1},
-                     {StackPtrCos, PointerType::get(Ctx, AddrSpace), 2}},
-                    LocObserver, &MI);
+  auto LibcallResult = createLibcall(
+      getRTLibDesc(MI.getOpcode(), Size), {{0}, Type::getVoidTy(Ctx), 0},
+      {{Src, OpType, 0},
+       {StackPtrSin, PointerType::get(Ctx, AddrSpace), 1},
+       {StackPtrCos, PointerType::get(Ctx, AddrSpace), 2}},
+      LocObserver, &MI);
 
   if (LibcallResult != LegalizeResult::Legalized)
     return LegalizerHelper::UnableToLegalize;
@@ -728,7 +733,7 @@ LegalizerHelper::emitModfLibcall(MachineInstr &MI, 
MachineIRBuilder &MIRBuilder,
 
   auto &Ctx = MF.getFunction().getContext();
   auto LibcallResult = createLibcall(
-      MIRBuilder, getRTLibDesc(MI.getOpcode(), Size), {DstFrac, OpType, 0},
+      getRTLibDesc(MI.getOpcode(), Size), {DstFrac, OpType, 0},
       {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
       LocObserver, &MI);
 
@@ -745,8 +750,8 @@ LegalizerHelper::emitModfLibcall(MachineInstr &MI, 
MachineIRBuilder &MIRBuilder,
 }
 
 LegalizerHelper::LegalizeResult
-llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
-                       MachineInstr &MI, LostDebugLocObserver &LocObserver) {
+LegalizerHelper::createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI,
+                                  LostDebugLocObserver &LocObserver) const {
   auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
 
   SmallVector<CallLowering::ArgInfo, 3> Args;
@@ -984,10 +989,9 @@ static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, 
Type *ToType,
   llvm_unreachable("Unsupported libcall function");
 }
 
-static LegalizerHelper::LegalizeResult
-conversionLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, Type *ToType,
-                  Type *FromType, LostDebugLocObserver &LocObserver,
-                  const TargetLowering &TLI, bool IsSigned = false) {
+LegalizerHelper::LegalizeResult LegalizerHelper::conversionLibcall(
+    MachineInstr &MI, Type *ToType, Type *FromType,
+    LostDebugLocObserver &LocObserver, bool IsSigned) const {
   CallLowering::ArgInfo Arg = {MI.getOperand(1).getReg(), FromType, 0};
   if (FromType->isIntegerTy()) {
     if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
@@ -997,9 +1001,8 @@ conversionLibcall(MachineInstr &MI, MachineIRBuilder 
&MIRBuilder, Type *ToType,
   }
 
   RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
-  return createLibcall(MIRBuilder, Libcall,
-                       {MI.getOperand(0).getReg(), ToType, 0}, Arg, 
LocObserver,
-                       &MI);
+  return createLibcall(Libcall, {MI.getOperand(0).getReg(), ToType, 0}, Arg,
+                       LocObserver, &MI);
 }
 
 static RTLIB::Libcall
@@ -1041,8 +1044,7 @@ getStateLibraryFunctionFor(MachineInstr &MI, const 
TargetLowering &TLI) {
 //     %0:_(s32) = G_LOAD % 1
 //
 LegalizerHelper::LegalizeResult
-LegalizerHelper::createGetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                       MachineInstr &MI,
+LegalizerHelper::createGetStateLibcall(MachineInstr &MI,
                                        LostDebugLocObserver &LocObserver) {
   const DataLayout &DL = MIRBuilder.getDataLayout();
   auto &MF = MIRBuilder.getMF();
@@ -1061,11 +1063,10 @@ LegalizerHelper::createGetStateLibcall(MachineIRBuilder 
&MIRBuilder,
   unsigned TempAddrSpace = DL.getAllocaAddrSpace();
   Type *StatePtrTy = PointerType::get(Ctx, TempAddrSpace);
   RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
-  auto Res =
-      createLibcall(MIRBuilder, RTLibcall,
-                    CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
-                    CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
-                    LocObserver, nullptr);
+  auto Res = createLibcall(
+      RTLibcall, CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
+      CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
+      nullptr);
   if (Res != LegalizerHelper::Legalized)
     return Res;
 
@@ -1081,8 +1082,7 @@ LegalizerHelper::createGetStateLibcall(MachineIRBuilder 
&MIRBuilder,
 // using transient space in stack. In this case the library function reads
 // content of memory region.
 LegalizerHelper::LegalizeResult
-LegalizerHelper::createSetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                       MachineInstr &MI,
+LegalizerHelper::createSetStateLibcall(MachineInstr &MI,
                                        LostDebugLocObserver &LocObserver) {
   const DataLayout &DL = MIRBuilder.getDataLayout();
   auto &MF = MIRBuilder.getMF();
@@ -1106,7 +1106,7 @@ LegalizerHelper::createSetStateLibcall(MachineIRBuilder 
&MIRBuilder,
   unsigned TempAddrSpace = DL.getAllocaAddrSpace();
   Type *StatePtrTy = PointerType::get(Ctx, TempAddrSpace);
   RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
-  return createLibcall(MIRBuilder, RTLibcall,
+  return createLibcall(RTLibcall,
                        CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
                        CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
                        LocObserver, nullptr);
@@ -1152,8 +1152,7 @@ getFCMPLibcallDesc(const CmpInst::Predicate Pred, 
unsigned Size) {
 }
 
 LegalizerHelper::LegalizeResult
-LegalizerHelper::createFCMPLibcall(MachineIRBuilder &MIRBuilder,
-                                   MachineInstr &MI,
+LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
                                    LostDebugLocObserver &LocObserver) {
   auto &MF = MIRBuilder.getMF();
   auto &Ctx = MF.getFunction().getContext();
@@ -1183,7 +1182,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder 
&MIRBuilder,
     Register Temp = MRI.createGenericVirtualRegister(TempLLT);
     // Generate libcall, holding result in Temp
     const auto Status = createLibcall(
-        MIRBuilder, Libcall, {Temp, Type::getInt32Ty(Ctx), 0},
+        Libcall, {Temp, Type::getInt32Ty(Ctx), 0},
         {{Cmp->getLHSReg(), OpType, 0}, {Cmp->getRHSReg(), OpType, 1}},
         LocObserver, &MI);
     if (!Status)
@@ -1282,8 +1281,7 @@ LegalizerHelper::createFCMPLibcall(MachineIRBuilder 
&MIRBuilder,
 // `((const femode_t *) -1)`. Such assumption is used here. If for some target
 // it is not true, the target must provide custom lowering.
 LegalizerHelper::LegalizeResult
-LegalizerHelper::createResetStateLibcall(MachineIRBuilder &MIRBuilder,
-                                         MachineInstr &MI,
+LegalizerHelper::createResetStateLibcall(MachineInstr &MI,
                                          LostDebugLocObserver &LocObserver) {
   const DataLayout &DL = MIRBuilder.getDataLayout();
   auto &MF = MIRBuilder.getMF();
@@ -1299,10 +1297,9 @@ 
LegalizerHelper::createResetStateLibcall(MachineIRBuilder &MIRBuilder,
   MIRBuilder.buildIntToPtr(Dest, DefValue);
 
   RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
-  return createLibcall(MIRBuilder, RTLibcall,
-                       CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
-                       CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}),
-                       LocObserver, &MI);
+  return createLibcall(
+      RTLibcall, CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
+      CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &MI);
 }
 
 LegalizerHelper::LegalizeResult
@@ -1408,7 +1405,7 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
     }
     auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
     LegalizeResult Status =
-        createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), ITy, 0},
+        createLibcall(Libcall, {MI.getOperand(0).getReg(), ITy, 0},
                       {{MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, 
&MI);
     if (Status != Legalized)
       return Status;
@@ -1431,9 +1428,8 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
         {MI.getOperand(1).getReg(), HLTy, 0},
         {MI.getOperand(2).getReg(), ITy, 1}};
     Args[1].Flags[0].setSExt();
-    LegalizeResult Status =
-        createLibcall(MIRBuilder, Libcall, {MI.getOperand(0).getReg(), HLTy, 
0},
-                      Args, LocObserver, &MI);
+    LegalizeResult Status = createLibcall(
+        Libcall, {MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &MI);
     if (Status != Legalized)
       return Status;
     break;
@@ -1444,14 +1440,13 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
     Type *ToTy = getFloatTypeForLLT(Ctx, 
MRI.getType(MI.getOperand(0).getReg()));
     if (!FromTy || !ToTy)
       return UnableToLegalize;
-    LegalizeResult Status =
-        conversionLibcall(MI, MIRBuilder, ToTy, FromTy, LocObserver, TLI);
+    LegalizeResult Status = conversionLibcall(MI, ToTy, FromTy, LocObserver);
     if (Status != Legalized)
       return Status;
     break;
   }
   case TargetOpcode::G_FCMP: {
-    LegalizeResult Status = createFCMPLibcall(MIRBuilder, MI, LocObserver);
+    LegalizeResult Status = createFCMPLibcall(MI, LocObserver);
     if (Status != Legalized)
       return Status;
     MI.eraseFromParent();
@@ -1465,8 +1460,8 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
     unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
     if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
       return UnableToLegalize;
-    LegalizeResult Status = conversionLibcall(
-        MI, MIRBuilder, Type::getIntNTy(Ctx, ToSize), FromTy, LocObserver, 
TLI);
+    LegalizeResult Status = conversionLibcall(MI, Type::getIntNTy(Ctx, ToSize),
+                                              FromTy, LocObserver);
     if (Status != Legalized)
       return Status;
     break;
@@ -1479,9 +1474,8 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
     if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
       return UnableToLegalize;
     bool IsSigned = MI.getOpcode() == TargetOpcode::G_SITOFP;
-    LegalizeResult Status =
-        conversionLibcall(MI, MIRBuilder, ToTy, Type::getIntNTy(Ctx, FromSize),
-                          LocObserver, TLI, IsSigned);
+    LegalizeResult Status = conversionLibcall(
+        MI, ToTy, Type::getIntNTy(Ctx, FromSize), LocObserver, IsSigned);
     if (Status != Legalized)
       return Status;
     break;
@@ -1504,7 +1498,7 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
   case TargetOpcode::G_MEMMOVE:
   case TargetOpcode::G_MEMSET: {
     LegalizeResult Result =
-        createMemLibcall(MIRBuilder, *MIRBuilder.getMRI(), MI, LocObserver);
+        createMemLibcall(*MIRBuilder.getMRI(), MI, LocObserver);
     if (Result != Legalized)
       return Result;
     MI.eraseFromParent();
@@ -1512,22 +1506,21 @@ LegalizerHelper::libcall(MachineInstr &MI, 
LostDebugLocObserver &LocObserver) {
   }
   case TargetOpcode::G_GET_FPENV:
   case TargetOpcode::G_GET_FPMODE: {
-    LegalizeResult Result = createGetStateLibcall(MIRBuilder, MI, LocObserver);
+    LegalizeResult Result = createGetStateLibcall(MI, LocObserver);
     if (Result != Legalized)
       return Result;
     break;
   }
   case TargetOpcode::G_SET_FPENV:
   case TargetOpcode::G_SET_FPMODE: {
-    LegalizeResult Result = createSetStateLibcall(MIRBuilder, MI, LocObserver);
+    LegalizeResult Result = createSetStateLibcall(MI, LocObserver);
     if (Result != Legalized)
       return Result;
     break;
   }
   case TargetOpcode::G_RESET_FPENV:
   case TargetOpcode::G_RESET_FPMODE: {
-    LegalizeResult Result =
-        createResetStateLibcall(MIRBuilder, MI, LocObserver);
+    LegalizeResult Result = createResetStateLibcall(MI, LocObserver);
     if (Result != Legalized)
       return Result;
     break;
diff --git a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp 
b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
index cdff649ecfa57..ad3e4f116321b 100644
--- a/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -365,10 +365,10 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper 
&Helper, MachineInstr &MI,
     StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ 
true);
     Register RetRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),
                           OriginalResult};
-    auto Status = createLibcall(MIRBuilder, Libcall, {RetRegs, RetTy, 0},
-                                {{MI.getOperand(1).getReg(), ArgTy, 0},
-                                 {MI.getOperand(2).getReg(), ArgTy, 0}},
-                                LocObserver, &MI);
+    auto Status = Helper.createLibcall(Libcall, {RetRegs, RetTy, 0},
+                                       {{MI.getOperand(1).getReg(), ArgTy, 0},
+                                        {MI.getOperand(2).getReg(), ArgTy, 0}},
+                                       LocObserver, &MI);
     if (Status != LegalizerHelper::Legalized)
       return false;
     break;
@@ -401,11 +401,11 @@ bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper 
&Helper, MachineInstr &MI,
     SmallVector<Register, 2> Results;
     for (auto Libcall : Libcalls) {
       auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
-      auto Status = createLibcall(MIRBuilder, Libcall.LibcallID,
-                                  {LibcallResult, RetTy, 0},
-                                  {{MI.getOperand(2).getReg(), ArgTy, 0},
-                                   {MI.getOperand(3).getReg(), ArgTy, 0}},
-                                  LocObserver, &MI);
+      auto Status =
+          Helper.createLibcall(Libcall.LibcallID, {LibcallResult, RetTy, 0},
+                               {{MI.getOperand(2).getReg(), ArgTy, 0},
+                                {MI.getOperand(3).getReg(), ArgTy, 0}},
+                               LocObserver, &MI);
 
       if (Status != LegalizerHelper::Legalized)
         return false;
diff --git a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h 
b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
index 4b82f572150e5..dbea3f608a881 100644
--- a/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
+++ b/llvm/unittests/CodeGen/GlobalISel/GISelMITest.h
@@ -124,6 +124,8 @@ class GISelMITest : public ::testing::Test {
     B.setMF(*MF);
     MRI = &MF->getRegInfo();
     B.setInsertPt(*EntryMBB, EntryMBB->end());
+    RTLCI.emplace(TM->getTargetTriple());
+    LibcallLowering.emplace(*RTLCI, MF->getSubtarget());
   }
 
   LLVMContext Context;
@@ -135,6 +137,8 @@ class GISelMITest : public ::testing::Test {
   MachineBasicBlock *EntryMBB;
   MachineIRBuilder B;
   MachineRegisterInfo *MRI;
+  std::optional<RTLIB::RuntimeLibcallsInfo> RTLCI;
+  std::optional<LibcallLoweringInfo> LibcallLowering;
 };
 
 class AArch64GISelMITest : public GISelMITest {
diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp 
b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
index 22181ce33f0da..f80082fdd46d0 100644
--- a/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
@@ -2050,7 +2050,7 @@ TEST_F(AArch64GISelMITest, LibcallFPExt) {
       B.buildInstr(TargetOpcode::G_FPEXT, {S128}, {Copies[1]});
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
               Helper.libcall(*MIBFPExt1, DummyLocObserver));
@@ -2094,7 +2094,7 @@ TEST_F(AArch64GISelMITest, LibcallFPTrunc) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBFPTrunc1, DummyLocObserver));
 
@@ -2162,7 +2162,7 @@ TEST_F(AArch64GISelMITest, LibcallMul) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBMul32, DummyLocObserver));
@@ -2220,7 +2220,7 @@ TEST_F(AArch64GISelMITest, LibcallSRem) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBSRem32, DummyLocObserver));
@@ -2278,7 +2278,7 @@ TEST_F(AArch64GISelMITest, LibcallURem) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBURem32, DummyLocObserver));
@@ -2337,7 +2337,7 @@ TEST_F(AArch64GISelMITest, LibcallCtlzZeroUndef) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBCtlz32, DummyLocObserver));
@@ -2389,7 +2389,7 @@ TEST_F(AArch64GISelMITest, LibcallFAdd) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBAdd32, DummyLocObserver));
@@ -2442,7 +2442,7 @@ TEST_F(AArch64GISelMITest, LibcallFSub) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBSub32, DummyLocObserver));
@@ -2494,7 +2494,7 @@ TEST_F(AArch64GISelMITest, LibcallFMul) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -2548,7 +2548,7 @@ TEST_F(AArch64GISelMITest, LibcallFDiv) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBDiv32, DummyLocObserver));
@@ -2599,7 +2599,7 @@ TEST_F(AArch64GISelMITest, LibcallFExp) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBExp32, DummyLocObserver));
@@ -2647,7 +2647,7 @@ TEST_F(AArch64GISelMITest, LibcallFExp2) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBExp232, DummyLocObserver));
@@ -2695,7 +2695,7 @@ TEST_F(AArch64GISelMITest, LibcallFRem) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBFRem32, DummyLocObserver));
@@ -2743,7 +2743,7 @@ TEST_F(AArch64GISelMITest, LibcallFPow) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBPow32, DummyLocObserver));
@@ -2792,7 +2792,7 @@ TEST_F(AArch64GISelMITest, LibcallFMa) {
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
   LostDebugLocObserver DummyLocObserver("");
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.libcall(*MIBMa32, DummyLocObserver));
@@ -2839,7 +2839,7 @@ TEST_F(AArch64GISelMITest, LibcallFCeil) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -2887,7 +2887,7 @@ TEST_F(AArch64GISelMITest, LibcallFFloor) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -2935,7 +2935,7 @@ TEST_F(AArch64GISelMITest, LibcallFMinNum) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -2986,7 +2986,7 @@ TEST_F(AArch64GISelMITest, LibcallFMaxNum) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -3037,7 +3037,7 @@ TEST_F(AArch64GISelMITest, LibcallFSqrt) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -3085,7 +3085,7 @@ TEST_F(AArch64GISelMITest, LibcallFRint) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -3136,7 +3136,7 @@ TEST_F(AArch64GISelMITest, LibcallFNearbyInt) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   LostDebugLocObserver DummyLocObserver("");
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -3181,7 +3181,7 @@ TEST_F(AArch64GISelMITest, NarrowScalarExtract) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.narrowScalar(*MIBExtractS32, 1, S32));
@@ -3229,7 +3229,7 @@ TEST_F(AArch64GISelMITest, LowerInsert) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.lower(*InsertS64S32, 0, LLT{}));
@@ -3307,7 +3307,7 @@ TEST_F(AArch64GISelMITest, LowerFFloor) {
   auto Floor = B.buildFFloor(LLT::scalar(64), Copies[0], 
MachineInstr::MIFlag::FmNoInfs);
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   // Perform Legalization
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.lower(*Floor, 0, LLT()));
@@ -3340,7 +3340,7 @@ TEST_F(AArch64GISelMITest, LowerBSWAP) {
   auto BSwap = B.buildBSwap(LLT::fixed_vector(2, 32), Cast);
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   // Perform Legalization
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.lower(*BSwap, 0, LLT()));
@@ -3417,7 +3417,7 @@ TEST_F(AArch64GISelMITest, LowerUDIVREM) {
       B.buildInstr(TargetOpcode::G_UDIVREM, {S64, S64}, {Copies[0], 
Copies[1]});
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   // Perform Legalization
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.lower(*UDivrem, 0, S64));
@@ -3451,7 +3451,7 @@ TEST_F(AArch64GISelMITest, LowerSelect) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
   // Perform Legalization
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
             Helper.lower(*SELECT, 0, S32));
@@ -3492,7 +3492,7 @@ TEST_F(AArch64GISelMITest, WidenUnmerge) {
 
   AInfo Info(MF->getSubtarget());
   DummyGISelObserver Observer;
-  LegalizerHelper Helper(*MF, Info, Observer, B);
+  LegalizerHelper Helper(*MF, Info, Observer, B, &*LibcallLowering);
 
   // Perform Legalization
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
@@ -3701,10 +3701,11 @@ TEST_F(AArch64GISelMITest, CreateLibcall) {
 
   LLVMContext &Ctx = MF->getFunction().getContext();
   auto *RetTy = Type::getVoidTy(Ctx);
+  LegalizerHelper Helper(*MF, Info, Observer, B);
 
   EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
-            createLibcall(B, "abort", {{}, RetTy, 0}, {}, CallingConv::C,
-                          DummyLocObserver, nullptr));
+            Helper.createLibcall("abort", {{}, RetTy, 0}, {}, CallingConv::C,
+                                 DummyLocObserver, nullptr));
 
   auto CheckStr = R"(
   CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
diff --git a/llvm/unittests/CodeGen/GlobalISel/LegalizerTest.cpp 
b/llvm/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
index c5992ebb831ed..1c90267ed28aa 100644
--- a/llvm/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
@@ -69,7 +69,7 @@ TEST_F(AArch64GISelMITest, BasicLegalizerTest) {
   GISelValueTracking VT(*MF);
 
   Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
-      *MF, LI, {&LocObserver}, LocObserver, B, &VT);
+      *MF, LI, {&LocObserver}, LocObserver, B, /*Libcalls=*/nullptr, &VT);
 
   EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
   EXPECT_TRUE(Result.Changed);
@@ -161,7 +161,7 @@ TEST_F(AArch64GISelMITest, UnorderedArtifactCombiningTest) {
   //  the process follows def-use chains, making them shorter at each step, 
thus
   //  combining everything that can be combined in O(n) time.
   Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
-      *MF, LI, {&LocObserver}, LocObserver, B, &VT);
+      *MF, LI, {&LocObserver}, LocObserver, B, /*Libcalls=*/nullptr, &VT);
 
   EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
   EXPECT_TRUE(Result.Changed);
@@ -201,7 +201,7 @@ TEST_F(AArch64GISelMITest, 
UnorderedArtifactCombiningManyCopiesTest) {
   GISelValueTracking VT(*MF);
 
   Legalizer::MFResult Result = Legalizer::legalizeMachineFunction(
-      *MF, LI, {&LocObserver}, LocObserver, B, &VT);
+      *MF, LI, {&LocObserver}, LocObserver, B, /*Libcalls=*/nullptr, &VT);
 
   EXPECT_TRUE(isNullMIPtr(Result.FailedOn));
   EXPECT_TRUE(Result.Changed);

>From 0c95e55bac4cd77541831cf031c8549d97d21c9b Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Tue, 25 Nov 2025 11:16:33 -0500
Subject: [PATCH 2/2] Old pass manager hacking

---
 llvm/include/llvm/Analysis/RuntimeLibcallInfo.h |  2 ++
 llvm/include/llvm/CodeGen/LibcallLoweringInfo.h | 16 +++++++++++-----
 llvm/include/llvm/CodeGen/Passes.h              |  2 ++
 llvm/lib/CodeGen/ExpandFp.cpp                   |  2 +-
 llvm/lib/CodeGen/GlobalISel/Legalizer.cpp       |  3 ++-
 llvm/lib/CodeGen/LibcallLoweringInfo.cpp        |  9 ++++++---
 llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp   |  2 +-
 llvm/lib/CodeGen/TargetPassConfig.cpp           |  2 ++
 8 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/Analysis/RuntimeLibcallInfo.h 
b/llvm/include/llvm/Analysis/RuntimeLibcallInfo.h
index 2d31c8aa6301b..b0f398d6e2b28 100644
--- a/llvm/include/llvm/Analysis/RuntimeLibcallInfo.h
+++ b/llvm/include/llvm/Analysis/RuntimeLibcallInfo.h
@@ -32,6 +32,8 @@ class LLVM_ABI RuntimeLibraryAnalysis
   LLVM_ABI RTLIB::RuntimeLibcallsInfo run(const Module &M,
                                           ModuleAnalysisManager &);
 
+  operator bool() const { return LibcallsInfo.has_value(); }
+
 private:
   friend AnalysisInfoMixin<RuntimeLibraryAnalysis>;
   LLVM_ABI static AnalysisKey Key;
diff --git a/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h 
b/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
index 3e0137710e8eb..47c0dd315d3b5 100644
--- a/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
+++ b/llvm/include/llvm/CodeGen/LibcallLoweringInfo.h
@@ -10,11 +10,12 @@
 #define LLVM_CODEGEN_LIBCALLLOWERINGINFO_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/RuntimeLibcallInfo.h"
 #include "llvm/IR/RuntimeLibcalls.h"
 #include "llvm/Pass.h"
 
 namespace llvm {
-
+class RuntimeLibraryInfoWrapper;
 class TargetSubtargetInfo;
 class TargetMachine;
 
@@ -97,6 +98,8 @@ class LibcallLoweringModuleAnalysisResult {
     LoweringMap.clear();
   }
 
+  operator bool() const { return RTLCI != nullptr; }
+
   LLVM_ABI bool invalidate(Module &, const PreservedAnalyses &,
                            ModuleAnalysisManager::Invalidator &);
 
@@ -122,21 +125,24 @@ class LibcallLoweringModuleAnalysis
 
 class LLVM_ABI LibcallLoweringInfoWrapper : public ImmutablePass {
   LibcallLoweringModuleAnalysisResult Result;
+  RuntimeLibraryInfoWrapper *RuntimeLibcallsWrapper = nullptr;
 
 public:
   static char ID;
   LibcallLoweringInfoWrapper();
 
   const LibcallLoweringInfo &
-  getLibcallLowering(const TargetSubtargetInfo &Subtarget) const {
-    return Result.getLibcallLowering(Subtarget);
+  getLibcallLowering(const Module &M, const TargetSubtargetInfo &Subtarget) {
+    return getResult(M).getLibcallLowering(Subtarget);
   }
 
-  const LibcallLoweringModuleAnalysisResult &getResult() const {
+  const LibcallLoweringModuleAnalysisResult &getResult(const Module &M) {
+    if (!Result)
+      Result.init(&RuntimeLibcallsWrapper->getRTLCI(M));
     return Result;
   }
 
-  bool doInitialization(Module &M) override;
+  void initializePass() override;
   void getAnalysisUsage(AnalysisUsage &AU) const override;
   void releaseMemory() override;
 };
diff --git a/llvm/include/llvm/CodeGen/Passes.h 
b/llvm/include/llvm/CodeGen/Passes.h
index a8525554b142e..168be429e13a6 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -487,6 +487,8 @@ LLVM_ABI FunctionPass *createInterleavedLoadCombinePass();
 ///
 LLVM_ABI ModulePass *createLowerEmuTLSPass();
 
+LLVM_ABI ModulePass *createLibcallLoweringInfoWrapper();
+
 /// This pass lowers the \@llvm.load.relative and \@llvm.objc.* intrinsics to
 /// instructions.  This is unsafe to do earlier because a pass may combine the
 /// constant initializer into the load, which may result in an overflowing
diff --git a/llvm/lib/CodeGen/ExpandFp.cpp b/llvm/lib/CodeGen/ExpandFp.cpp
index 13ed4846d2bf7..7d333be7ed6fc 100644
--- a/llvm/lib/CodeGen/ExpandFp.cpp
+++ b/llvm/lib/CodeGen/ExpandFp.cpp
@@ -1097,7 +1097,7 @@ class ExpandFpLegacyPass : public FunctionPass {
 
     const LibcallLoweringInfo &Libcalls =
         getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
-            *Subtarget);
+            *F.getParent(), *Subtarget);
 
     if (OptLevel != CodeGenOptLevel::None && !F.hasOptNone())
       AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
diff --git a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp 
b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
index ce2d9749f3fdc..711f7a0b5c35b 100644
--- a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp
@@ -343,7 +343,8 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
   const TargetSubtargetInfo &Subtarget = MF.getSubtarget();
 
   const LibcallLoweringInfo &Libcalls =
-      getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(Subtarget);
+      getAnalysis<LibcallLoweringInfoWrapper>().getLibcallLowering(
+          *MF.getFunction().getParent(), Subtarget);
 
   // This allows Known Bits Analysis in the legalizer.
   GISelValueTracking *VT =
diff --git a/llvm/lib/CodeGen/LibcallLoweringInfo.cpp 
b/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
index 0d54fac2422e2..388d2b009a9ef 100644
--- a/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/LibcallLoweringInfo.cpp
@@ -59,9 +59,8 @@ char LibcallLoweringInfoWrapper::ID = 0;
 
 LibcallLoweringInfoWrapper::LibcallLoweringInfoWrapper() : ImmutablePass(ID) {}
 
-bool LibcallLoweringInfoWrapper::doInitialization(Module &M) {
-  Result.init(&getAnalysis<RuntimeLibraryInfoWrapper>().getRTLCI(M));
-  return false;
+void LibcallLoweringInfoWrapper::initializePass() {
+  RuntimeLibcallsWrapper = &getAnalysis<RuntimeLibraryInfoWrapper>();
 }
 
 void LibcallLoweringInfoWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
@@ -70,3 +69,7 @@ void 
LibcallLoweringInfoWrapper::getAnalysisUsage(AnalysisUsage &AU) const {
 }
 
 void LibcallLoweringInfoWrapper::releaseMemory() { Result.clear(); }
+
+ModulePass *llvm::createLibcallLoweringInfoWrapper() {
+  return new LibcallLoweringInfoWrapper();
+}
diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp 
b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
index 72c3c566163e2..2336bb1f05be3 100644
--- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp
@@ -635,7 +635,7 @@ class PreISelIntrinsicLoweringLegacyPass : public 
ModulePass {
 
   bool runOnModule(Module &M) override {
     const LibcallLoweringModuleAnalysisResult &ModuleLibcalls =
-        getAnalysis<LibcallLoweringInfoWrapper>().getResult();
+        getAnalysis<LibcallLoweringInfoWrapper>().getResult(M);
 
     auto LookupTTI = [this](Function &F) -> TargetTransformInfo & {
       return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp 
b/llvm/lib/CodeGen/TargetPassConfig.cpp
index ceae0d29eea90..a791c4038a3b9 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -599,6 +599,8 @@ TargetPassConfig::TargetPassConfig(TargetMachine &TM, 
PassManagerBase &PM)
   // including this pass itself.
   initializeCodeGen(PR);
 
+  initializeLibcallLoweringInfoWrapperPass(PR);
+
   // Also register alias analysis passes required by codegen passes.
   initializeBasicAAWrapperPassPass(PR);
   initializeAAResultsWrapperPassPass(PR);

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to