1 //===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file declares the targeting of the RegisterBankInfo class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
14 #define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
16 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #define GET_REGBANK_DECLARATIONS
19 #include "MipsGenRegisterBank.inc"
23 class TargetRegisterInfo
;
25 class MipsGenRegisterBankInfo
: public RegisterBankInfo
{
26 #define GET_TARGET_REGBANK_CLASS
27 #include "MipsGenRegisterBank.inc"
30 /// This class provides the information for the target register banks.
31 class MipsRegisterBankInfo final
: public MipsGenRegisterBankInfo
{
33 MipsRegisterBankInfo(const TargetRegisterInfo
&TRI
);
35 const RegisterBank
&getRegBankFromRegClass(const TargetRegisterClass
&RC
,
38 const InstructionMapping
&
39 getInstrMapping(const MachineInstr
&MI
) const override
;
41 /// Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or
42 /// G_UNMERGE and erase instructions that became dead in the process. We
43 /// manually assign bank to def operand of all new instructions that were
44 /// created in the process since they will not end up in RegBankSelect loop.
45 void applyMappingImpl(const OperandsMapper
&OpdMapper
) const override
;
47 /// RegBankSelect determined that s64 operand is better to be split into two
48 /// s32 operands in gprb. Here we manually set register banks of def operands
49 /// of newly created instructions since they will not get regbankselected.
50 void setRegBank(MachineInstr
&MI
, MachineRegisterInfo
&MRI
) const;
53 /// Some instructions are used with both floating point and integer operands.
54 /// We assign InstType to such instructions as it helps us to avoid cross bank
55 /// copies. InstType deppends on context.
57 /// Temporary type, when visit(..., nullptr) finishes will convert to one of
58 /// the remaining types: Integer, FloatingPoint or Ambiguous.
60 /// Connected with instruction that interprets 'bags of bits' as integers.
61 /// Select gprb to avoid cross bank copies.
63 /// Connected with instruction that interprets 'bags of bits' as floating
64 /// point numbers. Select fprb to avoid cross bank copies.
66 /// Represents moving 'bags of bits' around. Select same bank for entire
67 /// chain to avoid cross bank copies. Currently we select fprb for s64 and
68 /// gprb for s32 Ambiguous operands.
70 /// Only used for s64. Unlike Ambiguous s64, AmbiguousWithMergeOrUnmerge s64
71 /// is mapped to gprb (legalized using narrow scalar to s32).
72 AmbiguousWithMergeOrUnmerge
75 bool isAmbiguous_64(InstType InstTy
, unsigned OpSize
) const {
76 if (InstTy
== InstType::Ambiguous
&& OpSize
== 64)
81 bool isAmbiguous_32(InstType InstTy
, unsigned OpSize
) const {
82 if (InstTy
== InstType::Ambiguous
&& OpSize
== 32)
87 bool isAmbiguous_32or64(InstType InstTy
, unsigned OpSize
) const {
88 if (InstTy
== InstType::Ambiguous
&& (OpSize
== 32 || OpSize
== 64))
93 bool isAmbiguousWithMergeOrUnmerge_64(InstType InstTy
,
94 unsigned OpSize
) const {
95 if (InstTy
== InstType::AmbiguousWithMergeOrUnmerge
&& OpSize
== 64)
100 bool isFloatingPoint_32or64(InstType InstTy
, unsigned OpSize
) const {
101 if (InstTy
== InstType::FloatingPoint
&& (OpSize
== 32 || OpSize
== 64))
106 bool isFloatingPoint_64(InstType InstTy
, unsigned OpSize
) const {
107 if (InstTy
== InstType::FloatingPoint
&& OpSize
== 64)
112 bool isInteger_32(InstType InstTy
, unsigned OpSize
) const {
113 if (InstTy
== InstType::Integer
&& OpSize
== 32)
118 /// Some generic instructions have operands that can be mapped to either fprb
119 /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
120 /// is always gprb since it is a pointer.
121 /// This class provides containers for MI's ambiguous:
122 /// DefUses : MachineInstrs that use one of MI's ambiguous def operands.
123 /// UseDefs : MachineInstrs that define MI's ambiguous use operands.
124 class AmbiguousRegDefUseContainer
{
125 SmallVector
<MachineInstr
*, 2> DefUses
;
126 SmallVector
<MachineInstr
*, 2> UseDefs
;
128 void addDefUses(Register Reg
, const MachineRegisterInfo
&MRI
);
129 void addUseDef(Register Reg
, const MachineRegisterInfo
&MRI
);
131 /// Skip copy instructions until we get to a non-copy instruction or to a
132 /// copy with phys register as def. Used during search for DefUses.
133 /// MI : %5 = COPY %4
135 /// $v0 = COPY %6 <- we want this one.
136 MachineInstr
*skipCopiesOutgoing(MachineInstr
*MI
) const;
138 /// Skip copy instructions until we get to a non-copy instruction or to a
139 /// copy with phys register as use. Used during search for UseDefs.
140 /// %1 = COPY $a1 <- we want this one.
142 /// MI = %3 = COPY %2
143 MachineInstr
*skipCopiesIncoming(MachineInstr
*MI
) const;
146 AmbiguousRegDefUseContainer(const MachineInstr
*MI
);
147 SmallVectorImpl
<MachineInstr
*> &getDefUses() { return DefUses
; }
148 SmallVectorImpl
<MachineInstr
*> &getUseDefs() { return UseDefs
; }
151 class TypeInfoForMF
{
152 /// MachineFunction name is used to recognise when MF changes.
154 /// <key, value> : value is vector of all MachineInstrs that are waiting for
155 /// key to figure out type of some of its ambiguous operands.
156 DenseMap
<const MachineInstr
*, SmallVector
<const MachineInstr
*, 2>>
158 /// Recorded InstTypes for visited instructions.
159 DenseMap
<const MachineInstr
*, InstType
> Types
;
161 /// Recursively visit MI's adjacent instructions and find MI's InstType.
162 bool visit(const MachineInstr
*MI
, const MachineInstr
*WaitingForTypeOfMI
,
163 InstType
&AmbiguousTy
);
165 /// Visit MI's adjacent UseDefs or DefUses.
166 bool visitAdjacentInstrs(const MachineInstr
*MI
,
167 SmallVectorImpl
<MachineInstr
*> &AdjacentInstrs
,
168 bool isDefUse
, InstType
&AmbiguousTy
);
170 /// Set type for MI, and recursively for all instructions that are
171 /// waiting for MI's type.
172 void setTypes(const MachineInstr
*MI
, InstType ITy
);
174 /// InstType for MI is determined, set it to InstType that corresponds to
175 /// physical regisiter that is operand number Op in CopyInst.
176 void setTypesAccordingToPhysicalRegister(const MachineInstr
*MI
,
177 const MachineInstr
*CopyInst
,
180 /// Set default values for MI in order to start visit.
181 void startVisit(const MachineInstr
*MI
) {
182 Types
.try_emplace(MI
, InstType::NotDetermined
);
183 WaitingQueues
.try_emplace(MI
);
186 /// Returns true if instruction was already visited. Type might not be
187 /// determined at this point but will be when visit(..., nullptr) finishes.
188 bool wasVisited(const MachineInstr
*MI
) const { return Types
.count(MI
); };
190 /// Returns recorded type for instruction.
191 const InstType
&getRecordedTypeForInstr(const MachineInstr
*MI
) const {
192 assert(wasVisited(MI
) && "Instruction was not visited!");
193 return Types
.find(MI
)->getSecond();
196 /// Change recorded type for instruction.
197 void changeRecordedTypeForInstr(const MachineInstr
*MI
, InstType InstTy
) {
198 assert(wasVisited(MI
) && "Instruction was not visited!");
199 Types
.find(MI
)->getSecond() = InstTy
;
202 /// Returns WaitingQueue for instruction.
203 const SmallVectorImpl
<const MachineInstr
*> &
204 getWaitingQueueFor(const MachineInstr
*MI
) const {
205 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
206 return WaitingQueues
.find(MI
)->getSecond();
209 /// Add WaitingForMI to MI's WaitingQueue.
210 void addToWaitingQueue(const MachineInstr
*MI
,
211 const MachineInstr
*WaitingForMI
) {
212 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
213 WaitingQueues
.find(MI
)->getSecond().push_back(WaitingForMI
);
217 InstType
determineInstType(const MachineInstr
*MI
);
219 void cleanupIfNewFunction(llvm::StringRef FunctionName
);
221 /// MI is about to get destroyed (using narrow scalar). Internal data is
222 /// saved based on MI's address, clear it since it is no longer valid.
223 void clearTypeInfoData(const MachineInstr
*MI
) {
225 WaitingQueues
.erase(MI
);
229 } // end namespace llvm