1 //===- MipsRegisterBankInfo.h -----------------------------------*- 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 /// \file
9 /// This file declares the targeting of the RegisterBankInfo class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
14 #define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
15 
16 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
17 
18 #define GET_REGBANK_DECLARATIONS
19 #include "MipsGenRegisterBank.inc"
20 
21 namespace llvm {
22 
23 class TargetRegisterInfo;
24 
25 class MipsGenRegisterBankInfo : public RegisterBankInfo {
26 #define GET_TARGET_REGBANK_CLASS
27 #include "MipsGenRegisterBank.inc"
28 };
29 
30 /// This class provides the information for the target register banks.
31 class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo {
32 public:
33   MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
34 
35   const RegisterBank &
36   getRegBankFromRegClass(const TargetRegisterClass &RC) const override;
37 
38   const InstructionMapping &
39   getInstrMapping(const MachineInstr &MI) const override;
40 
41   void applyMappingImpl(const OperandsMapper &OpdMapper) const override;
42 
43 private:
44   /// Some instructions are used with both floating point and integer operands.
45   /// We assign InstType to such instructions as it helps us to avoid cross bank
46   /// copies. InstType deppends on context.
47   enum InstType {
48     /// Temporary type, when visit(..., nullptr) finishes will convert to one of
49     /// the remaining types: Integer, FloatingPoint or Ambiguous.
50     NotDetermined,
51     /// Connected with instruction that interprets 'bags of bits' as integers.
52     /// Select gprb to avoid cross bank copies.
53     Integer,
54     /// Connected with instruction that interprets 'bags of bits' as floating
55     /// point numbers. Select fprb to avoid cross bank copies.
56     FloatingPoint,
57     /// Represents moving 'bags of bits' around. Select same bank for entire
58     /// chain to avoid cross bank copies. Currently we select fprb for s64 and
59     /// gprb for s32 Ambiguous operands.
60     Ambiguous
61   };
62 
63   /// Some generic instructions have operands that can be mapped to either fprb
64   /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
65   /// is always gprb since it is a pointer.
66   /// This class provides containers for MI's ambiguous:
67   /// DefUses : MachineInstrs that use one of MI's ambiguous def operands.
68   /// UseDefs : MachineInstrs that define MI's ambiguous use operands.
69   class AmbiguousRegDefUseContainer {
70     SmallVector<MachineInstr *, 2> DefUses;
71     SmallVector<MachineInstr *, 2> UseDefs;
72 
73     void addDefUses(Register Reg, const MachineRegisterInfo &MRI);
74     void addUseDef(Register Reg, const MachineRegisterInfo &MRI);
75 
76     /// Skip copy instructions until we get to a non-copy instruction or to a
77     /// copy with phys register as def. Used during search for DefUses.
78     /// MI :  %5 = COPY %4
79     ///       %6 = COPY %5
80     ///       $v0 = COPY %6 <- we want this one.
81     MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const;
82 
83     /// Skip copy instructions until we get to a non-copy instruction or to a
84     /// copy with phys register as use. Used during search for UseDefs.
85     ///       %1 = COPY $a1 <- we want this one.
86     ///       %2 = COPY %1
87     /// MI =  %3 = COPY %2
88     MachineInstr *skipCopiesIncoming(MachineInstr *MI) const;
89 
90   public:
91     AmbiguousRegDefUseContainer(const MachineInstr *MI);
92     SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; }
93     SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; }
94   };
95 
96   class TypeInfoForMF {
97     /// MachineFunction name is used to recognise when MF changes.
98     std::string MFName = "";
99     /// <key, value> : value is vector of all MachineInstrs that are waiting for
100     /// key to figure out type of some of its ambiguous operands.
101     DenseMap<const MachineInstr *, SmallVector<const MachineInstr *, 2>>
102         WaitingQueues;
103     /// Recorded InstTypes for visited instructions.
104     DenseMap<const MachineInstr *, InstType> Types;
105 
106     /// Recursively visit MI's adjacent instructions and find MI's InstType.
107     bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI);
108 
109     /// Visit MI's adjacent UseDefs or DefUses.
110     bool visitAdjacentInstrs(const MachineInstr *MI,
111                              SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
112                              bool isDefUse);
113 
114     /// Set type for MI, and recursively for all instructions that are
115     /// waiting for MI's type.
116     void setTypes(const MachineInstr *MI, InstType ITy);
117 
118     /// InstType for MI is determined, set it to InstType that corresponds to
119     /// physical regisiter that is operand number Op in CopyInst.
120     void setTypesAccordingToPhysicalRegister(const MachineInstr *MI,
121                                              const MachineInstr *CopyInst,
122                                              unsigned Op);
123 
124     /// Set default values for MI in order to start visit.
125     void startVisit(const MachineInstr *MI) {
126       Types.try_emplace(MI, InstType::NotDetermined);
127       WaitingQueues.try_emplace(MI);
128     }
129 
130     /// Returns true if instruction was already visited. Type might not be
131     /// determined at this point but will be when visit(..., nullptr) finishes.
132     bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); };
133 
134     /// Returns recorded type for instruction.
135     const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const {
136       assert(wasVisited(MI) && "Instruction was not visited!");
137       return Types.find(MI)->getSecond();
138     };
139 
140     /// Change recorded type for instruction.
141     void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) {
142       assert(wasVisited(MI) && "Instruction was not visited!");
143       Types.find(MI)->getSecond() = InstTy;
144     };
145 
146     /// Returns WaitingQueue for instruction.
147     const SmallVectorImpl<const MachineInstr *> &
148     getWaitingQueueFor(const MachineInstr *MI) const {
149       assert(WaitingQueues.count(MI) && "Instruction was not visited!");
150       return WaitingQueues.find(MI)->getSecond();
151     };
152 
153     /// Add WaitingForMI to MI's WaitingQueue.
154     void addToWaitingQueue(const MachineInstr *MI,
155                            const MachineInstr *WaitingForMI) {
156       assert(WaitingQueues.count(MI) && "Instruction was not visited!");
157       WaitingQueues.find(MI)->getSecond().push_back(WaitingForMI);
158     };
159 
160   public:
161     InstType determineInstType(const MachineInstr *MI);
162 
163     void cleanupIfNewFunction(llvm::StringRef FunctionName);
164   };
165 };
166 } // end namespace llvm
167 #endif
168