[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / Target / Mips / MipsRegisterBankInfo.h
blobdf51606e1e8a92bec3bf81c712b6205eebd4e5b4
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 //===----------------------------------------------------------------------===//
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"
21 namespace llvm {
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 {
32 public:
33 MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
35 const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC,
36 LLT) const override;
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;
52 private:
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.
56 enum InstType {
57 /// Temporary type, when visit(..., nullptr) finishes will convert to one of
58 /// the remaining types: Integer, FloatingPoint or Ambiguous.
59 NotDetermined,
60 /// Connected with instruction that interprets 'bags of bits' as integers.
61 /// Select gprb to avoid cross bank copies.
62 Integer,
63 /// Connected with instruction that interprets 'bags of bits' as floating
64 /// point numbers. Select fprb to avoid cross bank copies.
65 FloatingPoint,
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.
69 Ambiguous,
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)
77 return true;
78 return false;
81 bool isAmbiguous_32(InstType InstTy, unsigned OpSize) const {
82 if (InstTy == InstType::Ambiguous && OpSize == 32)
83 return true;
84 return false;
87 bool isAmbiguous_32or64(InstType InstTy, unsigned OpSize) const {
88 if (InstTy == InstType::Ambiguous && (OpSize == 32 || OpSize == 64))
89 return true;
90 return false;
93 bool isAmbiguousWithMergeOrUnmerge_64(InstType InstTy,
94 unsigned OpSize) const {
95 if (InstTy == InstType::AmbiguousWithMergeOrUnmerge && OpSize == 64)
96 return true;
97 return false;
100 bool isFloatingPoint_32or64(InstType InstTy, unsigned OpSize) const {
101 if (InstTy == InstType::FloatingPoint && (OpSize == 32 || OpSize == 64))
102 return true;
103 return false;
106 bool isFloatingPoint_64(InstType InstTy, unsigned OpSize) const {
107 if (InstTy == InstType::FloatingPoint && OpSize == 64)
108 return true;
109 return false;
112 bool isInteger_32(InstType InstTy, unsigned OpSize) const {
113 if (InstTy == InstType::Integer && OpSize == 32)
114 return true;
115 return false;
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
134 /// %6 = COPY %5
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.
141 /// %2 = COPY %1
142 /// MI = %3 = COPY %2
143 MachineInstr *skipCopiesIncoming(MachineInstr *MI) const;
145 public:
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.
153 std::string MFName;
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>>
157 WaitingQueues;
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,
178 unsigned Op);
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);
216 public:
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) {
224 Types.erase(MI);
225 WaitingQueues.erase(MI);
229 } // end namespace llvm
230 #endif