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