[llvm] 732d841 - [GISel][NewPM] Port RegBankSelect

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 14:51:56 PDT 2026


Author: Aiden Grossman
Date: 2026-08-20T14:51:51-07:00
New Revision: 732d8413c69b57a10de1beb1964a57a9264b23b9

URL: https://github.com/llvm/llvm-project/commit/732d8413c69b57a10de1beb1964a57a9264b23b9
DIFF: https://github.com/llvm/llvm-project/commit/732d8413c69b57a10de1beb1964a57a9264b23b9.diff

LOG: [GISel][NewPM] Port RegBankSelect

Standard NewPM pass porting. A little bit more analysis plumbing than
normal.

* Plumb both Pass*/MachineFunctionAnalysisManager* for critical edge
  splitting analysis updates.
* Plumb through functions to get MBFI/MBPI both cached and non-cached.
* Move the Impl class to the C++ file to try and keep the size of
  RegBankSelect.h small.

Reviewers: arsenm, mshockwave, aemerson, lenary, wangpc-pp

Pull Request: https://github.com/llvm/llvm-project/pull/217756

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
    llvm/include/llvm/InitializePasses.h
    llvm/include/llvm/Passes/MachinePassRegistry.def
    llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
    llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
    llvm/lib/Passes/PassBuilder.cpp
    llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
    llvm/lib/Target/ARM/ARMTargetMachine.cpp
    llvm/lib/Target/BPF/BPFTargetMachine.cpp
    llvm/lib/Target/Mips/MipsTargetMachine.cpp
    llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
    llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
    llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
    llvm/lib/Target/X86/X86TargetMachine.cpp
    llvm/test/CodeGen/AArch64/GlobalISel/regbank-ceil.mir

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
index 1b8f3c86e084c..3ba4d382451f4 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
@@ -64,558 +64,34 @@
 #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
 #define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
 
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
-#include "llvm/CodeGen/RegisterBankInfo.h"
-#include <cassert>
-#include <cstdint>
-#include <memory>
+#include "llvm/IR/Analysis.h"
+#include "llvm/IR/PassManager.h"
 
 namespace llvm {
 
-class BlockFrequency;
-class MachineBlockFrequencyInfo;
-class MachineBranchProbabilityInfo;
-class MachineOperand;
-class MachineRegisterInfo;
-class Pass;
-class raw_ostream;
-class TargetPassConfig;
-class TargetRegisterInfo;
+/// List of the modes supported by the RegBankSelect pass.
+enum RegBankSelectMode {
+  /// Assign the register banks as fast as possible (default).
+  Fast,
+  /// Greedily minimize the cost of assigning register banks.
+  /// This should produce code of greater quality, but will
+  /// require more compile time.
+  Greedy
+};
 
 /// This pass implements the reg bank selector pass used in the GlobalISel
 /// pipeline. At the end of this pass, all register operands have been assigned
-class LLVM_ABI RegBankSelect : public MachineFunctionPass {
+class LLVM_ABI RegBankSelectLegacy : public MachineFunctionPass {
+  RegBankSelectMode OptMode;
+
 public:
   static char ID;
 
-  /// List of the modes supported by the RegBankSelect pass.
-  enum Mode {
-    /// Assign the register banks as fast as possible (default).
-    Fast,
-    /// Greedily minimize the cost of assigning register banks.
-    /// This should produce code of greater quality, but will
-    /// require more compile time.
-    Greedy
-  };
-
-  /// Abstract class used to represent an insertion point in a CFG.
-  /// This class records an insertion point and materializes it on
-  /// demand.
-  /// It allows to reason about the frequency of this insertion point,
-  /// without having to logically materialize it (e.g., on an edge),
-  /// before we actually need to insert something.
-  class InsertPoint {
-  protected:
-    /// Tell if the insert point has already been materialized.
-    bool WasMaterialized = false;
-
-    /// Materialize the insertion point.
-    ///
-    /// If isSplit() is true, this involves actually splitting
-    /// the block or edge.
-    ///
-    /// \post getPointImpl() returns a valid iterator.
-    /// \post getInsertMBBImpl() returns a valid basic block.
-    /// \post isSplit() == false ; no more splitting should be required.
-    virtual void materialize() = 0;
-
-    /// Return the materialized insertion basic block.
-    /// Code will be inserted into that basic block.
-    ///
-    /// \pre ::materialize has been called.
-    virtual MachineBasicBlock &getInsertMBBImpl() = 0;
-
-    /// Return the materialized insertion point.
-    /// Code will be inserted before that point.
-    ///
-    /// \pre ::materialize has been called.
-    virtual MachineBasicBlock::iterator getPointImpl() = 0;
-
-  public:
-    virtual ~InsertPoint() = default;
-
-    /// The first call to this method will cause the splitting to
-    /// happen if need be, then sub sequent calls just return
-    /// the iterator to that point. I.e., no more splitting will
-    /// occur.
-    ///
-    /// \return The iterator that should be used with
-    /// MachineBasicBlock::insert. I.e., additional code happens
-    /// before that point.
-    MachineBasicBlock::iterator getPoint() {
-      if (!WasMaterialized) {
-        WasMaterialized = true;
-        assert(canMaterialize() && "Impossible to materialize this point");
-        materialize();
-      }
-      // When we materialized the point we should have done the splitting.
-      assert(!isSplit() && "Wrong pre-condition");
-      return getPointImpl();
-    }
-
-    /// The first call to this method will cause the splitting to
-    /// happen if need be, then sub sequent calls just return
-    /// the basic block that contains the insertion point.
-    /// I.e., no more splitting will occur.
-    ///
-    /// \return The basic block should be used with
-    /// MachineBasicBlock::insert and ::getPoint. The new code should
-    /// happen before that point.
-    MachineBasicBlock &getInsertMBB() {
-      if (!WasMaterialized) {
-        WasMaterialized = true;
-        assert(canMaterialize() && "Impossible to materialize this point");
-        materialize();
-      }
-      // When we materialized the point we should have done the splitting.
-      assert(!isSplit() && "Wrong pre-condition");
-      return getInsertMBBImpl();
-    }
-
-    /// Insert \p MI in the just before ::getPoint()
-    MachineBasicBlock::iterator insert(MachineInstr &MI) {
-      return getInsertMBB().insert(getPoint(), &MI);
-    }
-
-    /// Does this point involve splitting an edge or block?
-    /// As soon as ::getPoint is called and thus, the point
-    /// materialized, the point will not require splitting anymore,
-    /// i.e., this will return false.
-    virtual bool isSplit() const { return false; }
-
-    /// Frequency of the insertion point.
-    /// \p P is used to access the various analysis that will help to
-    /// get that information, like MachineBlockFrequencyInfo.  If \p P
-    /// does not contain enough to return the actual frequency,
-    /// this returns 1.
-    virtual uint64_t frequency(const Pass &P) const { return 1; }
-
-    /// Check whether this insertion point can be materialized.
-    /// As soon as ::getPoint is called and thus, the point materialized
-    /// calling this method does not make sense.
-    virtual bool canMaterialize() const { return false; }
-  };
-
-  /// Insertion point before or after an instruction.
-  class LLVM_ABI InstrInsertPoint : public InsertPoint {
-  private:
-    /// Insertion point.
-    MachineInstr &Instr;
-
-    /// Does the insertion point is before or after Instr.
-    bool Before;
-
-    void materialize() override;
-
-    MachineBasicBlock::iterator getPointImpl() override {
-      if (Before)
-        return Instr;
-      return Instr.getNextNode() ? *Instr.getNextNode()
-                                 : Instr.getParent()->end();
-    }
-
-    MachineBasicBlock &getInsertMBBImpl() override {
-      return *Instr.getParent();
-    }
-
-  public:
-    /// Create an insertion point before (\p Before=true) or after \p Instr.
-    InstrInsertPoint(MachineInstr &Instr, bool Before = true);
-
-    bool isSplit() const override;
-    uint64_t frequency(const Pass &P) const override;
-
-    // Worst case, we need to slice the basic block, but that is still doable.
-    bool canMaterialize() const override { return true; }
-  };
-
-  /// Insertion point at the beginning or end of a basic block.
-  class LLVM_ABI MBBInsertPoint : public InsertPoint {
-  private:
-    /// Insertion point.
-    MachineBasicBlock &MBB;
-
-    /// Does the insertion point is at the beginning or end of MBB.
-    bool Beginning;
-
-    void materialize() override { /*Nothing to do to materialize*/
-    }
-
-    MachineBasicBlock::iterator getPointImpl() override {
-      return Beginning ? MBB.begin() : MBB.end();
-    }
-
-    MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
-
-  public:
-    MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
-        : MBB(MBB), Beginning(Beginning) {
-      // If we try to insert before phis, we should use the insertion
-      // points on the incoming edges.
-      assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
-             "Invalid beginning point");
-      // If we try to insert after the terminators, we should use the
-      // points on the outcoming edges.
-      assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
-             "Invalid end point");
-    }
-
-    bool isSplit() const override { return false; }
-    uint64_t frequency(const Pass &P) const override;
-    bool canMaterialize() const override { return true; };
-  };
-
-  /// Insertion point on an edge.
-  class LLVM_ABI EdgeInsertPoint : public InsertPoint {
-  private:
-    /// Source of the edge.
-    MachineBasicBlock &Src;
-
-    /// Destination of the edge.
-    /// After the materialization is done, this hold the basic block
-    /// that resulted from the splitting.
-    MachineBasicBlock *DstOrSplit;
-
-    /// P is used to update the analysis passes as applicable.
-    Pass &P;
-
-    void materialize() override;
-
-    MachineBasicBlock::iterator getPointImpl() override {
-      // DstOrSplit should be the Split block at this point.
-      // I.e., it should have one predecessor, Src, and one successor,
-      // the original Dst.
-      assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
-             DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
-             "Did not split?!");
-      return DstOrSplit->begin();
-    }
-
-    MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
-
-  public:
-    EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
-        : Src(Src), DstOrSplit(&Dst), P(P) {}
-
-    bool isSplit() const override {
-      return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
-    }
-
-    uint64_t frequency(const Pass &P) const override;
-    bool canMaterialize() const override;
-  };
-
-  /// Struct used to represent the placement of a repairing point for
-  /// a given operand.
-  class RepairingPlacement {
-  public:
-    /// Define the kind of action this repairing needs.
-    enum RepairingKind {
-      /// Nothing to repair, just drop this action.
-      None,
-      /// Reparing code needs to happen before InsertPoints.
-      Insert,
-      /// (Re)assign the register bank of the operand.
-      Reassign,
-      /// Mark this repairing placement as impossible.
-      Impossible
-    };
-
-    /// \name Convenient types for a list of insertion points.
-    /// @{
-    using InsertionPoints = SmallVector<std::unique_ptr<InsertPoint>, 2>;
-    using insertpt_iterator = InsertionPoints::iterator;
-    using const_insertpt_iterator = InsertionPoints::const_iterator;
-    /// @}
-
-  private:
-    /// Kind of repairing.
-    RepairingKind Kind;
-    /// Index of the operand that will be repaired.
-    unsigned OpIdx;
-    /// Are all the insert points materializeable?
-    bool CanMaterialize;
-    /// Is there any of the insert points needing splitting?
-    bool HasSplit = false;
-    /// Insertion point for the repair code.
-    /// The repairing code needs to happen just before these points.
-    InsertionPoints InsertPoints;
-    /// Some insertion points may need to update the liveness and such.
-    Pass &P;
-
-  public:
-    /// Create a repairing placement for the \p OpIdx-th operand of
-    /// \p MI. \p TRI is used to make some checks on the register aliases
-    /// if the machine operand is a physical register. \p P is used to
-    /// to update liveness information and such when materializing the
-    /// points.
-    LLVM_ABI RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
-                                const TargetRegisterInfo &TRI, Pass &P,
-                                RepairingKind Kind = RepairingKind::Insert);
-
-    /// \name Getters.
-    /// @{
-    RepairingKind getKind() const { return Kind; }
-    unsigned getOpIdx() const { return OpIdx; }
-    bool canMaterialize() const { return CanMaterialize; }
-    bool hasSplit() { return HasSplit; }
-    /// @}
-
-    /// \name Overloaded methods to add an insertion point.
-    /// @{
-    /// Add a MBBInsertionPoint to the list of InsertPoints.
-    LLVM_ABI void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
-    /// Add a InstrInsertionPoint to the list of InsertPoints.
-    LLVM_ABI void addInsertPoint(MachineInstr &MI, bool Before);
-    /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
-    LLVM_ABI void addInsertPoint(MachineBasicBlock &Src,
-                                 MachineBasicBlock &Dst);
-    /// Add an InsertPoint to the list of insert points.
-    /// This method takes the ownership of &\p Point.
-    LLVM_ABI void addInsertPoint(InsertPoint &Point);
-    /// @}
-
-    /// \name Accessors related to the insertion points.
-    /// @{
-    insertpt_iterator begin() { return InsertPoints.begin(); }
-    insertpt_iterator end() { return InsertPoints.end(); }
-
-    const_insertpt_iterator begin() const { return InsertPoints.begin(); }
-    const_insertpt_iterator end() const { return InsertPoints.end(); }
-
-    unsigned getNumInsertPoints() const { return InsertPoints.size(); }
-    /// @}
-
-    /// Change the type of this repairing placement to \p NewKind.
-    /// It is not possible to switch a repairing placement to the
-    /// RepairingKind::Insert. There is no fundamental problem with
-    /// that, but no uses as well, so do not support it for now.
-    ///
-    /// \pre NewKind != RepairingKind::Insert
-    /// \post getKind() == NewKind
-    void switchTo(RepairingKind NewKind) {
-      assert(NewKind != Kind && "Already of the right Kind");
-      Kind = NewKind;
-      InsertPoints.clear();
-      CanMaterialize = NewKind != RepairingKind::Impossible;
-      HasSplit = false;
-      assert(NewKind != RepairingKind::Insert &&
-             "We would need more MI to switch to Insert");
-    }
-  };
-
-protected:
-  /// Helper class used to represent the cost for mapping an instruction.
-  /// When mapping an instruction, we may introduce some repairing code.
-  /// In most cases, the repairing code is local to the instruction,
-  /// thus, we can omit the basic block frequency from the cost.
-  /// However, some alternatives may produce non-local cost, e.g., when
-  /// repairing a phi, and thus we then need to scale the local cost
-  /// to the non-local cost. This class does this for us.
-  /// \note: We could simply always scale the cost. The problem is that
-  /// there are higher chances that we saturate the cost easier and end
-  /// up having the same cost for actually 
diff erent alternatives.
-  /// Another option would be to use APInt everywhere.
-  class MappingCost {
-  private:
-    /// Cost of the local instructions.
-    /// This cost is free of basic block frequency.
-    uint64_t LocalCost = 0;
-    /// Cost of the non-local instructions.
-    /// This cost should include the frequency of the related blocks.
-    uint64_t NonLocalCost = 0;
-    /// Frequency of the block where the local instructions live.
-    uint64_t LocalFreq;
-
-    MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
-        : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
-          LocalFreq(LocalFreq) {}
-
-    /// Check if this cost is saturated.
-    bool isSaturated() const;
-
-  public:
-    /// Create a MappingCost assuming that most of the instructions
-    /// will occur in a basic block with \p LocalFreq frequency.
-    LLVM_ABI MappingCost(BlockFrequency LocalFreq);
-
-    /// Add \p Cost to the local cost.
-    /// \return true if this cost is saturated, false otherwise.
-    LLVM_ABI bool addLocalCost(uint64_t Cost);
-
-    /// Add \p Cost to the non-local cost.
-    /// Non-local cost should reflect the frequency of their placement.
-    /// \return true if this cost is saturated, false otherwise.
-    LLVM_ABI bool addNonLocalCost(uint64_t Cost);
-
-    /// Saturate the cost to the maximal representable value.
-    LLVM_ABI void saturate();
-
-    /// Return an instance of MappingCost that represents an
-    /// impossible mapping.
-    LLVM_ABI static MappingCost ImpossibleCost();
-
-    /// Check if this is less than \p Cost.
-    LLVM_ABI bool operator<(const MappingCost &Cost) const;
-    /// Check if this is equal to \p Cost.
-    LLVM_ABI bool operator==(const MappingCost &Cost) const;
-    /// Check if this is not equal to \p Cost.
-    bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
-    /// Check if this is greater than \p Cost.
-    bool operator>(const MappingCost &Cost) const {
-      return *this != Cost && Cost < *this;
-    }
-
-    /// Print this on dbgs() stream.
-    LLVM_ABI void dump() const;
-
-    /// Print this on \p OS;
-    LLVM_ABI void print(raw_ostream &OS) const;
-
-    /// Overload the stream operator for easy debug printing.
-    friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) {
-      Cost.print(OS);
-      return OS;
-    }
-  };
-
-  /// Interface to the target lowering info related
-  /// to register banks.
-  const RegisterBankInfo *RBI = nullptr;
-
-  /// MRI contains all the register class/bank information that this
-  /// pass uses and updates.
-  MachineRegisterInfo *MRI = nullptr;
-
-  /// Information on the register classes for the current function.
-  const TargetRegisterInfo *TRI = nullptr;
-
-  /// Get the frequency of blocks.
-  /// This is required for non-fast mode.
-  MachineBlockFrequencyInfo *MBFI = nullptr;
-
-  /// Get the frequency of the edges.
-  /// This is required for non-fast mode.
-  MachineBranchProbabilityInfo *MBPI = nullptr;
-
-  /// Current optimization remark emitter. Used to report failures.
-  std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
-
-  /// Helper class used for every code morphing.
-  MachineIRBuilder MIRBuilder;
-
-  /// Optimization mode of the pass.
-  Mode OptMode;
-
-  /// Assign the register bank of each operand of \p MI.
-  /// \return True on success, false otherwise.
-  bool assignInstr(MachineInstr &MI);
-
-  /// Initialize the field members using \p MF.
-  void init(MachineFunction &MF);
-
-  /// Check if \p Reg is already assigned what is described by \p ValMapping.
-  /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
-  /// register bank.  I.e., no repairing is necessary to have the
-  /// assignment match.
-  bool assignmentMatch(Register Reg,
-                       const RegisterBankInfo::ValueMapping &ValMapping,
-                       bool &OnlyAssign) const;
-
-  /// Insert repairing code for \p Reg as specified by \p ValMapping.
-  /// The repairing placement is specified by \p RepairPt.
-  /// \p NewVRegs contains all the registers required to remap \p Reg.
-  /// In other words, the number of registers in NewVRegs must be equal
-  /// to ValMapping.BreakDown.size().
-  ///
-  /// The transformation could be sketched as:
-  /// \code
-  /// ... = op Reg
-  /// \endcode
-  /// Becomes
-  /// \code
-  /// <NewRegs> = COPY or extract Reg
-  /// ... = op Reg
-  /// \endcode
-  ///
-  /// and
-  /// \code
-  /// Reg = op ...
-  /// \endcode
-  /// Becomes
-  /// \code
-  /// Reg = op ...
-  /// Reg = COPY or build_sequence <NewRegs>
-  /// \endcode
-  ///
-  /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
-  ///
-  /// \note The caller is supposed to do the rewriting of op if need be.
-  /// I.e., Reg = op ... => <NewRegs> = NewOp ...
-  ///
-  /// \return True if the repairing worked, false otherwise.
-  bool repairReg(MachineOperand &MO,
-                 const RegisterBankInfo::ValueMapping &ValMapping,
-                 RegBankSelect::RepairingPlacement &RepairPt,
-                 const iterator_range<SmallVectorImpl<Register>::const_iterator>
-                     &NewVRegs);
-
-  /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
-  /// The cost is free of basic block frequencies.
-  /// \pre MO.isReg()
-  /// \pre MO is assigned to a register bank.
-  /// \pre ValMapping is a valid mapping for MO.
-  uint64_t
-  getRepairCost(const MachineOperand &MO,
-                const RegisterBankInfo::ValueMapping &ValMapping) const;
-
-  /// Find the best mapping for \p MI from \p PossibleMappings.
-  /// \return a reference on the best mapping in \p PossibleMappings.
-  const RegisterBankInfo::InstructionMapping &
-  findBestMapping(MachineInstr &MI,
-                  RegisterBankInfo::InstructionMappings &PossibleMappings,
-                  SmallVectorImpl<RepairingPlacement> &RepairPts);
-
-  /// Compute the cost of mapping \p MI with \p InstrMapping and
-  /// compute the repairing placement for such mapping in \p
-  /// RepairPts.
-  /// \p BestCost is used to specify when the cost becomes too high
-  /// and thus it is not worth computing the RepairPts.  Moreover if
-  /// \p BestCost == nullptr, the mapping cost is actually not
-  /// computed.
-  MappingCost
-  computeMapping(MachineInstr &MI,
-                 const RegisterBankInfo::InstructionMapping &InstrMapping,
-                 SmallVectorImpl<RepairingPlacement> &RepairPts,
-                 const MappingCost *BestCost = nullptr);
-
-  /// When \p RepairPt involves splitting to repair \p MO for the
-  /// given \p ValMapping, try to change the way we repair such that
-  /// the splitting is not required anymore.
-  ///
-  /// \pre \p RepairPt.hasSplit()
-  /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
-  /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
-  ///      that implied \p RepairPt.
-  void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt,
-                        const MachineOperand &MO,
-                        const RegisterBankInfo::ValueMapping &ValMapping) const;
-
-  /// Apply \p Mapping to \p MI. \p RepairPts represents the 
diff erent
-  /// mapping action that need to happen for the mapping to be
-  /// applied.
-  /// \return True if the mapping was applied sucessfully, false otherwise.
-  bool applyMapping(MachineInstr &MI,
-                    const RegisterBankInfo::InstructionMapping &InstrMapping,
-                    SmallVectorImpl<RepairingPlacement> &RepairPts);
-
-public:
-  /// Create a RegBankSelect pass with the specified \p RunningMode.
-  RegBankSelect(Mode RunningMode = Fast);
+  RegBankSelectLegacy(RegBankSelectMode RunningMode = RegBankSelectMode::Fast);
 
   StringRef getPassName() const override { return "RegBankSelect"; }
 
