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/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(MachineIRBuilder
&Builder
,
46 const OperandsMapper
&OpdMapper
) const override
;
48 /// RegBankSelect determined that s64 operand is better to be split into two
49 /// s32 operands in gprb. Here we manually set register banks of def operands
50 /// of newly created instructions since they will not get regbankselected.
51 void setRegBank(MachineInstr
&MI
, MachineRegisterInfo
&MRI
) const;
54 /// Some instructions are used with both floating point and integer operands.
55 /// We assign InstType to such instructions as it helps us to avoid cross bank
56 /// copies. InstType deppends on context.
58 /// Temporary type, when visit(..., nullptr) finishes will convert to one of
59 /// the remaining types: Integer, FloatingPoint or Ambiguous.
61 /// Connected with instruction that interprets 'bags of bits' as integers.
62 /// Select gprb to avoid cross bank copies.
64 /// Connected with instruction that interprets 'bags of bits' as floating
65 /// point numbers. Select fprb to avoid cross bank copies.
67 /// Represents moving 'bags of bits' around. Select same bank for entire
68 /// chain to avoid cross bank copies. Currently we select fprb for s64 and
69 /// gprb for s32 Ambiguous operands.
71 /// Only used for s64. Unlike Ambiguous s64, AmbiguousWithMergeOrUnmerge s64
72 /// is mapped to gprb (legalized using narrow scalar to s32).
73 AmbiguousWithMergeOrUnmerge
76 bool isAmbiguous_64(InstType InstTy
, unsigned OpSize
) const {
77 if (InstTy
== InstType::Ambiguous
&& OpSize
== 64)
82 bool isAmbiguous_32(InstType InstTy
, unsigned OpSize
) const {
83 if (InstTy
== InstType::Ambiguous
&& OpSize
== 32)
88 bool isAmbiguous_32or64(InstType InstTy
, unsigned OpSize
) const {
89 if (InstTy
== InstType::Ambiguous
&& (OpSize
== 32 || OpSize
== 64))
94 bool isAmbiguousWithMergeOrUnmerge_64(InstType InstTy
,
95 unsigned OpSize
) const {
96 if (InstTy
== InstType::AmbiguousWithMergeOrUnmerge
&& OpSize
== 64)
101 bool isFloatingPoint_32or64(InstType InstTy
, unsigned OpSize
) const {
102 if (InstTy
== InstType::FloatingPoint
&& (OpSize
== 32 || OpSize
== 64))
107 bool isFloatingPoint_64(InstType InstTy
, unsigned OpSize
) const {
108 if (InstTy
== InstType::FloatingPoint
&& OpSize
== 64)
113 bool isInteger_32(InstType InstTy
, unsigned OpSize
) const {
114 if (InstTy
== InstType::Integer
&& OpSize
== 32)
119 /// Some generic instructions have operands that can be mapped to either fprb
120 /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
121 /// is always gprb since it is a pointer.
122 /// This class provides containers for MI's ambiguous:
123 /// DefUses : MachineInstrs that use one of MI's ambiguous def operands.
124 /// UseDefs : MachineInstrs that define MI's ambiguous use operands.
125 class AmbiguousRegDefUseContainer
{
126 SmallVector
<MachineInstr
*, 2> DefUses
;
127 SmallVector
<MachineInstr
*, 2> UseDefs
;
129 void addDefUses(Register Reg
, const MachineRegisterInfo
&MRI
);
130 void addUseDef(Register Reg
, const MachineRegisterInfo
&MRI
);
132 /// Skip copy instructions until we get to a non-copy instruction or to a
133 /// copy with phys register as def. Used during search for DefUses.
134 /// MI : %5 = COPY %4
136 /// $v0 = COPY %6 <- we want this one.
137 MachineInstr
*skipCopiesOutgoing(MachineInstr
*MI
) const;
139 /// Skip copy instructions until we get to a non-copy instruction or to a
140 /// copy with phys register as use. Used during search for UseDefs.
141 /// %1 = COPY $a1 <- we want this one.
143 /// MI = %3 = COPY %2
144 MachineInstr
*skipCopiesIncoming(MachineInstr
*MI
) const;
147 AmbiguousRegDefUseContainer(const MachineInstr
*MI
);
148 SmallVectorImpl
<MachineInstr
*> &getDefUses() { return DefUses
; }
149 SmallVectorImpl
<MachineInstr
*> &getUseDefs() { return UseDefs
; }
152 class TypeInfoForMF
{
153 /// MachineFunction name is used to recognise when MF changes.
155 /// <key, value> : value is vector of all MachineInstrs that are waiting for
156 /// key to figure out type of some of its ambiguous operands.
157 DenseMap
<const MachineInstr
*, SmallVector
<const MachineInstr
*, 2>>
159 /// Recorded InstTypes for visited instructions.
160 DenseMap
<const MachineInstr
*, InstType
> Types
;
162 /// Recursively visit MI's adjacent instructions and find MI's InstType.
163 bool visit(const MachineInstr
*MI
, const MachineInstr
*WaitingForTypeOfMI
,
164 InstType
&AmbiguousTy
);
166 /// Visit MI's adjacent UseDefs or DefUses.
167 bool visitAdjacentInstrs(const MachineInstr
*MI
,
168 SmallVectorImpl
<MachineInstr
*> &AdjacentInstrs
,
169 bool isDefUse
, InstType
&AmbiguousTy
);
171 /// Set type for MI, and recursively for all instructions that are
172 /// waiting for MI's type.
173 void setTypes(const MachineInstr
*MI
, InstType ITy
);
175 /// InstType for MI is determined, set it to InstType that corresponds to
176 /// physical regisiter that is operand number Op in CopyInst.
177 void setTypesAccordingToPhysicalRegister(const MachineInstr
*MI
,
178 const MachineInstr
*CopyInst
,
181 /// Set default values for MI in order to start visit.
182 void startVisit(const MachineInstr
*MI
) {
183 Types
.try_emplace(MI
, InstType::NotDetermined
);
184 WaitingQueues
.try_emplace(MI
);
187 /// Returns true if instruction was already visited. Type might not be
188 /// determined at this point but will be when visit(..., nullptr) finishes.
189 bool wasVisited(const MachineInstr
*MI
) const { return Types
.count(MI
); };
191 /// Returns recorded type for instruction.
192 const InstType
&getRecordedTypeForInstr(const MachineInstr
*MI
) const {
193 assert(wasVisited(MI
) && "Instruction was not visited!");
194 return Types
.find(MI
)->getSecond();
197 /// Change recorded type for instruction.
198 void changeRecordedTypeForInstr(const MachineInstr
*MI
, InstType InstTy
) {
199 assert(wasVisited(MI
) && "Instruction was not visited!");
200 Types
.find(MI
)->getSecond() = InstTy
;
203 /// Returns WaitingQueue for instruction.
204 const SmallVectorImpl
<const MachineInstr
*> &
205 getWaitingQueueFor(const MachineInstr
*MI
) const {
206 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
207 return WaitingQueues
.find(MI
)->getSecond();
210 /// Add WaitingForMI to MI's WaitingQueue.
211 void addToWaitingQueue(const MachineInstr
*MI
,
212 const MachineInstr
*WaitingForMI
) {
213 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
214 WaitingQueues
.find(MI
)->getSecond().push_back(WaitingForMI
);
218 InstType
determineInstType(const MachineInstr
*MI
);
220 void cleanupIfNewFunction(llvm::StringRef FunctionName
);
222 /// MI is about to get destroyed (using narrow scalar). Internal data is
223 /// saved based on MI's address, clear it since it is no longer valid.
224 void clearTypeInfoData(const MachineInstr
*MI
) {
226 WaitingQueues
.erase(MI
);
230 } // end namespace llvm