xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1  //=- llvm/CodeGen/GlobalISel/RegBankSelect.h - Reg Bank Selector --*- C++ -*-=//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  //
9  /// \file
10  /// This file describes the interface of the MachineFunctionPass
11  /// responsible for assigning the generic virtual registers to register bank.
12  ///
13  /// By default, the reg bank selector relies on local decisions to
14  /// assign the register bank. In other words, it looks at one instruction
15  /// at a time to decide where the operand of that instruction should live.
16  ///
17  /// At higher optimization level, we could imagine that the reg bank selector
18  /// would use more global analysis and do crazier thing like duplicating
19  /// instructions and so on. This is future work.
20  ///
21  /// For now, the pass uses a greedy algorithm to decide where the operand
22  /// of an instruction should live. It asks the target which banks may be
23  /// used for each operand of the instruction and what is the cost. Then,
24  /// it chooses the solution which minimize the cost of the instruction plus
25  /// the cost of any move that may be needed to the values into the right
26  /// register bank.
27  /// In other words, the cost for an instruction on a register bank RegBank
28  /// is: Cost of I on RegBank plus the sum of the cost for bringing the
29  /// input operands from their current register bank to RegBank.
30  /// Thus, the following formula:
31  /// cost(I, RegBank) = cost(I.Opcode, RegBank) +
32  ///    sum(for each arg in I.arguments: costCrossCopy(arg.RegBank, RegBank))
33  ///
34  /// E.g., Let say we are assigning the register bank for the instruction
35  /// defining v2.
36  /// v0(A_REGBANK) = ...
37  /// v1(A_REGBANK) = ...
38  /// v2 = G_ADD i32 v0, v1 <-- MI
39  ///
40  /// The target may say it can generate G_ADD i32 on register bank A and B
41  /// with a cost of respectively 5 and 1.
42  /// Then, let say the cost of a cross register bank copies from A to B is 1.
43  /// The reg bank selector would compare the following two costs:
44  /// cost(MI, A_REGBANK) = cost(G_ADD, A_REGBANK) + cost(v0.RegBank, A_REGBANK) +
45  ///    cost(v1.RegBank, A_REGBANK)
46  ///                     = 5 + cost(A_REGBANK, A_REGBANK) + cost(A_REGBANK,
47  ///                                                             A_REGBANK)
48  ///                     = 5 + 0 + 0 = 5
49  /// cost(MI, B_REGBANK) = cost(G_ADD, B_REGBANK) + cost(v0.RegBank, B_REGBANK) +
50  ///    cost(v1.RegBank, B_REGBANK)
51  ///                     = 1 + cost(A_REGBANK, B_REGBANK) + cost(A_REGBANK,
52  ///                                                             B_REGBANK)
53  ///                     = 1 + 1 + 1 = 3
54  /// Therefore, in this specific example, the reg bank selector would choose
55  /// bank B for MI.
56  /// v0(A_REGBANK) = ...
57  /// v1(A_REGBANK) = ...
58  /// tmp0(B_REGBANK) = COPY v0
59  /// tmp1(B_REGBANK) = COPY v1
60  /// v2(B_REGBANK) = G_ADD i32 tmp0, tmp1
61  //
62  //===----------------------------------------------------------------------===//
63  
64  #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
65  #define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
66  
67  #include "llvm/ADT/SmallVector.h"
68  #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
69  #include "llvm/CodeGen/MachineBasicBlock.h"
70  #include "llvm/CodeGen/MachineFunctionPass.h"
71  #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
72  #include "llvm/CodeGen/RegisterBankInfo.h"
73  #include <cassert>
74  #include <cstdint>
75  #include <memory>
76  
77  namespace llvm {
78  
79  class BlockFrequency;
80  class MachineBlockFrequencyInfo;
81  class MachineBranchProbabilityInfo;
82  class MachineOperand;
83  class MachineRegisterInfo;
84  class Pass;
85  class raw_ostream;
86  class TargetPassConfig;
87  class TargetRegisterInfo;
88  
89  /// This pass implements the reg bank selector pass used in the GlobalISel
90  /// pipeline. At the end of this pass, all register operands have been assigned
91  class RegBankSelect : public MachineFunctionPass {
92  public:
93    static char ID;
94  
95    /// List of the modes supported by the RegBankSelect pass.
96    enum Mode {
97      /// Assign the register banks as fast as possible (default).
98      Fast,
99      /// Greedily minimize the cost of assigning register banks.
100      /// This should produce code of greater quality, but will
101      /// require more compile time.
102      Greedy
103    };
104  
105    /// Abstract class used to represent an insertion point in a CFG.
106    /// This class records an insertion point and materializes it on
107    /// demand.
108    /// It allows to reason about the frequency of this insertion point,
109    /// without having to logically materialize it (e.g., on an edge),
110    /// before we actually need to insert something.
111    class InsertPoint {
112    protected:
113      /// Tell if the insert point has already been materialized.
114      bool WasMaterialized = false;
115  
116      /// Materialize the insertion point.
117      ///
118      /// If isSplit() is true, this involves actually splitting
119      /// the block or edge.
120      ///
121      /// \post getPointImpl() returns a valid iterator.
122      /// \post getInsertMBBImpl() returns a valid basic block.
123      /// \post isSplit() == false ; no more splitting should be required.
124      virtual void materialize() = 0;
125  
126      /// Return the materialized insertion basic block.
127      /// Code will be inserted into that basic block.
128      ///
129      /// \pre ::materialize has been called.
130      virtual MachineBasicBlock &getInsertMBBImpl() = 0;
131  
132      /// Return the materialized insertion point.
133      /// Code will be inserted before that point.
134      ///
135      /// \pre ::materialize has been called.
136      virtual MachineBasicBlock::iterator getPointImpl() = 0;
137  
138    public:
139      virtual ~InsertPoint() = default;
140  
141      /// The first call to this method will cause the splitting to
142      /// happen if need be, then sub sequent calls just return
143      /// the iterator to that point. I.e., no more splitting will
144      /// occur.
145      ///
146      /// \return The iterator that should be used with
147      /// MachineBasicBlock::insert. I.e., additional code happens
148      /// before that point.
149      MachineBasicBlock::iterator getPoint() {
150        if (!WasMaterialized) {
151          WasMaterialized = true;
152          assert(canMaterialize() && "Impossible to materialize this point");
153          materialize();
154        }
155        // When we materialized the point we should have done the splitting.
156        assert(!isSplit() && "Wrong pre-condition");
157        return getPointImpl();
158      }
159  
160      /// The first call to this method will cause the splitting to
161      /// happen if need be, then sub sequent calls just return
162      /// the basic block that contains the insertion point.
163      /// I.e., no more splitting will occur.
164      ///
165      /// \return The basic block should be used with
166      /// MachineBasicBlock::insert and ::getPoint. The new code should
167      /// happen before that point.
168      MachineBasicBlock &getInsertMBB() {
169        if (!WasMaterialized) {
170          WasMaterialized = true;
171          assert(canMaterialize() && "Impossible to materialize this point");
172          materialize();
173        }
174        // When we materialized the point we should have done the splitting.
175        assert(!isSplit() && "Wrong pre-condition");
176        return getInsertMBBImpl();
177      }
178  
179      /// Insert \p MI in the just before ::getPoint()
180      MachineBasicBlock::iterator insert(MachineInstr &MI) {
181        return getInsertMBB().insert(getPoint(), &MI);
182      }
183  
184      /// Does this point involve splitting an edge or block?
185      /// As soon as ::getPoint is called and thus, the point
186      /// materialized, the point will not require splitting anymore,
187      /// i.e., this will return false.
188      virtual bool isSplit() const { return false; }
189  
190      /// Frequency of the insertion point.
191      /// \p P is used to access the various analysis that will help to
192      /// get that information, like MachineBlockFrequencyInfo.  If \p P
193      /// does not contain enough to return the actual frequency,
194      /// this returns 1.
195      virtual uint64_t frequency(const Pass &P) const { return 1; }
196  
197      /// Check whether this insertion point can be materialized.
198      /// As soon as ::getPoint is called and thus, the point materialized
199      /// calling this method does not make sense.
200      virtual bool canMaterialize() const { return false; }
201    };
202  
203    /// Insertion point before or after an instruction.
204    class InstrInsertPoint : public InsertPoint {
205    private:
206      /// Insertion point.
207      MachineInstr &Instr;
208  
209      /// Does the insertion point is before or after Instr.
210      bool Before;
211  
212      void materialize() override;
213  
214      MachineBasicBlock::iterator getPointImpl() override {
215        if (Before)
216          return Instr;
217        return Instr.getNextNode() ? *Instr.getNextNode()
218                                   : Instr.getParent()->end();
219      }
220  
221      MachineBasicBlock &getInsertMBBImpl() override {
222        return *Instr.getParent();
223      }
224  
225    public:
226      /// Create an insertion point before (\p Before=true) or after \p Instr.
227      InstrInsertPoint(MachineInstr &Instr, bool Before = true);
228  
229      bool isSplit() const override;
230      uint64_t frequency(const Pass &P) const override;
231  
232      // Worst case, we need to slice the basic block, but that is still doable.
233      bool canMaterialize() const override { return true; }
234    };
235  
236    /// Insertion point at the beginning or end of a basic block.
237    class MBBInsertPoint : public InsertPoint {
238    private:
239      /// Insertion point.
240      MachineBasicBlock &MBB;
241  
242      /// Does the insertion point is at the beginning or end of MBB.
243      bool Beginning;
244  
245      void materialize() override { /*Nothing to do to materialize*/
246      }
247  
248      MachineBasicBlock::iterator getPointImpl() override {
249        return Beginning ? MBB.begin() : MBB.end();
250      }
251  
252      MachineBasicBlock &getInsertMBBImpl() override { return MBB; }
253  
254    public:
255      MBBInsertPoint(MachineBasicBlock &MBB, bool Beginning = true)
256          : MBB(MBB), Beginning(Beginning) {
257        // If we try to insert before phis, we should use the insertion
258        // points on the incoming edges.
259        assert((!Beginning || MBB.getFirstNonPHI() == MBB.begin()) &&
260               "Invalid beginning point");
261        // If we try to insert after the terminators, we should use the
262        // points on the outcoming edges.
263        assert((Beginning || MBB.getFirstTerminator() == MBB.end()) &&
264               "Invalid end point");
265      }
266  
267      bool isSplit() const override { return false; }
268      uint64_t frequency(const Pass &P) const override;
269      bool canMaterialize() const override { return true; };
270    };
271  
272    /// Insertion point on an edge.
273    class EdgeInsertPoint : public InsertPoint {
274    private:
275      /// Source of the edge.
276      MachineBasicBlock &Src;
277  
278      /// Destination of the edge.
279      /// After the materialization is done, this hold the basic block
280      /// that resulted from the splitting.
281      MachineBasicBlock *DstOrSplit;
282  
283      /// P is used to update the analysis passes as applicable.
284      Pass &P;
285  
286      void materialize() override;
287  
288      MachineBasicBlock::iterator getPointImpl() override {
289        // DstOrSplit should be the Split block at this point.
290        // I.e., it should have one predecessor, Src, and one successor,
291        // the original Dst.
292        assert(DstOrSplit && DstOrSplit->isPredecessor(&Src) &&
293               DstOrSplit->pred_size() == 1 && DstOrSplit->succ_size() == 1 &&
294               "Did not split?!");
295        return DstOrSplit->begin();
296      }
297  
298      MachineBasicBlock &getInsertMBBImpl() override { return *DstOrSplit; }
299  
300    public:
301      EdgeInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst, Pass &P)
302          : Src(Src), DstOrSplit(&Dst), P(P) {}
303  
304      bool isSplit() const override {
305        return Src.succ_size() > 1 && DstOrSplit->pred_size() > 1;
306      }
307  
308      uint64_t frequency(const Pass &P) const override;
309      bool canMaterialize() const override;
310    };
311  
312    /// Struct used to represent the placement of a repairing point for
313    /// a given operand.
314    class RepairingPlacement {
315    public:
316      /// Define the kind of action this repairing needs.
317      enum RepairingKind {
318        /// Nothing to repair, just drop this action.
319        None,
320        /// Reparing code needs to happen before InsertPoints.
321        Insert,
322        /// (Re)assign the register bank of the operand.
323        Reassign,
324        /// Mark this repairing placement as impossible.
325        Impossible
326      };
327  
328      /// \name Convenient types for a list of insertion points.
329      /// @{
330      using InsertionPoints = SmallVector<std::unique_ptr<InsertPoint>, 2>;
331      using insertpt_iterator = InsertionPoints::iterator;
332      using const_insertpt_iterator = InsertionPoints::const_iterator;
333      /// @}
334  
335    private:
336      /// Kind of repairing.
337      RepairingKind Kind;
338      /// Index of the operand that will be repaired.
339      unsigned OpIdx;
340      /// Are all the insert points materializeable?
341      bool CanMaterialize;
342      /// Is there any of the insert points needing splitting?
343      bool HasSplit = false;
344      /// Insertion point for the repair code.
345      /// The repairing code needs to happen just before these points.
346      InsertionPoints InsertPoints;
347      /// Some insertion points may need to update the liveness and such.
348      Pass &P;
349  
350    public:
351      /// Create a repairing placement for the \p OpIdx-th operand of
352      /// \p MI. \p TRI is used to make some checks on the register aliases
353      /// if the machine operand is a physical register. \p P is used to
354      /// to update liveness information and such when materializing the
355      /// points.
356      RepairingPlacement(MachineInstr &MI, unsigned OpIdx,
357                         const TargetRegisterInfo &TRI, Pass &P,
358                         RepairingKind Kind = RepairingKind::Insert);
359  
360      /// \name Getters.
361      /// @{
362      RepairingKind getKind() const { return Kind; }
363      unsigned getOpIdx() const { return OpIdx; }
364      bool canMaterialize() const { return CanMaterialize; }
365      bool hasSplit() { return HasSplit; }
366      /// @}
367  
368      /// \name Overloaded methods to add an insertion point.
369      /// @{
370      /// Add a MBBInsertionPoint to the list of InsertPoints.
371      void addInsertPoint(MachineBasicBlock &MBB, bool Beginning);
372      /// Add a InstrInsertionPoint to the list of InsertPoints.
373      void addInsertPoint(MachineInstr &MI, bool Before);
374      /// Add an EdgeInsertionPoint (\p Src, \p Dst) to the list of InsertPoints.
375      void addInsertPoint(MachineBasicBlock &Src, MachineBasicBlock &Dst);
376      /// Add an InsertPoint to the list of insert points.
377      /// This method takes the ownership of &\p Point.
378      void addInsertPoint(InsertPoint &Point);
379      /// @}
380  
381      /// \name Accessors related to the insertion points.
382      /// @{
383      insertpt_iterator begin() { return InsertPoints.begin(); }
384      insertpt_iterator end() { return InsertPoints.end(); }
385  
386      const_insertpt_iterator begin() const { return InsertPoints.begin(); }
387      const_insertpt_iterator end() const { return InsertPoints.end(); }
388  
389      unsigned getNumInsertPoints() const { return InsertPoints.size(); }
390      /// @}
391  
392      /// Change the type of this repairing placement to \p NewKind.
393      /// It is not possible to switch a repairing placement to the
394      /// RepairingKind::Insert. There is no fundamental problem with
395      /// that, but no uses as well, so do not support it for now.
396      ///
397      /// \pre NewKind != RepairingKind::Insert
398      /// \post getKind() == NewKind
399      void switchTo(RepairingKind NewKind) {
400        assert(NewKind != Kind && "Already of the right Kind");
401        Kind = NewKind;
402        InsertPoints.clear();
403        CanMaterialize = NewKind != RepairingKind::Impossible;
404        HasSplit = false;
405        assert(NewKind != RepairingKind::Insert &&
406               "We would need more MI to switch to Insert");
407      }
408    };
409  
410  protected:
411    /// Helper class used to represent the cost for mapping an instruction.
412    /// When mapping an instruction, we may introduce some repairing code.
413    /// In most cases, the repairing code is local to the instruction,
414    /// thus, we can omit the basic block frequency from the cost.
415    /// However, some alternatives may produce non-local cost, e.g., when
416    /// repairing a phi, and thus we then need to scale the local cost
417    /// to the non-local cost. This class does this for us.
418    /// \note: We could simply always scale the cost. The problem is that
419    /// there are higher chances that we saturate the cost easier and end
420    /// up having the same cost for actually different alternatives.
421    /// Another option would be to use APInt everywhere.
422    class MappingCost {
423    private:
424      /// Cost of the local instructions.
425      /// This cost is free of basic block frequency.
426      uint64_t LocalCost = 0;
427      /// Cost of the non-local instructions.
428      /// This cost should include the frequency of the related blocks.
429      uint64_t NonLocalCost = 0;
430      /// Frequency of the block where the local instructions live.
431      uint64_t LocalFreq;
432  
433      MappingCost(uint64_t LocalCost, uint64_t NonLocalCost, uint64_t LocalFreq)
434          : LocalCost(LocalCost), NonLocalCost(NonLocalCost),
435            LocalFreq(LocalFreq) {}
436  
437      /// Check if this cost is saturated.
438      bool isSaturated() const;
439  
440    public:
441      /// Create a MappingCost assuming that most of the instructions
442      /// will occur in a basic block with \p LocalFreq frequency.
443      MappingCost(BlockFrequency LocalFreq);
444  
445      /// Add \p Cost to the local cost.
446      /// \return true if this cost is saturated, false otherwise.
447      bool addLocalCost(uint64_t Cost);
448  
449      /// Add \p Cost to the non-local cost.
450      /// Non-local cost should reflect the frequency of their placement.
451      /// \return true if this cost is saturated, false otherwise.
452      bool addNonLocalCost(uint64_t Cost);
453  
454      /// Saturate the cost to the maximal representable value.
455      void saturate();
456  
457      /// Return an instance of MappingCost that represents an
458      /// impossible mapping.
459      static MappingCost ImpossibleCost();
460  
461      /// Check if this is less than \p Cost.
462      bool operator<(const MappingCost &Cost) const;
463      /// Check if this is equal to \p Cost.
464      bool operator==(const MappingCost &Cost) const;
465      /// Check if this is not equal to \p Cost.
466      bool operator!=(const MappingCost &Cost) const { return !(*this == Cost); }
467      /// Check if this is greater than \p Cost.
468      bool operator>(const MappingCost &Cost) const {
469        return *this != Cost && Cost < *this;
470      }
471  
472      /// Print this on dbgs() stream.
473      void dump() const;
474  
475      /// Print this on \p OS;
476      void print(raw_ostream &OS) const;
477  
478      /// Overload the stream operator for easy debug printing.
479      friend raw_ostream &operator<<(raw_ostream &OS, const MappingCost &Cost) {
480        Cost.print(OS);
481        return OS;
482      }
483    };
484  
485    /// Interface to the target lowering info related
486    /// to register banks.
487    const RegisterBankInfo *RBI = nullptr;
488  
489    /// MRI contains all the register class/bank information that this
490    /// pass uses and updates.
491    MachineRegisterInfo *MRI = nullptr;
492  
493    /// Information on the register classes for the current function.
494    const TargetRegisterInfo *TRI = nullptr;
495  
496    /// Get the frequency of blocks.
497    /// This is required for non-fast mode.
498    MachineBlockFrequencyInfo *MBFI = nullptr;
499  
500    /// Get the frequency of the edges.
501    /// This is required for non-fast mode.
502    MachineBranchProbabilityInfo *MBPI = nullptr;
503  
504    /// Current optimization remark emitter. Used to report failures.
505    std::unique_ptr<MachineOptimizationRemarkEmitter> MORE;
506  
507    /// Helper class used for every code morphing.
508    MachineIRBuilder MIRBuilder;
509  
510    /// Optimization mode of the pass.
511    Mode OptMode;
512  
513    /// Current target configuration. Controls how the pass handles errors.
514    const TargetPassConfig *TPC;
515  
516    /// Assign the register bank of each operand of \p MI.
517    /// \return True on success, false otherwise.
518    bool assignInstr(MachineInstr &MI);
519  
520    /// Initialize the field members using \p MF.
521    void init(MachineFunction &MF);
522  
523    /// Check if \p Reg is already assigned what is described by \p ValMapping.
524    /// \p OnlyAssign == true means that \p Reg just needs to be assigned a
525    /// register bank.  I.e., no repairing is necessary to have the
526    /// assignment match.
527    bool assignmentMatch(Register Reg,
528                         const RegisterBankInfo::ValueMapping &ValMapping,
529                         bool &OnlyAssign) const;
530  
531    /// Insert repairing code for \p Reg as specified by \p ValMapping.
532    /// The repairing placement is specified by \p RepairPt.
533    /// \p NewVRegs contains all the registers required to remap \p Reg.
534    /// In other words, the number of registers in NewVRegs must be equal
535    /// to ValMapping.BreakDown.size().
536    ///
537    /// The transformation could be sketched as:
538    /// \code
539    /// ... = op Reg
540    /// \endcode
541    /// Becomes
542    /// \code
543    /// <NewRegs> = COPY or extract Reg
544    /// ... = op Reg
545    /// \endcode
546    ///
547    /// and
548    /// \code
549    /// Reg = op ...
550    /// \endcode
551    /// Becomes
552    /// \code
553    /// Reg = op ...
554    /// Reg = COPY or build_sequence <NewRegs>
555    /// \endcode
556    ///
557    /// \pre NewVRegs.size() == ValMapping.BreakDown.size()
558    ///
559    /// \note The caller is supposed to do the rewriting of op if need be.
560    /// I.e., Reg = op ... => <NewRegs> = NewOp ...
561    ///
562    /// \return True if the repairing worked, false otherwise.
563    bool repairReg(MachineOperand &MO,
564                   const RegisterBankInfo::ValueMapping &ValMapping,
565                   RegBankSelect::RepairingPlacement &RepairPt,
566                   const iterator_range<SmallVectorImpl<Register>::const_iterator>
567                       &NewVRegs);
568  
569    /// Return the cost of the instruction needed to map \p MO to \p ValMapping.
570    /// The cost is free of basic block frequencies.
571    /// \pre MO.isReg()
572    /// \pre MO is assigned to a register bank.
573    /// \pre ValMapping is a valid mapping for MO.
574    uint64_t
575    getRepairCost(const MachineOperand &MO,
576                  const RegisterBankInfo::ValueMapping &ValMapping) const;
577  
578    /// Find the best mapping for \p MI from \p PossibleMappings.
579    /// \return a reference on the best mapping in \p PossibleMappings.
580    const RegisterBankInfo::InstructionMapping &
581    findBestMapping(MachineInstr &MI,
582                    RegisterBankInfo::InstructionMappings &PossibleMappings,
583                    SmallVectorImpl<RepairingPlacement> &RepairPts);
584  
585    /// Compute the cost of mapping \p MI with \p InstrMapping and
586    /// compute the repairing placement for such mapping in \p
587    /// RepairPts.
588    /// \p BestCost is used to specify when the cost becomes too high
589    /// and thus it is not worth computing the RepairPts.  Moreover if
590    /// \p BestCost == nullptr, the mapping cost is actually not
591    /// computed.
592    MappingCost
593    computeMapping(MachineInstr &MI,
594                   const RegisterBankInfo::InstructionMapping &InstrMapping,
595                   SmallVectorImpl<RepairingPlacement> &RepairPts,
596                   const MappingCost *BestCost = nullptr);
597  
598    /// When \p RepairPt involves splitting to repair \p MO for the
599    /// given \p ValMapping, try to change the way we repair such that
600    /// the splitting is not required anymore.
601    ///
602    /// \pre \p RepairPt.hasSplit()
603    /// \pre \p MO == MO.getParent()->getOperand(\p RepairPt.getOpIdx())
604    /// \pre \p ValMapping is the mapping of \p MO for MO.getParent()
605    ///      that implied \p RepairPt.
606    void tryAvoidingSplit(RegBankSelect::RepairingPlacement &RepairPt,
607                          const MachineOperand &MO,
608                          const RegisterBankInfo::ValueMapping &ValMapping) const;
609  
610    /// Apply \p Mapping to \p MI. \p RepairPts represents the different
611    /// mapping action that need to happen for the mapping to be
612    /// applied.
613    /// \return True if the mapping was applied sucessfully, false otherwise.
614    bool applyMapping(MachineInstr &MI,
615                      const RegisterBankInfo::InstructionMapping &InstrMapping,
616                      SmallVectorImpl<RepairingPlacement> &RepairPts);
617  
618  public:
619    /// Create a RegBankSelect pass with the specified \p RunningMode.
620    RegBankSelect(char &PassID = ID, Mode RunningMode = Fast);
621  
622    StringRef getPassName() const override { return "RegBankSelect"; }
623  
624    void getAnalysisUsage(AnalysisUsage &AU) const override;
625  
626    MachineFunctionProperties getRequiredProperties() const override {
627      return MachineFunctionProperties()
628          .set(MachineFunctionProperties::Property::IsSSA)
629          .set(MachineFunctionProperties::Property::Legalized);
630    }
631  
632    MachineFunctionProperties getSetProperties() const override {
633      return MachineFunctionProperties().set(
634          MachineFunctionProperties::Property::RegBankSelected);
635    }
636  
637    MachineFunctionProperties getClearedProperties() const override {
638      return MachineFunctionProperties()
639        .set(MachineFunctionProperties::Property::NoPHIs);
640    }
641  
642    /// Check that our input is fully legal: we require the function to have the
643    /// Legalized property, so it should be.
644    ///
645    /// FIXME: This should be in the MachineVerifier.
646    bool checkFunctionIsLegal(MachineFunction &MF) const;
647  
648    /// Walk through \p MF and assign a register bank to every virtual register
649    /// that are still mapped to nothing.
650    /// The target needs to provide a RegisterBankInfo and in particular
651    /// override RegisterBankInfo::getInstrMapping.
652    ///
653    /// Simplified algo:
654    /// \code
655    ///   RBI = MF.subtarget.getRegBankInfo()
656    ///   MIRBuilder.setMF(MF)
657    ///   for each bb in MF
658    ///     for each inst in bb
659    ///       MIRBuilder.setInstr(inst)
660    ///       MappingCosts = RBI.getMapping(inst);
661    ///       Idx = findIdxOfMinCost(MappingCosts)
662    ///       CurRegBank = MappingCosts[Idx].RegBank
663    ///       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
664    ///       for each argument in inst
665    ///         if (CurRegBank != argument.RegBank)
666    ///           ArgReg = argument.getReg()
667    ///           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
668    ///           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
669    ///           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
670    /// \endcode
671    bool assignRegisterBanks(MachineFunction &MF);
672  
673    bool runOnMachineFunction(MachineFunction &MF) override;
674  };
675  
676  } // end namespace llvm
677  
678  #endif // LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
679