@@ -633,38 +109,28 @@ class LLVM_ABI RegBankSelect : public MachineFunctionPass {
     return MachineFunctionProperties().setNoPHIs();
   }
 
-  /// Check that our input is fully legal: we require the function to have the
-  /// Legalized property, so it should be.
-  ///
-  /// FIXME: This should be in the MachineVerifier.
-  bool checkFunctionIsLegal(MachineFunction &MF) const;
+  bool runOnMachineFunction(MachineFunction &MF) override;
+};
+
+class RegBankSelectPass : public RequiredPassInfoMixin<RegBankSelectPass> {
+  RegBankSelectMode OptMode;
 
-  /// Walk through \p MF and assign a register bank to every virtual register
-  /// that are still mapped to nothing.
-  /// The target needs to provide a RegisterBankInfo and in particular
-  /// override RegisterBankInfo::getInstrMapping.
-  ///
-  /// Simplified algo:
-  /// \code
-  ///   RBI = MF.subtarget.getRegBankInfo()
-  ///   MIRBuilder.setMF(MF)
-  ///   for each bb in MF
-  ///     for each inst in bb
-  ///       MIRBuilder.setInstr(inst)
-  ///       MappingCosts = RBI.getMapping(inst);
-  ///       Idx = findIdxOfMinCost(MappingCosts)
-  ///       CurRegBank = MappingCosts[Idx].RegBank
-  ///       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
-  ///       for each argument in inst
-  ///         if (CurRegBank != argument.RegBank)
-  ///           ArgReg = argument.getReg()
-  ///           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
-  ///           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
-  ///           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
-  /// \endcode
-  bool assignRegisterBanks(MachineFunction &MF);
+public:
+  RegBankSelectPass(RegBankSelectMode RunningMode = RegBankSelectMode::Fast);
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM);
 
