Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:26

0001 //=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// \file
0010 /// This file describes the interface of the MachineFunctionPass
0011 /// responsible for assigning the generic virtual registers to register bank.
0012 ///
0013 /// By default, the reg bank selector relies on local decisions to
0014 /// assign the register bank. In other words, it looks at one instruction
0015 /// at a time to decide where the operand of that instruction should live.
0016 ///
0017 /// At higher optimization level, we could imagine that the reg bank selector
0018 /// would use more global analysis and do crazier thing like duplicating
0019 /// instructions and so on. This is future work.
0020 ///
0021 /// For now, the pass uses a greedy algorithm to decide where the operand
0022 /// of an instruction should live. It asks the target which banks may be
0023 /// used for each operand of the instruction and what is the cost. Then,
0024 /// it chooses the solution which minimize the cost of the instruction plus
0025 /// the cost of any move that may be needed to the values into the right
0026 /// register bank.
0027 /// In other words, the cost for an instruction on a register bank RegBank
0028 /// is: Cost of I on RegBank plus the sum of the cost for bringing the
0029 /// input operands from their current register bank to RegBank.
0030 /// Thus, the following formula:
0031 /// cost(I, RegBank) = cost(I.Opcode, RegBank) +
0032 ///    sum(for each arg in I.arguments: costCrossCopy(arg.RegBank, RegBank))
0033 ///
0034 /// E.g., Let say we are assigning the register bank for the instruction
0035 /// defining v2.
0036 /// v0(A_REGBANK) = ...
0037 /// v1(A_REGBANK) = ...
0038 /// v2 = G_ADD i32 v0, v1 <-- MI
0039 ///
0040 /// The target may say it can generate G_ADD i32 on register bank A and B
0041 /// with a cost of respectively 5 and 1.
0042 /// Then, let say the cost of a cross register bank copies from A to B is 1.
0043 /// The reg bank selector would compare the following two costs:
0044 /// cost(MI, A_REGBANK) = cost(G_ADD, A_REGBANK) + cost(v0.RegBank, A_REGBANK) +
0045 ///    cost(v1.RegBank, A_REGBANK)
0046 ///                     = 5 + cost(A_REGBANK, A_REGBANK) + cost(A_REGBANK,
0047 ///                                                             A_REGBANK)
0048 ///                     = 5 + 0 + 0 = 5
0049 /// cost(MI, B_REGBANK) = cost(G_ADD, B_REGBANK) + cost(v0.RegBank, B_REGBANK) +
0050 ///    cost(v1.RegBank, B_REGBANK)
0051 ///                     = 1 + cost(A_REGBANK, B_REGBANK) + cost(A_REGBANK,
0052 ///                                                             B_REGBANK)
0053 ///                     = 1 + 1 + 1 = 3
0054 /// Therefore, in this specific example, the reg bank selector would choose
0055 /// bank B for MI.
0056 /// v0(A_REGBANK) = ...
0057 /// v1(A_REGBANK) = ...
0058 /// tmp0(B_REGBANK) = COPY v0
0059 /// tmp1(B_REGBANK) = COPY v1
0060 /// v2(B_REGBANK) = G_ADD i32 tmp0, tmp1
0061 //
0062 //===----------------------------------------------------------------------===//
0063 
0064 #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
0065 #define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
0066 
0067 #include "llvm/ADT/SmallVector.h"
0068 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
0069 #include "llvm/CodeGen/MachineBasicBlock.h"
0070 #include "llvm/CodeGen/MachineFunctionPass.h"
0071 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
0072 #include "llvm/CodeGen/RegisterBankInfo.h"
0073 #include <cassert>
0074 #include <cstdint>
0075 #include <memory>
0076 
0077 namespace llvm {
0078 
0079 class BlockFrequency;
0080 class MachineBlockFrequencyInfo;
0081 class MachineBranchProbabilityInfo;
0082 class MachineOperand;
0083 class MachineRegisterInfo;
0084 class Pass;
0085 class raw_ostream;
0086 class TargetPassConfig;
0087 class TargetRegisterInfo;
0088 
0089 /// This pass implements the reg bank selector pass used in the GlobalISel
0090 /// pipeline. At the end of this pass, all register operands have been assigned
0091 class RegBankSelect : public MachineFunctionPass {
0092 public:
0093   static char ID;
0094 
0095   /// List of the modes supported by the RegBankSelect pass.
0096   enum Mode {
0097     /// Assign the register banks as fast as possible (default).
0098     Fast,
0099     /// Greedily minimize the cost of assigning register banks.
0100     /// This should produce code of greater quality, but will
0101     /// require more compile time.
0102     Greedy
0103   };
0104 
0105   /// Abstract class used to represent an insertion point in a CFG.
0106   /// This class records an insertion point and materializes it on
0107   /// demand.
0108   /// It allows to reason about the frequency of this insertion point,
0109   /// without having to logically materialize it (e.g., on an edge),
0110   /// before we actually need to insert something.
0111   class InsertPoint {
0112   protected:
0113     /// Tell if the insert point has already been materialized.
0114     bool WasMaterialized = false;
0115 
0116     /// Materialize the insertion point.
0117     ///
0118     /// If isSplit() is true, this involves actually splitting
0119     /// the block or edge.
0120     ///
0121     /// \post getPointImpl() returns a valid iterator.
0122     /// \post getInsertMBBImpl() returns a valid basic block.
0123     /// \post isSplit() == false ; no more splitting should be required.
0124     virtual void materialize() = 0;
0125 
0126     /// Return the materialized insertion basic block.
0127     /// Code will be inserted into that basic block.
0128     ///
0129     /// \pre ::materialize has been called.
0130     virtual MachineBasicBlock &getInsertMBBImpl() = 0;
0131 
0132     /// Return the materialized insertion point.
0133     /// Code will be inserted before that point.
0134     ///
0135     /// \pre ::materialize has been called.
0136     virtual MachineBasicBlock::iterator getPointImpl() = 0;
0137 
0138   public:
0139     virtual ~InsertPoint() = default;
0140 
0141     /// The first call to this method will cause the splitting to
0142     /// happen if need be, then sub sequent calls just return
0143     /// the iterator to that point. I.e., no more splitting will
0144     /// occur.
0145     ///
0146     /// \return The iterator that should be used with
0147     /// MachineBasicBlock::insert. I.e., additional code happens
0148     /// before that point.
0149     MachineBasicBlock::iterator getPoint() {
0150       if (!WasMaterialized) {
0151         WasMaterialized = true;
0152         assert(canMaterialize() && "Impossible to materialize this point");
0153         materialize();
0154       }
0155       // When we materialized the point we should have done the splitting.
0156       assert(!isSplit() && "Wrong pre-condition");
0157       return getPointImpl();
0158     }
0159 
0160     /// The first call to this method will cause the splitting to
0161     /// happen if need be, then sub sequent calls just return
0162     /// the basic block that contains the insertion point.
0163     /// I.e., no more splitting will occur.
0164     ///
0165     /// \return The basic block should be used with
0166     /// MachineBasicBlock::insert and ::getPoint. The new code should
0167     /// happen before that point.
0168     MachineBasicBlock &getInsertMBB() {
0169       if (!WasMaterialized) {
0170         WasMaterialized = true;
0171         assert(canMaterialize() && "Impossible to materialize this point");
0172         materialize();
0173       }
0174       // When we materialized the point we should have done the splitting.
0175       assert(!isSplit() && "Wrong pre-condition");
0176       return getInsertMBBImpl();
0177     }
0178 
0179     /// Insert \p MI in the just before ::getPoint()
0180     MachineBasicBlock::iterator insert(MachineInstr &MI) {
0181       return getInsertMBB().insert(getPoint(), &MI);
0182     }
0183 
0184     /// Does this point involve splitting an edge or block?
0185     /// As soon as ::getPoint is called and thus, the point
0186     /// materialized, the point will not require splitting anymore,
0187     /// i.e., this will return false.
0188     virtual bool isSplit() const { return false; }
0189 
0190     /// Frequency of the insertion point.
0191     /// \p P is used to access the various analysis that will help to
0192     /// get that information, like MachineBlockFrequencyInfo.  If \p P
0193     /// does not contain enough to return the actual frequency,
0194     /// this returns 1.
0195     virtual uint64_t frequency(const Pass &P) const { return 1; }
0196 
0197     /// Check whether this insertion point can be materialized.
0198     /// As soon as ::getPoint is called and thus, the point materialized
0199     /// calling this method does not make sense.
0200     virtual bool canMaterialize() const { return false; }
0201   };
0202 
0203   /// Insertion point before or after an instruction.
0204   class InstrInsertPoint : public InsertPoint {
0205   private:
0206     /// Insertion point.
0207     MachineInstr &Instr;
0208 
0209     /// Does the insertion point is before or after Instr.
0210     bool Before;
0211 
0212     void materialize() override;
0213 
0214     MachineBasicBlock::iterator getPointImpl() override {
0215       if (Before)
0216         return Instr;
0217       return Instr.getNextNode() ? *Instr.getNextNode()
0218                                  : Instr.getParent()->end();
0219     }
0220 
0221     MachineBasicBlock &getInsertMBBImpl() override {
0222       return *Instr.getParent();
0223     }
0224 
0225   public:
0226     /// Create an insertion point before (\p Before=true) or after \p Instr.
0227     InstrInsertPoint(MachineInstr &Instr, bool Before = true);
0228 
0229     bool isSplit() const override;
0230     uint64_t frequency(const Pass &P) const override;
0231 
0232     // Worst case, we need to slice the basic block, but that is still doable.
0233     bool canMaterialize() const override { return true; }
0234   };
0235 
0236   /// Insertion point at the beginning or end of a basic block.
0237   class MBBInsertPoint : public InsertPoint {
0238   private:
0239     /// Insertion point.
0240     MachineBasicBlock &MBB;
0241 
0242     /// Does the insertion point is at the beginning or end of MBB.
0243     bool Beginning;
0244 
0245     void materialize() override { /*Nothing to do to materialize*/
0246     }
0247 
0248     MachineBasicBlock::iterator getPointImpl() override {
0249       return Beginning ? MBB.begin() : MBB.end();
0250     }
0251 
0252     MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
0253 
0254   public:
0255     MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
0256         : MBB(MBB), Beginning(Beginning) {
0257       // If we try to insert before phis, we should use the insertion
0258       // points on the incoming edges.
0259       assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
0260              "Invalid beginning point");
0261       // If we try to insert after the terminators, we should use the
0262       // points on the outcoming edges.
0263       assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
0264              "Invalid end point");
0265     }
0266 
0267     bool isSplit() const override { return false; }
0268     uint64_t frequency(const Pass &P) const override;
0269     bool canMaterialize() const override { return true; };
0270   };
0271 
0272   /// Insertion point on an edge.
0273   class EdgeInsertPoint : public InsertPoint {
0274   private:
0275     /// Source of the edge.
0276     MachineBasicBlock &Src;
0277 
0278     /// Destination of the edge.
0279     /// After the materialization is done, this hold the basic block
0280     /// that resulted from the splitting.
0281     MachineBasicBlock *DstOrSplit;
0282 
0283     /// P is used to update the analysis passes as applicable.
0284     Pass &P;
0285 
0286     void materialize() override;
0287 
0288     MachineBasicBlock::iterator getPointImpl() override {
0289       // DstOrSplit should be the Split block at this point.
0290       // I.e., it should have one predecessor, Src, and one successor,
0291       // the original Dst.
0292       assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
0293              DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
0294              "Did not split?!");
0295       return DstOrSplit->begin();
0296     }
0297 
0298     MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
0299 
0300   public:
0301     EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
0302         : Src(Src), DstOrSplit(&Dst), P(P) {}
0303 
0304     bool isSplit() const override {
0305       return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
0306     }
0307 
0308     uint64_t frequency(const Pass &P) const override;
0309     bool canMaterialize() const override;
0310   };
0311 
0312   /// Struct used to represent the placement of a repairing point for
0313   /// a given operand.
0314   class RepairingPlacement {
0315   public:
0316     /// Define the kind of action this repairing needs.
0317     enum RepairingKind {
0318       /// Nothing to repair, just drop this action.
0319       None,
0320       /// Reparing code needs to happen before InsertPoints.
0321       Insert,
0322       /// (Re)assign the register bank of the operand.
0323       Reassign,
0324       /// Mark this repairing placement as impossible.
0325       Impossible
0326     };
0327 
0328     /// \name Convenient types for a list of insertion points.
0329     /// @{
0330     using InsertionPoints = SmallVector<std::unique_ptr<InsertPoint>, 2>;
0331     using insertpt_iterator = InsertionPoints::iterator;
0332     using const_insertpt_iterator = InsertionPoints::const_iterator;
0333     /// @}
0334 
0335   private:
0336     /// Kind of repairing.
0337     RepairingKind Kind;
0338     /// Index of the operand that will be repaired.
0339     unsigned OpIdx;
0340     /// Are all the insert points materializeable?
0341     bool CanMaterialize;
0342     /// Is there any of the insert points needing splitting?
0343     bool HasSplit = false;
0344     /// Insertion point for the repair code.
0345     /// The repairing code needs to happen just before these points.
0346     InsertionPoints InsertPoints;
0347     /// Some insertion points may need to update the liveness and such.
0348     Pass &P;
0349 
0350   public:
0351     /// Create a repairing placement for the \p OpIdx-th operand of
0352     /// \p MI. \p TRI is used to make some checks on the register aliases
0353     /// if the machine operand is a physical register. \p P is used to
0354     /// to update liveness information and such when materializing the
0355     /// points.
0356     RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
0357                        const TargetRegisterInfo &TRI, Pass &P,
0358                        RepairingKind Kind = RepairingKind::Insert);
0359 
0360     /// \name Getters.
0361     /// @{
0362     RepairingKind getKind() const { return Kind; }
0363     unsigned getOpIdx() const { return OpIdx; }
0364     bool canMaterialize() const { return CanMaterialize; }
0365     bool hasSplit() { return HasSplit; }
0366     /// @}
0367 
0368     /// \name Overloaded methods to add an insertion point.
0369     /// @{
0370     /// Add a MBBInsertionPoint to the list of InsertPoints.
0371     void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
0372     /// Add a InstrInsertionPoint to the list of InsertPoints.
0373     void addInsertPoint(MachineInstr &MI, bool Before);
0374     /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
0375     void addInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst);
0376     /// Add an InsertPoint to the list of insert points.
0377     /// This method takes the ownership of &\p Point.
0378     void addInsertPoint(InsertPoint &Point);
0379     /// @}
0380 
0381     /// \name Accessors related to the insertion points.
0382     /// @{
0383     insertpt_iterator begin() { return InsertPoints.begin(); }
0384     insertpt_iterator end() { return InsertPoints.end(); }
0385 
0386     const_insertpt_iterator begin() const { return InsertPoints.begin(); }
0387     const_insertpt_iterator end() const { return InsertPoints.end(); }
0388 
0389     unsigned getNumInsertPoints() const { return InsertPoints.size(); }
0390     /// @}
0391 
0392     /// Change the type of this repairing placement to \p NewKind.
0393     /// It is not possible to switch a repairing placement to the
0394     /// RepairingKind::Insert. There is no fundamental problem with
0395     /// that, but no uses as well, so do not support it for now.
0396     ///
0397     /// \pre NewKind != RepairingKind::Insert
0398     /// \post getKind() == NewKind
0399     void switchTo(RepairingKind NewKind) {
0400       assert(NewKind != Kind && "Already of the right Kind");
0401       Kind = NewKind;
0402       InsertPoints.clear();
0403       CanMaterialize = NewKind != RepairingKind::Impossible;
0404       HasSplit = false;
0405       assert(NewKind != RepairingKind::Insert &&
0406              "We would need more MI to switch to Insert");
0407     }
0408   };
0409 
0410 protected:
0411   /// Helper class used to represent the cost for mapping an instruction.
0412   /// When mapping an instruction, we may introduce some repairing code.
0413   /// In most cases, the repairing code is local to the instruction,
0414   /// thus, we can omit the basic block frequency from the cost.
0415   /// However, some alternatives may produce non-local cost, e.g., when
0416   /// repairing a phi, and thus we then need to scale the local cost
0417   /// to the non-local cost. This class does this for us.
0418   /// \note: We could simply always scale the cost. The problem is that
0419   /// there are higher chances that we saturate the cost easier and end
0420   /// up having the same cost for actually different alternatives.
0421   /// Another option would be to use APInt everywhere.
0422   class MappingCost {
0423   private:
0424     /// Cost of the local instructions.
0425     /// This cost is free of basic block frequency.
0426     uint64_t LocalCost = 0;
0427     /// Cost of the non-local instructions.
0428     /// This cost should include the frequency of the related blocks.
0429     uint64_t NonLocalCost = 0;
0430     /// Frequency of the block where the local instructions live.
0431     uint64_t LocalFreq;
0432 
0433     MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
0434         : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
0435           LocalFreq(LocalFreq) {}
0436 
0437     /// Check if this cost is saturated.
0438     bool isSaturated() const;
0439 
0440   public:
0441     /// Create a MappingCost assuming that most of the instructions
0442     /// will occur in a basic block with \p LocalFreq frequency.
0443     MappingCost(BlockFrequency LocalFreq);
0444 
0445     /// Add \p Cost to the local cost.
0446     /// \return true if this cost is saturated, false otherwise.
0447     bool addLocalCost(uint64_t Cost);
0448 
0449     /// Add \p Cost to the non-local cost.
0450     /// Non-local cost should reflect the frequency of their placement.
0451     /// \return true if this cost is saturated, false otherwise.
0452     bool addNonLocalCost(uint64_t Cost);
0453 
0454     /// Saturate the cost to the maximal representable value.
0455     void saturate();
0456 
0457     /// Return an instance of MappingCost that represents an
0458     /// impossible mapping.
0459     static MappingCost ImpossibleCost();
0460 
0461     /// Check if this is less than \p Cost.
0462     bool operator<(const MappingCost &Cost) const;
0463     /// Check if this is equal to \p Cost.
0464     bool operator==(const MappingCost &Cost) const;
0465     /// Check if this is not equal to \p Cost.
0466     bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
0467     /// Check if this is greater than \p Cost.
0468     bool operator>(const MappingCost &Cost) const {
0469       return *this != Cost && Cost < *this;
0470     }
0471 
0472     /// Print this on dbgs() stream.
0473     void dump() const;
0474 
0475     /// Print this on \p OS;
0476     void print(raw_ostream &OS) const;
0477 
0478     /// Overload the stream operator for easy debug printing.
0479     friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) {
0480       Cost.print(OS);
0481       return OS;
0482     }
0483   };
0484 
0485   /// Interface to the target lowering info related
0486   /// to register banks.
0487   const RegisterBankInfo *RBI = nullptr;
0488 
0489   /// MRI contains all the register class/bank information that this
0490   /// pass uses and updates.
0491   MachineRegisterInfo *MRI = nullptr;
0492 
0493   /// Information on the register classes for the current function.
0494   const TargetRegisterInfo *TRI = nullptr;
0495 
0496   /// Get the frequency of blocks.
0497   /// This is required for non-fast mode.
0498   MachineBlockFrequencyInfo *MBFI = nullptr;
0499 
0500   /// Get the frequency of the edges.
0501   /// This is required for non-fast mode.
0502   MachineBranchProbabilityInfo *MBPI = nullptr;
0503 
0504   /// Current optimization remark emitter. Used to report failures.
0505   std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
0506 
0507   /// Helper class used for every code morphing.
0508   MachineIRBuilder MIRBuilder;
0509 
0510   /// Optimization mode of the pass.
0511   Mode OptMode;
0512 
0513   /// Current target configuration. Controls how the pass handles errors.
0514   const TargetPassConfig *TPC;
0515 
0516   /// Assign the register bank of each operand of \p MI.
0517   /// \return True on success, false otherwise.
0518   bool assignInstr(MachineInstr &MI);
0519 
0520   /// Initialize the field members using \p MF.
0521   void init(MachineFunction &MF);
0522 
0523   /// Check if \p Reg is already assigned what is described by \p ValMapping.
0524   /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
0525   /// register bank.  I.e., no repairing is necessary to have the
0526   /// assignment match.
0527   bool assignmentMatch(Register Reg,
0528                        const RegisterBankInfo::ValueMapping &ValMapping,
0529                        bool &OnlyAssign) const;
0530 
0531   /// Insert repairing code for \p Reg as specified by \p ValMapping.
0532   /// The repairing placement is specified by \p RepairPt.
0533   /// \p NewVRegs contains all the registers required to remap \p Reg.
0534   /// In other words, the number of registers in NewVRegs must be equal
0535   /// to ValMapping.BreakDown.size().
0536   ///
0537   /// The transformation could be sketched as:
0538   /// \code
0539   /// ... = op Reg
0540   /// \endcode
0541   /// Becomes
0542   /// \code
0543   /// <NewRegs> = COPY or extract Reg
0544   /// ... = op Reg
0545   /// \endcode
0546   ///
0547   /// and
0548   /// \code
0549   /// Reg = op ...
0550   /// \endcode
0551   /// Becomes
0552   /// \code
0553   /// Reg = op ...
0554   /// Reg = COPY or build_sequence <NewRegs>
0555   /// \endcode
0556   ///
0557   /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
0558   ///
0559   /// \note The caller is supposed to do the rewriting of op if need be.
0560   /// I.e., Reg = op ... => <NewRegs> = NewOp ...
0561   ///
0562   /// \return True if the repairing worked, false otherwise.
0563   bool repairReg(MachineOperand &MO,
0564                  const RegisterBankInfo::ValueMapping &ValMapping,
0565                  RegBankSelect::RepairingPlacement &RepairPt,
0566                  const iterator_range<SmallVectorImpl<Register>::const_iterator>
0567                      &NewVRegs);
0568 
0569   /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
0570   /// The cost is free of basic block frequencies.
0571   /// \pre MO.isReg()
0572   /// \pre MO is assigned to a register bank.
0573   /// \pre ValMapping is a valid mapping for MO.
0574   uint64_t
0575   getRepairCost(const MachineOperand &MO,
0576                 const RegisterBankInfo::ValueMapping &ValMapping) const;
0577 
0578   /// Find the best mapping for \p MI from \p PossibleMappings.
0579   /// \return a reference on the best mapping in \p PossibleMappings.
0580   const RegisterBankInfo::InstructionMapping &
0581   findBestMapping(MachineInstr &MI,
0582                   RegisterBankInfo::InstructionMappings &PossibleMappings,
0583                   SmallVectorImpl<RepairingPlacement> &RepairPts);
0584 
0585   /// Compute the cost of mapping \p MI with \p InstrMapping and
0586   /// compute the repairing placement for such mapping in \p
0587   /// RepairPts.
0588   /// \p BestCost is used to specify when the cost becomes too high
0589   /// and thus it is not worth computing the RepairPts.  Moreover if
0590   /// \p BestCost == nullptr, the mapping cost is actually not
0591   /// computed.
0592   MappingCost
0593   computeMapping(MachineInstr &MI,
0594                  const RegisterBankInfo::InstructionMapping &InstrMapping,
0595                  SmallVectorImpl<RepairingPlacement> &RepairPts,
0596                  const MappingCost *BestCost = nullptr);
0597 
0598   /// When \p RepairPt involves splitting to repair \p MO for the
0599   /// given \p ValMapping, try to change the way we repair such that
0600   /// the splitting is not required anymore.
0601   ///
0602   /// \pre \p RepairPt.hasSplit()
0603   /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
0604   /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
0605   ///      that implied \p RepairPt.
0606   void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt,
0607                         const MachineOperand &MO,
0608                         const RegisterBankInfo::ValueMapping &ValMapping) const;
0609 
0610   /// Apply \p Mapping to \p MI. \p RepairPts represents the different
0611   /// mapping action that need to happen for the mapping to be
0612   /// applied.
0613   /// \return True if the mapping was applied sucessfully, false otherwise.
0614   bool applyMapping(MachineInstr &MI,
0615                     const RegisterBankInfo::InstructionMapping &InstrMapping,
0616                     SmallVectorImpl<RepairingPlacement> &RepairPts);
0617 
0618 public:
0619   /// Create a RegBankSelect pass with the specified \p RunningMode.
0620   RegBankSelect(Mode RunningMode = Fast);
0621 
0622   StringRef getPassName() const override { return "RegBankSelect"; }
0623 
0624   void getAnalysisUsage(AnalysisUsage &AU) const override;
0625 
0626   MachineFunctionProperties getRequiredProperties() const override {
0627     return MachineFunctionProperties()
0628         .set(MachineFunctionProperties::Property::IsSSA)
0629         .set(MachineFunctionProperties::Property::Legalized);
0630   }
0631 
0632   MachineFunctionProperties getSetProperties() const override {
0633     return MachineFunctionProperties().set(
0634         MachineFunctionProperties::Property::RegBankSelected);
0635   }
0636 
0637   MachineFunctionProperties getClearedProperties() const override {
0638     return MachineFunctionProperties()
0639       .set(MachineFunctionProperties::Property::NoPHIs);
0640   }
0641 
0642   /// Check that our input is fully legal: we require the function to have the
0643   /// Legalized property, so it should be.
0644   ///
0645   /// FIXME: This should be in the MachineVerifier.
0646   bool checkFunctionIsLegal(MachineFunction &MF) const;
0647 
0648   /// Walk through \p MF and assign a register bank to every virtual register
0649   /// that are still mapped to nothing.
0650   /// The target needs to provide a RegisterBankInfo and in particular
0651   /// override RegisterBankInfo::getInstrMapping.
0652   ///
0653   /// Simplified algo:
0654   /// \code
0655   ///   RBI = MF.subtarget.getRegBankInfo()
0656   ///   MIRBuilder.setMF(MF)
0657   ///   for each bb in MF
0658   ///     for each inst in bb
0659   ///       MIRBuilder.setInstr(inst)
0660   ///       MappingCosts = RBI.getMapping(inst);
0661   ///       Idx = findIdxOfMinCost(MappingCosts)
0662   ///       CurRegBank = MappingCosts[Idx].RegBank
0663   ///       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
0664   ///       for each argument in inst
0665   ///         if (CurRegBank != argument.RegBank)
0666   ///           ArgReg = argument.getReg()
0667   ///           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
0668   ///           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
0669   ///           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
0670   /// \endcode
0671   bool assignRegisterBanks(MachineFunction &MF);
0672 
0673   bool runOnMachineFunction(MachineFunction &MF) override;
0674 };
0675 
0676 } // end namespace llvm
0677 
0678 #endif // LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H