-  bool runOnMachineFunction(MachineFunction &MF) override;
+  MachineFunctionProperties getRequiredProperties() const {
+    return MachineFunctionProperties().setIsSSA().setLegalized();
+  }
+
+  MachineFunctionProperties getSetProperties() const {
+    return MachineFunctionProperties().setRegBankSelected();
+  }
+
+  MachineFunctionProperties getClearedProperties() const {
+    return MachineFunctionProperties().setNoPHIs();
+  }
 };
 
 } // end namespace llvm

diff  --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 29f82acbbca51..09530210dc535 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -275,7 +275,7 @@ LLVM_ABI void initializeRegAllocFastPass(PassRegistry &);
 LLVM_ABI void
 initializeRegAllocPriorityAdvisorAnalysisLegacyPass(PassRegistry &);
 LLVM_ABI void initializeRegAllocScoringPass(PassRegistry &);
-LLVM_ABI void initializeRegBankSelectPass(PassRegistry &);
+LLVM_ABI void initializeRegBankSelectLegacyPass(PassRegistry &);
 LLVM_ABI void initializeRegToMemWrapperPassPass(PassRegistry &);
 LLVM_ABI void initializeRegUsageInfoCollectorLegacyPass(PassRegistry &);
 LLVM_ABI void initializeRegUsageInfoPropagationLegacyPass(PassRegistry &);

diff  --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def
index a6addb7547073..58a4bbd09aeb5 100644
--- a/llvm/include/llvm/Passes/MachinePassRegistry.def
+++ b/llvm/include/llvm/Passes/MachinePassRegistry.def
@@ -133,6 +133,7 @@ MACHINE_FUNCTION_PASS("print<slot-indexes>", SlotIndexesPrinterPass(errs()))
 MACHINE_FUNCTION_PASS("print<virtregmap>", VirtRegMapPrinterPass(errs()))
 MACHINE_FUNCTION_PASS("process-imp-defs", ProcessImplicitDefsPass())
 MACHINE_FUNCTION_PASS("prolog-epilog", PrologEpilogInserterPass())
+MACHINE_FUNCTION_PASS("reg-bank-select", RegBankSelectPass())
 MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass())
 MACHINE_FUNCTION_PASS("reg-usage-propagation", RegUsageInfoPropagationPass())
 MACHINE_FUNCTION_PASS("register-coalescer", RegisterCoalescerPass())
@@ -256,7 +257,6 @@ DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass)
 DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass)
 DUMMY_MACHINE_FUNCTION_PASS("regalloc", RegAllocPass)
 DUMMY_MACHINE_FUNCTION_PASS("regallocscoringpass", RegAllocScoringPass)
-DUMMY_MACHINE_FUNCTION_PASS("regbankselect", RegBankSelectPass)
 DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function", ResetMachineFunctionPass)
 DUMMY_MACHINE_FUNCTION_PASS("stackmap-liveness", StackMapLivenessPass)
 #undef DUMMY_MACHINE_FUNCTION_PASS

diff  --git a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
index 8fe847eeafb2e..e669fbc4dced2 100644
--- a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp
@@ -19,7 +19,7 @@ void llvm::initializeGlobalISel(PassRegistry &Registry) {
   initializeLegalizerLegacyPass(Registry);
   initializeLoadStoreOptLegacyPass(Registry);
   initializeLocalizerLegacyPass(Registry);
-  initializeRegBankSelectPass(Registry);
+  initializeRegBankSelectLegacyPass(Registry);
   initializeInstructionSelectPass(Registry);
   initializeGISelValueTrackingAnalysisLegacyPass(Registry);
   initializeGISelCSEAnalysisWrapperPassPass(Registry);

diff  --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
index be5d2fa7d4df7..9405a6dbf0938 100644
--- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp
@@ -14,14 +14,17 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
 #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/MachinePassManager.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/RegisterBank.h"
 #include "llvm/CodeGen/RegisterBankInfo.h"
@@ -30,6 +33,7 @@
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/Config/llvm-config.h"
+#include "llvm/IR/Analysis.h"
 #include "llvm/IR/Function.h"
 #include "llvm/InitializePasses.h"
 #include "llvm/Pass.h"
@@ -58,42 +62,643 @@ using namespace llvm;
 static constexpr unsigned ImpossibleRepairCost =
     std::numeric_limits<unsigned>::max();
 
-static cl::opt<RegBankSelect::Mode> RegBankSelectMode(
+static cl::opt<RegBankSelectMode> RegBankSelectModeOption(
     cl::desc("Mode of the RegBankSelect pass"), cl::Hidden, cl::Optional,
-    cl::values(clEnumValN(RegBankSelect::Mode::Fast, "regbankselect-fast",
+    cl::values(clEnumValN(RegBankSelectMode::Fast, "regbankselect-fast",
                           "Run the Fast mode (default mapping)"),
-               clEnumValN(RegBankSelect::Mode::Greedy, "regbankselect-greedy",
+               clEnumValN(RegBankSelectMode::Greedy, "regbankselect-greedy",
                           "Use the Greedy mode (best local mapping)")));
 
-char RegBankSelect::ID = 0;
+char RegBankSelectLegacy::ID = 0;
 
-INITIALIZE_PASS_BEGIN(RegBankSelect, DEBUG_TYPE,
+INITIALIZE_PASS_BEGIN(RegBankSelectLegacy, DEBUG_TYPE,
                       "Assign register bank of generic virtual registers",
                       false, false);
 INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
-INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,
+INITIALIZE_PASS_END(RegBankSelectLegacy, DEBUG_TYPE,
                     "Assign register bank of generic virtual registers", false,
                     false)
 
-RegBankSelect::RegBankSelect(Mode RunningMode)
-    : MachineFunctionPass(ID), OptMode(RunningMode) {
-  if (RegBankSelectMode.getNumOccurrences() != 0) {
-    OptMode = RegBankSelectMode;
-    if (RegBankSelectMode != RunningMode)
+static RegBankSelectMode computeOptMode(RegBankSelectMode RequestedMode) {
+  if (RegBankSelectModeOption.getNumOccurrences() != 0) {
+    if (RegBankSelectModeOption != RequestedMode)
       LLVM_DEBUG(dbgs() << "RegBankSelect mode overrided by command line\n");
+    return RegBankSelectModeOption;
   }
+  return RequestedMode;
 }
 
-void RegBankSelect::init(MachineFunction &MF) {
+namespace {
+
+class RegBankSelectImpl {
+  /// Abstract class used to represent an insertion point in a CFG.
+  /// This class records an insertion point and materializes it on
+  /// demand.
+  /// It allows to reason about the frequency of this insertion point,
+  /// without having to logically materialize it (e.g., on an edge),
+  /// before we actually need to insert something.
+  class InsertPoint {
+  protected:
+    /// Tell if the insert point has already been materialized.
+    bool WasMaterialized = false;
+
+    /// Materialize the insertion point.
+    ///
+    /// If isSplit() is true, this involves actually splitting
+    /// the block or edge.
+    ///
+    /// \post getPointImpl() returns a valid iterator.
+    /// \post getInsertMBBImpl() returns a valid basic block.
+    /// \post isSplit() == false ; no more splitting should be required.
+    virtual void materialize() = 0;
+
+    /// Return the materialized insertion basic block.
+    /// Code will be inserted into that basic block.
+    ///
+    /// \pre ::materialize has been called.
+    virtual MachineBasicBlock &getInsertMBBImpl() = 0;
+
+    /// Return the materialized insertion point.
+    /// Code will be inserted before that point.
+    ///
+    /// \pre ::materialize has been called.
+    virtual MachineBasicBlock::iterator getPointImpl() = 0;
+
+  public:
+    virtual ~InsertPoint() = default;
+
+    /// The first call to this method will cause the splitting to
+    /// happen if need be, then sub sequent calls just return
+    /// the iterator to that point. I.e., no more splitting will
+    /// occur.
+    ///
+    /// \return The iterator that should be used with
+    /// MachineBasicBlock::insert. I.e., additional code happens
+    /// before that point.
+    MachineBasicBlock::iterator getPoint() {
+      if (!WasMaterialized) {
+        WasMaterialized = true;
+        assert(canMaterialize() && "Impossible to materialize this point");
+        materialize();
+      }
+      // When we materialized the point we should have done the splitting.
+      assert(!isSplit() && "Wrong pre-condition");
+      return getPointImpl();
+    }
+
+    /// The first call to this method will cause the splitting to
+    /// happen if need be, then sub sequent calls just return
+    /// the basic block that contains the insertion point.
+    /// I.e., no more splitting will occur.
+    ///
+    /// \return The basic block should be used with
+    /// MachineBasicBlock::insert and ::getPoint. The new code should
+    /// happen before that point.
+    MachineBasicBlock &getInsertMBB() {
+      if (!WasMaterialized) {
+        WasMaterialized = true;
+        assert(canMaterialize() && "Impossible to materialize this point");
+        materialize();
+      }
+      // When we materialized the point we should have done the splitting.
+      assert(!isSplit() && "Wrong pre-condition");
+      return getInsertMBBImpl();
+    }
+
+    /// Insert \p MI in the just before ::getPoint()
+    MachineBasicBlock::iterator insert(MachineInstr &MI) {
+      return getInsertMBB().insert(getPoint(), &MI);
+    }
+
+    /// Does this point involve splitting an edge or block?
+    /// As soon as ::getPoint is called and thus, the point
+    /// materialized, the point will not require splitting anymore,
+    /// i.e., this will return false.
+    virtual bool isSplit() const { return false; }
+
+    /// Frequency of the insertion point.
+    /// \p P is used to access the various analysis that will help to
+    /// get that information, like MachineBlockFrequencyInfo.  If \p P
+    /// does not contain enough to return the actual frequency,
+    /// this returns 1.
+    virtual uint64_t frequency(
+        function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+        function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) const {
+      return 1;
+    }
+
+    /// Check whether this insertion point can be materialized.
+    /// As soon as ::getPoint is called and thus, the point materialized
+    /// calling this method does not make sense.
+    virtual bool canMaterialize() const { return false; }
+  };
+
+  /// Insertion point before or after an instruction.
+  class LLVM_ABI InstrInsertPoint : public InsertPoint {
+  private:
+    /// Insertion point.
+    MachineInstr &Instr;
+
+    /// Does the insertion point is before or after Instr.
+    bool Before;
+
+    void materialize() override;
+
+    MachineBasicBlock::iterator getPointImpl() override {
+      if (Before)
+        return Instr;
+      return Instr.getNextNode() ? *Instr.getNextNode()
+                                 : Instr.getParent()->end();
+    }
+
+    MachineBasicBlock &getInsertMBBImpl() override {
+      return *Instr.getParent();
+    }
+
+  public:
+    /// Create an insertion point before (\p Before=true) or after \p Instr.
+    InstrInsertPoint(MachineInstr &Instr, bool Before = true);
+
+    bool isSplit() const override;
+    uint64_t
+    frequency(function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+              function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI)
+        const override;
+
+    // Worst case, we need to slice the basic block, but that is still doable.
+    bool canMaterialize() const override { return true; }
+  };
+
+  /// Insertion point at the beginning or end of a basic block.
+  class LLVM_ABI MBBInsertPoint : public InsertPoint {
+  private:
+    /// Insertion point.
+    MachineBasicBlock &MBB;
+
+    /// Does the insertion point is at the beginning or end of MBB.
+    bool Beginning;
+
+    void materialize() override { /*Nothing to do to materialize*/ }
+
+    MachineBasicBlock::iterator getPointImpl() override {
+      return Beginning ? MBB.begin() : MBB.end();
+    }
+
+    MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
+
+  public:
+    MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
+        : MBB(MBB), Beginning(Beginning) {
+      // If we try to insert before phis, we should use the insertion
+      // points on the incoming edges.
+      assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
+             "Invalid beginning point");
+      // If we try to insert after the terminators, we should use the
+      // points on the outcoming edges.
+      assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
+             "Invalid end point");
+    }
+
+    bool isSplit() const override { return false; }
+    uint64_t
+    frequency(function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+              function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI)
+        const override;
+    bool canMaterialize() const override { return true; };
+  };
+
+  /// Insertion point on an edge.
+  class LLVM_ABI EdgeInsertPoint : public InsertPoint {
+  private:
+    /// Source of the edge.
+    MachineBasicBlock &Src;
+
+    /// Destination of the edge.
+    /// After the materialization is done, this hold the basic block
+    /// that resulted from the splitting.
+    MachineBasicBlock *DstOrSplit;
+
+    /// P/MFAM is used to update the analysis passes as applicable when
+    /// splitting critical edges.
+    Pass *P;
+    MachineFunctionAnalysisManager *MFAM;
+
+    void materialize() override;
+
+    MachineBasicBlock::iterator getPointImpl() override {
+      // DstOrSplit should be the Split block at this point.
+      // I.e., it should have one predecessor, Src, and one successor,
+      // the original Dst.
+      assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
+             DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
+             "Did not split?!");
+      return DstOrSplit->begin();
+    }
+
+    MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
+
+  public:
+    EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass *P,
+                    MachineFunctionAnalysisManager *MFAM)
+        : Src(Src), DstOrSplit(&Dst), P(P), MFAM(MFAM) {}
+
+    bool isSplit() const override {
+      return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
+    }
+
+    uint64_t
+    frequency(function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+              function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI)
+        const override;
+    bool canMaterialize() const override;
+  };
+
+  /// Struct used to represent the placement of a repairing point for
+  /// a given operand.
+  class RepairingPlacement {
+  public:
+    /// Define the kind of action this repairing needs.
+    enum RepairingKind {
+      /// Nothing to repair, just drop this action.
+      None,
+      /// Reparing code needs to happen before InsertPoints.
+      Insert,
+      /// (Re)assign the register bank of the operand.
+      Reassign,
+      /// Mark this repairing placement as impossible.
+      Impossible
+    };
+
+    /// \name Convenient types for a list of insertion points.
+    /// @{
+    using InsertionPoints = SmallVector<std::unique_ptr<InsertPoint>, 2>;
+    using insertpt_iterator = InsertionPoints::iterator;
+    using const_insertpt_iterator = InsertionPoints::const_iterator;
+    /// @}
+
+  private:
+    /// Kind of repairing.
+    RepairingKind Kind;
+    /// Index of the operand that will be repaired.
+    unsigned OpIdx;
+    /// Are all the insert points materializeable?
+    bool CanMaterialize;
+    /// Is there any of the insert points needing splitting?
+    bool HasSplit = false;
+    /// Insertion point for the repair code.
+    /// The repairing code needs to happen just before these points.
+    InsertionPoints InsertPoints;
+    /// Some insertion points may need to update the liveness and such.
+    Pass *P;
+    MachineFunctionAnalysisManager *MFAM;
+
+  public:
+    /// Create a repairing placement for the \p OpIdx-th operand of
+    /// \p MI. \p TRI is used to make some checks on the register aliases
+    /// if the machine operand is a physical register. \p P is used to
+    /// to update liveness information and such when materializing the
+    /// points.
+    LLVM_ABI RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
+                                const TargetRegisterInfo &TRI, Pass *P,
+                                MachineFunctionAnalysisManager *MFAM,
+                                RepairingKind Kind = RepairingKind::Insert);
+
+    /// \name Getters.
+    /// @{
+    RepairingKind getKind() const { return Kind; }
+    unsigned getOpIdx() const { return OpIdx; }
+    bool canMaterialize() const { return CanMaterialize; }
+    bool hasSplit() { return HasSplit; }
+    /// @}
+
+    /// \name Overloaded methods to add an insertion point.
+    /// @{
+    /// Add a MBBInsertionPoint to the list of InsertPoints.
+    LLVM_ABI void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
+    /// Add a InstrInsertionPoint to the list of InsertPoints.
+    LLVM_ABI void addInsertPoint(MachineInstr &MI, bool Before);
+    /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
+    LLVM_ABI void addInsertPoint(MachineBasicBlock &Src,
+                                 MachineBasicBlock &Dst);
+    /// Add an InsertPoint to the list of insert points.
+    /// This method takes the ownership of &\p Point.
+    LLVM_ABI void addInsertPoint(InsertPoint &Point);
+    /// @}
+
+    /// \name Accessors related to the insertion points.
+    /// @{
+    insertpt_iterator begin() { return InsertPoints.begin(); }
+    insertpt_iterator end() { return InsertPoints.end(); }
+
+    const_insertpt_iterator begin() const { return InsertPoints.begin(); }
+    const_insertpt_iterator end() const { return InsertPoints.end(); }
+
+    unsigned getNumInsertPoints() const { return InsertPoints.size(); }
+    /// @}
+
+    /// Change the type of this repairing placement to \p NewKind.
+    /// It is not possible to switch a repairing placement to the
+    /// RepairingKind::Insert. There is no fundamental problem with
+    /// that, but no uses as well, so do not support it for now.
+    ///
+    /// \pre NewKind != RepairingKind::Insert
+    /// \post getKind() == NewKind
+    void switchTo(RepairingKind NewKind) {
+      assert(NewKind != Kind && "Already of the right Kind");
+      Kind = NewKind;
+      InsertPoints.clear();
+      CanMaterialize = NewKind != RepairingKind::Impossible;
+      HasSplit = false;
+      assert(NewKind != RepairingKind::Insert &&
+             "We would need more MI to switch to Insert");
+    }
+  };
+
+protected:
+  /// Helper class used to represent the cost for mapping an instruction.
+  /// When mapping an instruction, we may introduce some repairing code.
+  /// In most cases, the repairing code is local to the instruction,
+  /// thus, we can omit the basic block frequency from the cost.
+  /// However, some alternatives may produce non-local cost, e.g., when
+  /// repairing a phi, and thus we then need to scale the local cost
+  /// to the non-local cost. This class does this for us.
+  /// \note: We could simply always scale the cost. The problem is that
+  /// there are higher chances that we saturate the cost easier and end
+  /// up having the same cost for actually 
diff erent alternatives.
+  /// Another option would be to use APInt everywhere.
+  class MappingCost {
+  private:
+    /// Cost of the local instructions.
+    /// This cost is free of basic block frequency.
+    uint64_t LocalCost = 0;
+    /// Cost of the non-local instructions.
+    /// This cost should include the frequency of the related blocks.
+    uint64_t NonLocalCost = 0;
+    /// Frequency of the block where the local instructions live.
+    uint64_t LocalFreq;
+
+    MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
+        : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
+          LocalFreq(LocalFreq) {}
+
+    /// Check if this cost is saturated.
+    bool isSaturated() const;
+
+  public:
+    /// Create a MappingCost assuming that most of the instructions
+    /// will occur in a basic block with \p LocalFreq frequency.
+    LLVM_ABI MappingCost(BlockFrequency LocalFreq);
+
+    /// Add \p Cost to the local cost.
+    /// \return true if this cost is saturated, false otherwise.
+    LLVM_ABI bool addLocalCost(uint64_t Cost);
+
+    /// Add \p Cost to the non-local cost.
+    /// Non-local cost should reflect the frequency of their placement.
+    /// \return true if this cost is saturated, false otherwise.
+    LLVM_ABI bool addNonLocalCost(uint64_t Cost);
+
+    /// Saturate the cost to the maximal representable value.
+    LLVM_ABI void saturate();
+
+    /// Return an instance of MappingCost that represents an
+    /// impossible mapping.
+    LLVM_ABI static MappingCost ImpossibleCost();
+
+    /// Check if this is less than \p Cost.
+    LLVM_ABI bool operator<(const MappingCost &Cost) const;
+    /// Check if this is equal to \p Cost.
+    LLVM_ABI bool operator==(const MappingCost &Cost) const;
+    /// Check if this is not equal to \p Cost.
+    bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
+    /// Check if this is greater than \p Cost.
+    bool operator>(const MappingCost &Cost) const {
+      return *this != Cost && Cost < *this;
+    }
+
+    /// Print this on dbgs() stream.
+    LLVM_ABI void dump() const;
+
+    /// Print this on \p OS;
+    LLVM_ABI void print(raw_ostream &OS) const;
+
+    /// Overload the stream operator for easy debug printing.
+    friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) {
+      Cost.print(OS);
+      return OS;
+    }
+  };
+
+  /// Interface to the target lowering info related
+  /// to register banks.
+  const RegisterBankInfo *RBI = nullptr;
+
+  /// MRI contains all the register class/bank information that this
+  /// pass uses and updates.
+  MachineRegisterInfo *MRI = nullptr;
+
+  /// Information on the register classes for the current function.
+  const TargetRegisterInfo *TRI = nullptr;
+
+  /// Get the frequency of blocks.
+  /// This is required for non-fast mode.
+  MachineBlockFrequencyInfo *MBFI = nullptr;
+
+  /// Get the frequency of the edges.
+  /// This is required for non-fast mode.
+  MachineBranchProbabilityInfo *MBPI = nullptr;
+
+  /// Current optimization remark emitter. Used to report failures.
+  std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
+
+  /// Helper class used for every code morphing.
+  MachineIRBuilder MIRBuilder;
+
+  /// Optimization mode of the pass.
+  RegBankSelectMode OptMode;
+
+  /// The current Pass/MFAM reference to enable updating analyses.
+  Pass *P = nullptr;
+  MachineFunctionAnalysisManager *MFAM = nullptr;
+
+  /// Assign the register bank of each operand of \p MI.
+  /// \return True on success, false otherwise.
+  bool
+  assignInstr(MachineInstr &MI,
+              function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+              function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI);
+
+  /// Initialize the field members using \p MF.
+  void init(MachineFunction &MF,
+            function_ref<MachineBlockFrequencyInfo *()> GetMBFI,
+            function_ref<MachineBranchProbabilityInfo *()> GetMBPI);
+
+  /// Check if \p Reg is already assigned what is described by \p ValMapping.
+  /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
+  /// register bank.  I.e., no repairing is necessary to have the
+  /// assignment match.
+  bool assignmentMatch(Register Reg,
+                       const RegisterBankInfo::ValueMapping &ValMapping,
+                       bool &OnlyAssign) const;
+
+  /// Insert repairing code for \p Reg as specified by \p ValMapping.
+  /// The repairing placement is specified by \p RepairPt.
+  /// \p NewVRegs contains all the registers required to remap \p Reg.
+  /// In other words, the number of registers in NewVRegs must be equal
+  /// to ValMapping.BreakDown.size().
+  ///
+  /// The transformation could be sketched as:
+  /// \code
+  /// ... = op Reg
+  /// \endcode
+  /// Becomes
+  /// \code
+  /// <NewRegs> = COPY or extract Reg
+  /// ... = op Reg
+  /// \endcode
+  ///
+  /// and
+  /// \code
+  /// Reg = op ...
+  /// \endcode
+  /// Becomes
+  /// \code
+  /// Reg = op ...
+  /// Reg = COPY or build_sequence <NewRegs>
+  /// \endcode
+  ///
+  /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
+  ///
+  /// \note The caller is supposed to do the rewriting of op if need be.
+  /// I.e., Reg = op ... => <NewRegs> = NewOp ...
+  ///
+  /// \return True if the repairing worked, false otherwise.
+  bool repairReg(MachineOperand &MO,
+                 const RegisterBankInfo::ValueMapping &ValMapping,
+                 RegBankSelectImpl::RepairingPlacement &RepairPt,
+                 const iterator_range<SmallVectorImpl<Register>::const_iterator>
+                     &NewVRegs);
+
+  /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
+  /// The cost is free of basic block frequencies.
+  /// \pre MO.isReg()
+  /// \pre MO is assigned to a register bank.
+  /// \pre ValMapping is a valid mapping for MO.
+  uint64_t
+  getRepairCost(const MachineOperand &MO,
+                const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+  /// Find the best mapping for \p MI from \p PossibleMappings.
+  /// \return a reference on the best mapping in \p PossibleMappings.
+  const RegisterBankInfo::InstructionMapping &
+  findBestMapping(MachineInstr &MI,
+                  RegisterBankInfo::InstructionMappings &PossibleMappings,
+                  SmallVectorImpl<RepairingPlacement> &RepairPts,
+                  function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+                  function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI);
+
+  /// Compute the cost of mapping \p MI with \p InstrMapping and
+  /// compute the repairing placement for such mapping in \p
+  /// RepairPts.
+  /// \p BestCost is used to specify when the cost becomes too high
+  /// and thus it is not worth computing the RepairPts.  Moreover if
+  /// \p BestCost == nullptr, the mapping cost is actually not
+  /// computed.
+  MappingCost
+  computeMapping(MachineInstr &MI,
+                 const RegisterBankInfo::InstructionMapping &InstrMapping,
+                 SmallVectorImpl<RepairingPlacement> &RepairPts,
+                 function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+                 function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI,
+                 const MappingCost *BestCost = nullptr);
+
+  /// When \p RepairPt involves splitting to repair \p MO for the
+  /// given \p ValMapping, try to change the way we repair such that
+  /// the splitting is not required anymore.
+  ///
+  /// \pre \p RepairPt.hasSplit()
+  /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
+  /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
+  ///      that implied \p RepairPt.
+  void tryAvoidingSplit(RegBankSelectImpl::RepairingPlacement &RepairPt,
+                        const MachineOperand &MO,
+                        const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+  /// Apply \p Mapping to \p MI. \p RepairPts represents the 
diff erent
+  /// mapping action that need to happen for the mapping to be
+  /// applied.
+  /// \return True if the mapping was applied sucessfully, false otherwise.
+  bool applyMapping(MachineInstr &MI,
+                    const RegisterBankInfo::InstructionMapping &InstrMapping,
+                    SmallVectorImpl<RepairingPlacement> &RepairPts);
+
+public:
+  /// Create a RegBankSelect pass with the specified \p RunningMode.
+  RegBankSelectImpl(RegBankSelectMode RunningMode);
+
+  /// Check that our input is fully legal: we require the function to have the
+  /// Legalized property, so it should be.
+  ///
+  /// FIXME: This should be in the MachineVerifier.
+  bool checkFunctionIsLegal(MachineFunction &MF) const;
+
+  /// Walk through \p MF and assign a register bank to every virtual register
+  /// that are still mapped to nothing.
+  /// The target needs to provide a RegisterBankInfo and in particular
+  /// override RegisterBankInfo::getInstrMapping.
+  ///
+  /// Simplified algo:
+  /// \code
+  ///   RBI = MF.subtarget.getRegBankInfo()
+  ///   MIRBuilder.setMF(MF)
+  ///   for each bb in MF
+  ///     for each inst in bb
+  ///       MIRBuilder.setInstr(inst)
+  ///       MappingCosts = RBI.getMapping(inst);
+  ///       Idx = findIdxOfMinCost(MappingCosts)
+  ///       CurRegBank = MappingCosts[Idx].RegBank
+  ///       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
+  ///       for each argument in inst
+  ///         if (CurRegBank != argument.RegBank)
+  ///           ArgReg = argument.getReg()
+  ///           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
+  ///           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
+  ///           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
+  /// \endcode
+  bool assignRegisterBanks(
+      MachineFunction &MF,
+      function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+      function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI);
+
+  bool runOnMachineFunction(
+      MachineFunction &MF, Pass *PassRef,
+      MachineFunctionAnalysisManager *MFAMRef,
+      function_ref<MachineBlockFrequencyInfo *()> GetMBFI,
+      function_ref<MachineBranchProbabilityInfo *()> GetMBPI,
+      function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+      function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI);
+};
+
+} // namespace
+
+RegBankSelectImpl::RegBankSelectImpl(RegBankSelectMode RunningMode)
+    : OptMode(RunningMode) {}
+
+RegBankSelectLegacy::RegBankSelectLegacy(RegBankSelectMode RunningMode)
+    : MachineFunctionPass(ID), OptMode(computeOptMode(RunningMode)) {}
+
+void RegBankSelectImpl::init(
+    MachineFunction &MF, function_ref<MachineBlockFrequencyInfo *()> GetMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetMBPI) {
   RBI = MF.getSubtarget().getRegBankInfo();
   assert(RBI && "Cannot work without RegisterBankInfo");
   MRI = &MF.getRegInfo();
   TRI = MF.getSubtarget().getRegisterInfo();
-  if (OptMode != Mode::Fast) {
-    MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
-    MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
+  if (OptMode != RegBankSelectMode::Fast) {
+    MBFI = GetMBFI();
+    MBPI = GetMBPI();
   } else {
     MBFI = nullptr;
     MBPI = nullptr;
@@ -102,8 +707,8 @@ void RegBankSelect::init(MachineFunction &MF) {
   MORE = std::make_unique<MachineOptimizationRemarkEmitter>(MF, MBFI);
 }
 
-void RegBankSelect::getAnalysisUsage(AnalysisUsage &AU) const {
-  if (OptMode != Mode::Fast) {
+void RegBankSelectLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
+  if (OptMode != RegBankSelectMode::Fast) {
     // We could preserve the information from these two analysis but
     // the APIs do not allow to do so yet.
     AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
@@ -114,7 +719,7 @@ void RegBankSelect::getAnalysisUsage(AnalysisUsage &AU) const {
   MachineFunctionPass::getAnalysisUsage(AU);
 }
 
-bool RegBankSelect::assignmentMatch(
+bool RegBankSelectImpl::assignmentMatch(
     Register Reg, const RegisterBankInfo::ValueMapping &ValMapping,
     bool &OnlyAssign) const {
   // By default we assume we will have to repair something.
@@ -137,9 +742,9 @@ bool RegBankSelect::assignmentMatch(
   return CurRegBank == DesiredRegBank;
 }
 
-bool RegBankSelect::repairReg(
+bool RegBankSelectImpl::repairReg(
     MachineOperand &MO, const RegisterBankInfo::ValueMapping &ValMapping,
-    RegBankSelect::RepairingPlacement &RepairPt,
+    RegBankSelectImpl::RepairingPlacement &RepairPt,
     const iterator_range<SmallVectorImpl<Register>::const_iterator> &NewVRegs) {
 
   assert(ValMapping.NumBreakDowns == (unsigned)size(NewVRegs) &&
@@ -241,7 +846,7 @@ bool RegBankSelect::repairReg(
   return true;
 }
 
-uint64_t RegBankSelect::getRepairCost(
+uint64_t RegBankSelectImpl::getRepairCost(
     const MachineOperand &MO,
     const RegisterBankInfo::ValueMapping &ValMapping) const {
   assert(MO.isReg() && "We should only repair register operand");
@@ -292,9 +897,11 @@ uint64_t RegBankSelect::getRepairCost(
   return ImpossibleRepairCost;
 }
 
-const RegisterBankInfo::InstructionMapping &RegBankSelect::findBestMapping(
+const RegisterBankInfo::InstructionMapping &RegBankSelectImpl::findBestMapping(
     MachineInstr &MI, RegisterBankInfo::InstructionMappings &PossibleMappings,
-    SmallVectorImpl<RepairingPlacement> &RepairPts) {
+    SmallVectorImpl<RepairingPlacement> &RepairPts,
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) {
   assert(!PossibleMappings.empty() &&
          "Do not know how to map this instruction");
 
@@ -303,8 +910,8 @@ const RegisterBankInfo::InstructionMapping &RegBankSelect::findBestMapping(
   SmallVector<RepairingPlacement, 4> LocalRepairPts;
   for (const RegisterBankInfo::InstructionMapping *CurMapping :
        PossibleMappings) {
-    MappingCost CurCost =
-        computeMapping(MI, *CurMapping, LocalRepairPts, &Cost);
+    MappingCost CurCost = computeMapping(MI, *CurMapping, LocalRepairPts,
+                                         GetCachedMBFI, GetCachedMBPI, &Cost);
     if (CurCost < Cost) {
       LLVM_DEBUG(dbgs() << "New best: " << CurCost << '\n');
       Cost = CurCost;
@@ -320,15 +927,15 @@ const RegisterBankInfo::InstructionMapping &RegBankSelect::findBestMapping(
     // Thus, pick the first one and set an impossible repairing point.
     // It will trigger the failed isel mode.
     BestMapping = *PossibleMappings.begin();
-    RepairPts.emplace_back(
-        RepairingPlacement(MI, 0, *TRI, *this, RepairingPlacement::Impossible));
+    RepairPts.emplace_back(RepairingPlacement(MI, 0, *TRI, P, MFAM,
+                                              RepairingPlacement::Impossible));
   } else
     assert(BestMapping && "No suitable mapping for instruction");
   return *BestMapping;
 }
 
-void RegBankSelect::tryAvoidingSplit(
-    RegBankSelect::RepairingPlacement &RepairPt, const MachineOperand &MO,
+void RegBankSelectImpl::tryAvoidingSplit(
+    RegBankSelectImpl::RepairingPlacement &RepairPt, const MachineOperand &MO,
     const RegisterBankInfo::ValueMapping &ValMapping) const {
   const MachineInstr &MI = *MO.getParent();
   assert(RepairPt.hasSplit() && "We should not have to adjust for split");
@@ -447,10 +1054,12 @@ void RegBankSelect::tryAvoidingSplit(
   }
 }
 
-RegBankSelect::MappingCost RegBankSelect::computeMapping(
+RegBankSelectImpl::MappingCost RegBankSelectImpl::computeMapping(
     MachineInstr &MI, const RegisterBankInfo::InstructionMapping &InstrMapping,
     SmallVectorImpl<RepairingPlacement> &RepairPts,
-    const RegBankSelect::MappingCost *BestCost) {
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI,
+    const RegBankSelectImpl::MappingCost *BestCost) {
   assert((MBFI || !BestCost) && "Costs comparison require MBFI");
 
   if (!InstrMapping.isValid())
@@ -497,14 +1106,14 @@ RegBankSelect::MappingCost RegBankSelect::computeMapping(
     }
     if (Assign) {
       LLVM_DEBUG(dbgs() << "=> is free (simple assignment).\n");
-      RepairPts.emplace_back(RepairingPlacement(MI, OpIdx, *TRI, *this,
+      RepairPts.emplace_back(RepairingPlacement(MI, OpIdx, *TRI, P, MFAM,
                                                 RepairingPlacement::Reassign));
       continue;
     }
 
     // Find the insertion point for the repairing code.
-    RepairPts.emplace_back(
-        RepairingPlacement(MI, OpIdx, *TRI, *this, RepairingPlacement::Insert));
+    RepairPts.emplace_back(RepairingPlacement(MI, OpIdx, *TRI, P, MFAM,
+                                              RepairingPlacement::Insert));
     RepairingPlacement &RepairPt = RepairPts.back();
 
     // If we need to split a basic block to materialize this insertion point,
@@ -567,7 +1176,8 @@ RegBankSelect::MappingCost RegBankSelect::computeMapping(
         assert(CostForInsertPt + Bias > CostForInsertPt &&
                "Repairing + split bias overflows");
         CostForInsertPt += Bias;
-        uint64_t PtCost = InsertPt->frequency(*this) * CostForInsertPt;
+        uint64_t PtCost =
+            InsertPt->frequency(GetCachedMBFI, GetCachedMBPI) * CostForInsertPt;
         // Check if we just overflowed.
         if ((Saturated = PtCost < CostForInsertPt))
           Cost.saturate();
@@ -592,9 +1202,9 @@ RegBankSelect::MappingCost RegBankSelect::computeMapping(
   return Cost;
 }
 
-bool RegBankSelect::applyMapping(
+bool RegBankSelectImpl::applyMapping(
     MachineInstr &MI, const RegisterBankInfo::InstructionMapping &InstrMapping,
-    SmallVectorImpl<RegBankSelect::RepairingPlacement> &RepairPts) {
+    SmallVectorImpl<RegBankSelectImpl::RepairingPlacement> &RepairPts) {
   // OpdMapper will hold all the information needed for the rewriting.
   std::optional<RegisterBankInfo::OperandsMapper> OpdMapper;
 
@@ -646,7 +1256,9 @@ bool RegBankSelect::applyMapping(
   return true;
 }
 
-bool RegBankSelect::assignInstr(MachineInstr &MI) {
+bool RegBankSelectImpl::assignInstr(
+    MachineInstr &MI, function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) {
   LLVM_DEBUG(dbgs() << "Assign: " << MI);
 
   unsigned Opc = MI.getOpcode();
@@ -671,9 +1283,10 @@ bool RegBankSelect::assignInstr(MachineInstr &MI) {
   SmallVector<RepairingPlacement, 4> RepairPts;
 
   const RegisterBankInfo::InstructionMapping *BestMapping;
-  if (OptMode == RegBankSelect::Mode::Fast) {
+  if (OptMode == RegBankSelectMode::Fast) {
     BestMapping = &RBI->getInstrMapping(MI);
-    MappingCost DefaultCost = computeMapping(MI, *BestMapping, RepairPts);
+    MappingCost DefaultCost = computeMapping(MI, *BestMapping, RepairPts,
+                                             GetCachedMBFI, GetCachedMBPI);
     (void)DefaultCost;
     if (DefaultCost == MappingCost::ImpossibleCost())
       return false;
@@ -682,7 +1295,8 @@ bool RegBankSelect::assignInstr(MachineInstr &MI) {
         RBI->getInstrPossibleMappings(MI);
     if (PossibleMappings.empty())
       return false;
-    BestMapping = &findBestMapping(MI, PossibleMappings, RepairPts);
+    BestMapping = &findBestMapping(MI, PossibleMappings, RepairPts,
+                                   GetCachedMBFI, GetCachedMBPI);
   }
   // Make sure the mapping is valid for MI.
   assert(BestMapping->verify(MI) && "Invalid instruction mapping");
@@ -694,7 +1308,10 @@ bool RegBankSelect::assignInstr(MachineInstr &MI) {
   return applyMapping(MI, *BestMapping, RepairPts);
 }
 
-bool RegBankSelect::assignRegisterBanks(MachineFunction &MF) {
+bool RegBankSelectImpl::assignRegisterBanks(
+    MachineFunction &MF,
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) {
   // Walk the function and assign register banks to all operands.
   // Use a RPOT to make sure all registers are assigned before we choose
   // the best mapping of the current instruction.
@@ -723,7 +1340,7 @@ bool RegBankSelect::assignRegisterBanks(MachineFunction &MF) {
       if (MI.isImplicitDef())
         continue;
 
-      if (!assignInstr(MI)) {
+      if (!assignInstr(MI, GetCachedMBFI, GetCachedMBPI)) {
         reportGISelFailure(MF, *MORE, "gisel-regbankselect",
                            "unable to map instruction", MI);
         return false;
@@ -734,7 +1351,7 @@ bool RegBankSelect::assignRegisterBanks(MachineFunction &MF) {
   return true;
 }
 
-bool RegBankSelect::checkFunctionIsLegal(MachineFunction &MF) const {
+bool RegBankSelectImpl::checkFunctionIsLegal(MachineFunction &MF) const {
 #ifndef NDEBUG
   if (!DisableGISelLegalityCheck) {
     if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) {
@@ -747,24 +1364,32 @@ bool RegBankSelect::checkFunctionIsLegal(MachineFunction &MF) const {
   return true;
 }
 
-bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) {
+bool RegBankSelectImpl::runOnMachineFunction(
+    MachineFunction &MF, Pass *PassRef, MachineFunctionAnalysisManager *MFAMRef,
+    function_ref<MachineBlockFrequencyInfo *()> GetMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetMBPI,
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) {
   // If the ISel pipeline failed, do not bother running that pass.
   if (MF.getProperties().hasFailedISel())
     return false;
 
+  P = PassRef;
+  MFAM = MFAMRef;
+
   LLVM_DEBUG(dbgs() << "Assign register banks for: " << MF.getName() << '\n');
   const Function &F = MF.getFunction();
-  Mode SaveOptMode = OptMode;
+  RegBankSelectMode SaveOptMode = OptMode;
   if (F.hasOptNone())
-    OptMode = Mode::Fast;
-  init(MF);
+    OptMode = RegBankSelectMode::Fast;
+  init(MF, GetMBFI, GetMBPI);
 
 #ifndef NDEBUG
   if (!checkFunctionIsLegal(MF))
     return false;
 #endif
 
-  assignRegisterBanks(MF);
+  assignRegisterBanks(MF, GetCachedMBFI, GetCachedMBPI);
 
   OptMode = SaveOptMode;
   return false;
@@ -773,8 +1398,9 @@ bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) {
 //------------------------------------------------------------------------------
 //                  Helper Classes Implementation
 //------------------------------------------------------------------------------
-RegBankSelect::RepairingPlacement::RepairingPlacement(
-    MachineInstr &MI, unsigned OpIdx, const TargetRegisterInfo &TRI, Pass &P,
+RegBankSelectImpl::RepairingPlacement::RepairingPlacement(
+    MachineInstr &MI, unsigned OpIdx, const TargetRegisterInfo &TRI, Pass *P,
+    MachineFunctionAnalysisManager *MFAM,
     RepairingPlacement::RepairingKind Kind)
     // Default is, we are going to insert code to repair OpIdx.
     : Kind(Kind), OpIdx(OpIdx),
@@ -867,30 +1493,30 @@ RegBankSelect::RepairingPlacement::RepairingPlacement(
   }
 }
 
-void RegBankSelect::RepairingPlacement::addInsertPoint(MachineInstr &MI,
-                                                       bool Before) {
+void RegBankSelectImpl::RepairingPlacement::addInsertPoint(MachineInstr &MI,
+                                                           bool Before) {
   addInsertPoint(*new InstrInsertPoint(MI, Before));
 }
 
-void RegBankSelect::RepairingPlacement::addInsertPoint(MachineBasicBlock &MBB,
-                                                       bool Beginning) {
+void RegBankSelectImpl::RepairingPlacement::addInsertPoint(
+    MachineBasicBlock &MBB, bool Beginning) {
   addInsertPoint(*new MBBInsertPoint(MBB, Beginning));
 }
 
-void RegBankSelect::RepairingPlacement::addInsertPoint(MachineBasicBlock &Src,
-                                                       MachineBasicBlock &Dst) {
-  addInsertPoint(*new EdgeInsertPoint(Src, Dst, P));
+void RegBankSelectImpl::RepairingPlacement::addInsertPoint(
+    MachineBasicBlock &Src, MachineBasicBlock &Dst) {
+  addInsertPoint(*new EdgeInsertPoint(Src, Dst, P, MFAM));
 }
 
-void RegBankSelect::RepairingPlacement::addInsertPoint(
-    RegBankSelect::InsertPoint &Point) {
+void RegBankSelectImpl::RepairingPlacement::addInsertPoint(
+    RegBankSelectImpl::InsertPoint &Point) {
   CanMaterialize &= Point.canMaterialize();
   HasSplit |= Point.isSplit();
   InsertPoints.emplace_back(&Point);
 }
 
-RegBankSelect::InstrInsertPoint::InstrInsertPoint(MachineInstr &Instr,
-                                                  bool Before)
+RegBankSelectImpl::InstrInsertPoint::InstrInsertPoint(MachineInstr &Instr,
+                                                      bool Before)
     : Instr(Instr), Before(Before) {
   // Since we do not support splitting, we do not need to update
   // liveness and such, so do not do anything with P.
@@ -900,7 +1526,7 @@ RegBankSelect::InstrInsertPoint::InstrInsertPoint(MachineInstr &Instr,
          "Splitting between phis does not make sense");
 }
 
-void RegBankSelect::InstrInsertPoint::materialize() {
+void RegBankSelectImpl::InstrInsertPoint::materialize() {
   if (isSplit()) {
     // Slice and return the beginning of the new block.
     // If we need to split between the terminators, we theoritically
@@ -922,7 +1548,7 @@ void RegBankSelect::InstrInsertPoint::materialize() {
   // here.
 }
 
-bool RegBankSelect::InstrInsertPoint::isSplit() const {
+bool RegBankSelectImpl::InstrInsertPoint::isSplit() const {
   // If the insertion point is after a terminator, we need to split.
   if (!Before)
     return Instr.isTerminator();
@@ -931,50 +1557,49 @@ bool RegBankSelect::InstrInsertPoint::isSplit() const {
   return Instr.getPrevNode() && Instr.getPrevNode()->isTerminator();
 }
 
-uint64_t RegBankSelect::InstrInsertPoint::frequency(const Pass &P) const {
+uint64_t RegBankSelectImpl::InstrInsertPoint::frequency(
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) const {
   // Even if we need to split, because we insert between terminators,
   // this split has actually the same frequency as the instruction.
-  const auto *MBFIWrapper =
-      P.getAnalysisIfAvailable<MachineBlockFrequencyInfoWrapperPass>();
-  if (!MBFIWrapper)
+  const MachineBlockFrequencyInfo *MBFI = GetCachedMBFI();
+  if (!MBFI)
     return 1;
-  return MBFIWrapper->getMBFI().getBlockFreq(Instr.getParent()).getFrequency();
+  return MBFI->getBlockFreq(Instr.getParent()).getFrequency();
 }
 
-uint64_t RegBankSelect::MBBInsertPoint::frequency(const Pass &P) const {
-  const auto *MBFIWrapper =
-      P.getAnalysisIfAvailable<MachineBlockFrequencyInfoWrapperPass>();
-  if (!MBFIWrapper)
+uint64_t RegBankSelectImpl::MBBInsertPoint::frequency(
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) const {
+  const MachineBlockFrequencyInfo *MBFI = GetCachedMBFI();
+  if (!MBFI)
     return 1;
-  return MBFIWrapper->getMBFI().getBlockFreq(&MBB).getFrequency();
+  return MBFI->getBlockFreq(&MBB).getFrequency();
 }
 
-void RegBankSelect::EdgeInsertPoint::materialize() {
+void RegBankSelectImpl::EdgeInsertPoint::materialize() {
   // If we end up repairing twice at the same place before materializing the
   // insertion point, we may think we have to split an edge twice.
   // We should have a factory for the insert point such that identical points
   // are the same instance.
   assert(Src.isSuccessor(DstOrSplit) && DstOrSplit->isPredecessor(&Src) &&
          "This point has already been split");
-  MachineBasicBlock *NewBB = Src.SplitCriticalEdge(DstOrSplit, P);
+  MachineBasicBlock *NewBB = Src.SplitCriticalEdge(DstOrSplit, P, MFAM);
   assert(NewBB && "Invalid call to materialize");
   // We reuse the destination block to hold the information of the new block.
   DstOrSplit = NewBB;
 }
 
-uint64_t RegBankSelect::EdgeInsertPoint::frequency(const Pass &P) const {
-  const auto *MBFIWrapper =
-      P.getAnalysisIfAvailable<MachineBlockFrequencyInfoWrapperPass>();
-  if (!MBFIWrapper)
+uint64_t RegBankSelectImpl::EdgeInsertPoint::frequency(
+    function_ref<MachineBlockFrequencyInfo *()> GetCachedMBFI,
+    function_ref<MachineBranchProbabilityInfo *()> GetCachedMBPI) const {
+  const MachineBlockFrequencyInfo *MBFI = GetCachedMBFI();
+  if (!MBFI)
     return 1;
-  const auto *MBFI = &MBFIWrapper->getMBFI();
   if (WasMaterialized)
     return MBFI->getBlockFreq(DstOrSplit).getFrequency();
 
-  auto *MBPIWrapper =
-      P.getAnalysisIfAvailable<MachineBranchProbabilityInfoWrapperPass>();
-  const MachineBranchProbabilityInfo *MBPI =
-      MBPIWrapper ? &MBPIWrapper->getMBPI() : nullptr;
+  const MachineBranchProbabilityInfo *MBPI = GetCachedMBPI();
   if (!MBPI)
     return 1;
   // The basic block will be on the edge.
@@ -982,7 +1607,7 @@ uint64_t RegBankSelect::EdgeInsertPoint::frequency(const Pass &P) const {
       .getFrequency();
 }
 
-bool RegBankSelect::EdgeInsertPoint::canMaterialize() const {
+bool RegBankSelectImpl::EdgeInsertPoint::canMaterialize() const {
   // If this is not a critical edge, we should not have used this insert
   // point. Indeed, either the successor or the predecessor should
   // have do.
@@ -991,10 +1616,10 @@ bool RegBankSelect::EdgeInsertPoint::canMaterialize() const {
   return Src.canSplitCriticalEdge(DstOrSplit);
 }
 
-RegBankSelect::MappingCost::MappingCost(BlockFrequency LocalFreq)
+RegBankSelectImpl::MappingCost::MappingCost(BlockFrequency LocalFreq)
     : LocalFreq(LocalFreq.getFrequency()) {}
 
-bool RegBankSelect::MappingCost::addLocalCost(uint64_t Cost) {
+bool RegBankSelectImpl::MappingCost::addLocalCost(uint64_t Cost) {
   // Check if this overflows.
   if (LocalCost + Cost < LocalCost) {
     saturate();
@@ -1004,7 +1629,7 @@ bool RegBankSelect::MappingCost::addLocalCost(uint64_t Cost) {
   return isSaturated();
 }
 
-bool RegBankSelect::MappingCost::addNonLocalCost(uint64_t Cost) {
+bool RegBankSelectImpl::MappingCost::addNonLocalCost(uint64_t Cost) {
   // Check if this overflows.
   if (NonLocalCost + Cost < NonLocalCost) {
     saturate();
@@ -1014,21 +1639,22 @@ bool RegBankSelect::MappingCost::addNonLocalCost(uint64_t Cost) {
   return isSaturated();
 }
 
-bool RegBankSelect::MappingCost::isSaturated() const {
+bool RegBankSelectImpl::MappingCost::isSaturated() const {
   return LocalCost == UINT64_MAX - 1 && NonLocalCost == UINT64_MAX &&
          LocalFreq == UINT64_MAX;
 }
 
-void RegBankSelect::MappingCost::saturate() {
+void RegBankSelectImpl::MappingCost::saturate() {
   *this = ImpossibleCost();
   --LocalCost;
 }
 
-RegBankSelect::MappingCost RegBankSelect::MappingCost::ImpossibleCost() {
+RegBankSelectImpl::MappingCost
+RegBankSelectImpl::MappingCost::ImpossibleCost() {
   return MappingCost(UINT64_MAX, UINT64_MAX, UINT64_MAX);
 }
 
-bool RegBankSelect::MappingCost::operator<(const MappingCost &Cost) const {
+bool RegBankSelectImpl::MappingCost::operator<(const MappingCost &Cost) const {
   // Sort out the easy cases.
   if (*this == Cost)
     return false;
@@ -1105,19 +1731,19 @@ bool RegBankSelect::MappingCost::operator<(const MappingCost &Cost) const {
   return ThisScaledCost < OtherScaledCost;
 }
 
-bool RegBankSelect::MappingCost::operator==(const MappingCost &Cost) const {
+bool RegBankSelectImpl::MappingCost::operator==(const MappingCost &Cost) const {
   return LocalCost == Cost.LocalCost && NonLocalCost == Cost.NonLocalCost &&
          LocalFreq == Cost.LocalFreq;
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-LLVM_DUMP_METHOD void RegBankSelect::MappingCost::dump() const {
+LLVM_DUMP_METHOD void RegBankSelectImpl::MappingCost::dump() const {
   print(dbgs());
   dbgs() << '\n';
 }
 #endif
 
-void RegBankSelect::MappingCost::print(raw_ostream &OS) const {
+void RegBankSelectImpl::MappingCost::print(raw_ostream &OS) const {
   if (*this == ImpossibleCost()) {
     OS << "impossible";
     return;
@@ -1128,3 +1754,45 @@ void RegBankSelect::MappingCost::print(raw_ostream &OS) const {
   }
   OS << LocalFreq << " * " << LocalCost << " + " << NonLocalCost;
 }
+
+bool RegBankSelectLegacy::runOnMachineFunction(MachineFunction &MF) {
+  RegBankSelectImpl Impl(OptMode);
+  return Impl.runOnMachineFunction(
+      MF, this, nullptr,
+      [&]() {
+        return &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
+      },
+      [&]() {
+        return &getAnalysis<MachineBranchProbabilityInfoWrapperPass>()
+                    .getMBPI();
+      },
+      [&]() {
+        return &getAnalysisIfAvailable<MachineBlockFrequencyInfoWrapperPass>()
+                    ->getMBFI();
+      },
+      [&]() {
+        return &getAnalysisIfAvailable<
+                    MachineBranchProbabilityInfoWrapperPass>()
+                    ->getMBPI();
+      });
+}
+
+RegBankSelectPass::RegBankSelectPass(RegBankSelectMode RunningMode)
+    : OptMode(RunningMode) {}
+
+PreservedAnalyses RegBankSelectPass::run(MachineFunction &MF,
+                                         MachineFunctionAnalysisManager &MFAM) {
+  MFPropsModifier _(*this, MF);
+  RegBankSelectImpl Impl(OptMode);
+  bool Changed = Impl.runOnMachineFunction(
+      MF, nullptr, &MFAM,
+      [&]() { return &MFAM.getResult<MachineBlockFrequencyAnalysis>(MF); },
+      [&]() { return &MFAM.getResult<MachineBranchProbabilityAnalysis>(MF); },
+      [&]() { return MFAM.getCachedResult<MachineBlockFrequencyAnalysis>(MF); },
+      [&]() {
+        return MFAM.getCachedResult<MachineBranchProbabilityAnalysis>(MF);
+      });
+  return Changed ? getMachineFunctionPassPreservedAnalyses()
+                       .preserveSet<CFGAnalyses>()
+                 : PreservedAnalyses::all();
+}

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index ccda9a3705db8..e6bd34f285eb9 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -110,6 +110,7 @@
 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
 #include "llvm/CodeGen/GlobalISel/LoadStoreOpt.h"
 #include "llvm/CodeGen/GlobalISel/Localizer.h"
+#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
 #include "llvm/CodeGen/GlobalMerge.h"
 #include "llvm/CodeGen/GlobalMergeFunctions.h"
 #include "llvm/CodeGen/HardwareLoops.h"

diff  --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 05ade33bfa8fa..2669647a8f56b 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -802,7 +802,7 @@ void AArch64PassConfig::addPreRegBankSelect() {
 }
 
 bool AArch64PassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
index 40cd57eec571f..ea993dd33f550 100644
--- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp
@@ -509,7 +509,7 @@ bool ARMPassConfig::addLegalizeMachineIR() {
 }
 
 bool ARMPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
index 66d3582cfc36a..88b58436b749d 100644
--- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp
+++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp
@@ -167,7 +167,7 @@ bool BPFPassConfig::addLegalizeMachineIR() {
 }
 
 bool BPFPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
index 25f717a5d52ac..8b0903ff324cb 100644
--- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp
@@ -323,7 +323,7 @@ void MipsPassConfig::addPreRegBankSelect() {
 }
 
 bool MipsPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
index a234eff4460e3..6a7de59db98f9 100644
--- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -595,7 +595,7 @@ bool PPCPassConfig::addLegalizeMachineIR() {
 }
 
 bool PPCPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 94a258574ee56..af2f77ebd933e 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -546,7 +546,7 @@ void RISCVPassConfig::addPreRegBankSelect() {
 }
 
 bool RISCVPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index 7a4e236ac522a..f200bcc17b108 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -270,7 +270,7 @@ bool SPIRVPassConfig::addLegalizeMachineIR() {
 
 // Do not add the RegBankSelect pass, as we only ever need virtual registers.
 bool SPIRVPassConfig::addRegBankSelect() {
-  disablePass(&RegBankSelect::ID);
+  disablePass(&RegBankSelectLegacy::ID);
   return false;
 }
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 739a6fc2e9fbe..e41743a227da0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -537,7 +537,7 @@ void WebAssemblyPassConfig::addPreRegBankSelect() {
 }
 
 bool WebAssemblyPassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 1d1ad4e1b0034..1169e78b252f4 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -478,7 +478,7 @@ bool X86PassConfig::addLegalizeMachineIR() {
 }
 
 bool X86PassConfig::addRegBankSelect() {
-  addPass(new RegBankSelect());
+  addPass(new RegBankSelectLegacy());
   return false;
 }
 

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/regbank-ceil.mir b/llvm/test/CodeGen/AArch64/GlobalISel/regbank-ceil.mir
index 1d26a9af1f72f..560fbd587274a 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/regbank-ceil.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/regbank-ceil.mir
@@ -1,5 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
 # RUN: llc -mtriple=aarch64 -run-pass=reg-bank-select -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64 -passes=reg-bank-select %s -o - | FileCheck %s
 
 ...
 ---


        


More information about the llvm-commits mailing list