1fac93e28SPetar Jovanovic //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
2fac93e28SPetar Jovanovic //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fac93e28SPetar Jovanovic //
7fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
8fac93e28SPetar Jovanovic /// \file
9fac93e28SPetar Jovanovic /// This file implements the targeting of the RegisterBankInfo class for Mips.
10fac93e28SPetar Jovanovic /// \todo This should be generated by TableGen.
11fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
12fac93e28SPetar Jovanovic 
13fac93e28SPetar Jovanovic #include "MipsRegisterBankInfo.h"
14ec575f6eSPetar Avramovic #include "MipsInstrInfo.h"
15ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
16ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
17ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18fac93e28SPetar Jovanovic #include "llvm/CodeGen/MachineRegisterInfo.h"
19fac93e28SPetar Jovanovic 
20366857a2SPetar Jovanovic #define GET_TARGET_REGBANK_IMPL
21fac93e28SPetar Jovanovic 
22366857a2SPetar Jovanovic #include "MipsGenRegisterBank.inc"
23366857a2SPetar Jovanovic 
24366857a2SPetar Jovanovic namespace llvm {
25366857a2SPetar Jovanovic namespace Mips {
26366857a2SPetar Jovanovic enum PartialMappingIdx {
27366857a2SPetar Jovanovic   PMI_GPR,
281af05df3SPetar Avramovic   PMI_SPR,
291af05df3SPetar Avramovic   PMI_DPR,
30366857a2SPetar Jovanovic   PMI_Min = PMI_GPR,
31366857a2SPetar Jovanovic };
32366857a2SPetar Jovanovic 
33366857a2SPetar Jovanovic RegisterBankInfo::PartialMapping PartMappings[]{
341af05df3SPetar Avramovic     {0, 32, GPRBRegBank},
351af05df3SPetar Avramovic     {0, 32, FPRBRegBank},
361af05df3SPetar Avramovic     {0, 64, FPRBRegBank}
37366857a2SPetar Jovanovic };
38366857a2SPetar Jovanovic 
391af05df3SPetar Avramovic enum ValueMappingIdx {
401af05df3SPetar Avramovic     InvalidIdx = 0,
411af05df3SPetar Avramovic     GPRIdx = 1,
421af05df3SPetar Avramovic     SPRIdx = 4,
431af05df3SPetar Avramovic     DPRIdx = 7
441af05df3SPetar Avramovic };
45366857a2SPetar Jovanovic 
46366857a2SPetar Jovanovic RegisterBankInfo::ValueMapping ValueMappings[] = {
47366857a2SPetar Jovanovic     // invalid
48366857a2SPetar Jovanovic     {nullptr, 0},
491af05df3SPetar Avramovic     // up to 3 operands in GPRs
50366857a2SPetar Jovanovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
51366857a2SPetar Jovanovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
521af05df3SPetar Avramovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
531af05df3SPetar Avramovic     // up to 3 ops operands FPRs - single precission
541af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
551af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
561af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
571af05df3SPetar Avramovic     // up to 3 ops operands FPRs - double precission
581af05df3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1},
591af05df3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1},
601af05df3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1}
611af05df3SPetar Avramovic };
62366857a2SPetar Jovanovic 
63366857a2SPetar Jovanovic } // end namespace Mips
64366857a2SPetar Jovanovic } // end namespace llvm
65366857a2SPetar Jovanovic 
66366857a2SPetar Jovanovic using namespace llvm;
67fac93e28SPetar Jovanovic 
68fac93e28SPetar Jovanovic MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
69fac93e28SPetar Jovanovic     : MipsGenRegisterBankInfo() {}
70366857a2SPetar Jovanovic 
71366857a2SPetar Jovanovic const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
72366857a2SPetar Jovanovic     const TargetRegisterClass &RC) const {
73366857a2SPetar Jovanovic   using namespace Mips;
74366857a2SPetar Jovanovic 
75366857a2SPetar Jovanovic   switch (RC.getID()) {
76366857a2SPetar Jovanovic   case Mips::GPR32RegClassID:
77366857a2SPetar Jovanovic   case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
78852dd83bSSimon Atanasyan   case Mips::GPRMM16MovePPairFirstRegClassID:
79852dd83bSSimon Atanasyan   case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
80366857a2SPetar Jovanovic   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
81852dd83bSSimon Atanasyan   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
82021e4c82SPetar Jovanovic   case Mips::SP32RegClassID:
83efcd3c00SPetar Avramovic   case Mips::GP32RegClassID:
84366857a2SPetar Jovanovic     return getRegBank(Mips::GPRBRegBankID);
853dfa368dSPetar Avramovic   case Mips::FGRCCRegClassID:
86afa3afa3SPetar Avramovic   case Mips::FGR32RegClassID:
873dfa368dSPetar Avramovic   case Mips::FGR64RegClassID:
883dfa368dSPetar Avramovic   case Mips::AFGR64RegClassID:
893dfa368dSPetar Avramovic     return getRegBank(Mips::FPRBRegBankID);
90366857a2SPetar Jovanovic   default:
91366857a2SPetar Jovanovic     llvm_unreachable("Register class not supported");
92366857a2SPetar Jovanovic   }
93366857a2SPetar Jovanovic }
94366857a2SPetar Jovanovic 
95ec575f6eSPetar Avramovic // Instructions where all register operands are floating point.
96ec575f6eSPetar Avramovic static bool isFloatingPointOpcode(unsigned Opc) {
97ec575f6eSPetar Avramovic   switch (Opc) {
98ec575f6eSPetar Avramovic   case TargetOpcode::G_FCONSTANT:
99ec575f6eSPetar Avramovic   case TargetOpcode::G_FADD:
100ec575f6eSPetar Avramovic   case TargetOpcode::G_FSUB:
101ec575f6eSPetar Avramovic   case TargetOpcode::G_FMUL:
102ec575f6eSPetar Avramovic   case TargetOpcode::G_FDIV:
103ec575f6eSPetar Avramovic   case TargetOpcode::G_FABS:
104ec575f6eSPetar Avramovic   case TargetOpcode::G_FSQRT:
105ec575f6eSPetar Avramovic   case TargetOpcode::G_FCEIL:
106ec575f6eSPetar Avramovic   case TargetOpcode::G_FFLOOR:
107ec575f6eSPetar Avramovic   case TargetOpcode::G_FPEXT:
108ec575f6eSPetar Avramovic   case TargetOpcode::G_FPTRUNC:
109ec575f6eSPetar Avramovic     return true;
110ec575f6eSPetar Avramovic   default:
111ec575f6eSPetar Avramovic     return false;
112ec575f6eSPetar Avramovic   }
113ec575f6eSPetar Avramovic }
114ec575f6eSPetar Avramovic 
115aa699b20SPetar Avramovic // Instructions where use operands are floating point registers.
116aa699b20SPetar Avramovic // Def operands are general purpose.
117aa699b20SPetar Avramovic static bool isFloatingPointOpcodeUse(unsigned Opc) {
118aa699b20SPetar Avramovic   switch (Opc) {
119aa699b20SPetar Avramovic   case TargetOpcode::G_FPTOSI:
120aa699b20SPetar Avramovic   case TargetOpcode::G_FPTOUI:
121aa699b20SPetar Avramovic   case TargetOpcode::G_FCMP:
122aa699b20SPetar Avramovic   case Mips::MFC1:
123aa699b20SPetar Avramovic   case Mips::ExtractElementF64:
124aa699b20SPetar Avramovic   case Mips::ExtractElementF64_64:
125aa699b20SPetar Avramovic     return true;
126aa699b20SPetar Avramovic   default:
127aa699b20SPetar Avramovic     return isFloatingPointOpcode(Opc);
128aa699b20SPetar Avramovic   }
129aa699b20SPetar Avramovic }
130aa699b20SPetar Avramovic 
131ec575f6eSPetar Avramovic // Instructions where def operands are floating point registers.
132ec575f6eSPetar Avramovic // Use operands are general purpose.
133ec575f6eSPetar Avramovic static bool isFloatingPointOpcodeDef(unsigned Opc) {
134ec575f6eSPetar Avramovic   switch (Opc) {
135ec575f6eSPetar Avramovic   case TargetOpcode::G_SITOFP:
136ec575f6eSPetar Avramovic   case TargetOpcode::G_UITOFP:
137ec575f6eSPetar Avramovic   case Mips::MTC1:
138ec575f6eSPetar Avramovic   case Mips::BuildPairF64:
139ec575f6eSPetar Avramovic   case Mips::BuildPairF64_64:
140ec575f6eSPetar Avramovic     return true;
141ec575f6eSPetar Avramovic   default:
142ec575f6eSPetar Avramovic     return isFloatingPointOpcode(Opc);
143ec575f6eSPetar Avramovic   }
144ec575f6eSPetar Avramovic }
145ec575f6eSPetar Avramovic 
146ec575f6eSPetar Avramovic static bool isAmbiguous(unsigned Opc) {
147ec575f6eSPetar Avramovic   switch (Opc) {
148ec575f6eSPetar Avramovic   case TargetOpcode::G_LOAD:
149ec575f6eSPetar Avramovic   case TargetOpcode::G_STORE:
150ec575f6eSPetar Avramovic   case TargetOpcode::G_PHI:
151ec575f6eSPetar Avramovic   case TargetOpcode::G_SELECT:
15275e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF:
153ec575f6eSPetar Avramovic     return true;
154ec575f6eSPetar Avramovic   default:
155ec575f6eSPetar Avramovic     return false;
156ec575f6eSPetar Avramovic   }
157ec575f6eSPetar Avramovic }
158ec575f6eSPetar Avramovic 
159aa699b20SPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
160aa699b20SPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
161aa699b20SPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
162aa699b20SPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
163aa699b20SPetar Avramovic   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
16496252407SPetar Avramovic     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
16596252407SPetar Avramovic     // Copy with many uses.
16696252407SPetar Avramovic     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
1672bea69bfSDaniel Sanders         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
16896252407SPetar Avramovic       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
16996252407SPetar Avramovic     else
17096252407SPetar Avramovic       DefUses.push_back(skipCopiesOutgoing(&UseMI));
171aa699b20SPetar Avramovic   }
172aa699b20SPetar Avramovic }
173aa699b20SPetar Avramovic 
174ec575f6eSPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
175ec575f6eSPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
176ec575f6eSPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
177ec575f6eSPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
178ec575f6eSPetar Avramovic   MachineInstr *DefMI = MRI.getVRegDef(Reg);
17996252407SPetar Avramovic   UseDefs.push_back(skipCopiesIncoming(DefMI));
18096252407SPetar Avramovic }
181ec575f6eSPetar Avramovic 
18296252407SPetar Avramovic MachineInstr *
18396252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
18496252407SPetar Avramovic     MachineInstr *MI) const {
18596252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
18696252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
18796252407SPetar Avramovic   MachineInstr *Ret = MI;
18896252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
1892bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
19096252407SPetar Avramovic          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
19196252407SPetar Avramovic     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
19296252407SPetar Avramovic   }
19396252407SPetar Avramovic   return Ret;
19496252407SPetar Avramovic }
19596252407SPetar Avramovic 
19696252407SPetar Avramovic MachineInstr *
19796252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
19896252407SPetar Avramovic     MachineInstr *MI) const {
19996252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
20096252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
20196252407SPetar Avramovic   MachineInstr *Ret = MI;
20296252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
2032bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
20496252407SPetar Avramovic     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
20596252407SPetar Avramovic   return Ret;
206ec575f6eSPetar Avramovic }
207ec575f6eSPetar Avramovic 
208ec575f6eSPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
209ec575f6eSPetar Avramovic     const MachineInstr *MI) {
210ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) &&
211ec575f6eSPetar Avramovic          "Not implemented for non Ambiguous opcode.\n");
212ec575f6eSPetar Avramovic 
213ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
214ec575f6eSPetar Avramovic 
215aa699b20SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_LOAD)
216aa699b20SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
217aa699b20SPetar Avramovic 
218ec575f6eSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_STORE)
219ec575f6eSPetar Avramovic     addUseDef(MI->getOperand(0).getReg(), MRI);
220dbb6d01dSPetar Avramovic 
221be20e361SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_PHI) {
222be20e361SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
223be20e361SPetar Avramovic 
224be20e361SPetar Avramovic     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
225be20e361SPetar Avramovic       addUseDef(MI->getOperand(i).getReg(), MRI);
226be20e361SPetar Avramovic   }
227be20e361SPetar Avramovic 
228dbb6d01dSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
229dbb6d01dSPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
230dbb6d01dSPetar Avramovic 
231dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(2).getReg(), MRI);
232dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(3).getReg(), MRI);
233dbb6d01dSPetar Avramovic   }
23475e43a60SPetar Avramovic 
23575e43a60SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
23675e43a60SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
237ec575f6eSPetar Avramovic }
238ec575f6eSPetar Avramovic 
239e3bb0a72SPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visit(
240e3bb0a72SPetar Avramovic     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
241ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
242e3bb0a72SPetar Avramovic   if (wasVisited(MI))
243e3bb0a72SPetar Avramovic     return true; // InstType has already been determined for MI.
244ec575f6eSPetar Avramovic 
245ec575f6eSPetar Avramovic   startVisit(MI);
246ec575f6eSPetar Avramovic   AmbiguousRegDefUseContainer DefUseContainer(MI);
247ec575f6eSPetar Avramovic 
248aa699b20SPetar Avramovic   // Visit instructions where MI's DEF operands are USED.
249aa699b20SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
250aa699b20SPetar Avramovic     return true;
251aa699b20SPetar Avramovic 
252ec575f6eSPetar Avramovic   // Visit instructions that DEFINE MI's USE operands.
253aa699b20SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
254ec575f6eSPetar Avramovic     return true;
255ec575f6eSPetar Avramovic 
256e3bb0a72SPetar Avramovic   // All MI's adjacent instructions, are ambiguous.
257e3bb0a72SPetar Avramovic   if (!WaitingForTypeOfMI) {
258e3bb0a72SPetar Avramovic     // This is chain of ambiguous instructions.
259e3bb0a72SPetar Avramovic     setTypes(MI, InstType::Ambiguous);
260e3bb0a72SPetar Avramovic     return true;
261e3bb0a72SPetar Avramovic   }
262e3bb0a72SPetar Avramovic   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
263e3bb0a72SPetar Avramovic   // instructions or has no other adjacent instructions. Anyway InstType could
264e3bb0a72SPetar Avramovic   // not be determined. There could be unexplored path from some of
265e3bb0a72SPetar Avramovic   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
266e3bb0a72SPetar Avramovic   // mapping available.
267e3bb0a72SPetar Avramovic   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
268e3bb0a72SPetar Avramovic   // this way when WaitingForTypeOfMI figures out its InstType same InstType
269e3bb0a72SPetar Avramovic   // will be assigned to all instructions in this branch.
270e3bb0a72SPetar Avramovic   addToWaitingQueue(WaitingForTypeOfMI, MI);
271ec575f6eSPetar Avramovic   return false;
272ec575f6eSPetar Avramovic }
273ec575f6eSPetar Avramovic 
274ec575f6eSPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
275aa699b20SPetar Avramovic     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
276aa699b20SPetar Avramovic     bool isDefUse) {
277ec575f6eSPetar Avramovic   while (!AdjacentInstrs.empty()) {
278ec575f6eSPetar Avramovic     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
279ec575f6eSPetar Avramovic 
280aa699b20SPetar Avramovic     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
281aa699b20SPetar Avramovic                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
282ec575f6eSPetar Avramovic       setTypes(MI, InstType::FloatingPoint);
283ec575f6eSPetar Avramovic       return true;
284ec575f6eSPetar Avramovic     }
285ec575f6eSPetar Avramovic 
286ec575f6eSPetar Avramovic     // Determine InstType from register bank of phys register that is
287aa699b20SPetar Avramovic     // 'isDefUse ? def : use' of this copy.
288ec575f6eSPetar Avramovic     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
289aa699b20SPetar Avramovic       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
290ec575f6eSPetar Avramovic       return true;
291ec575f6eSPetar Avramovic     }
292ec575f6eSPetar Avramovic 
293ec575f6eSPetar Avramovic     // Defaults to integer instruction. Includes G_MERGE_VALUES and
294ec575f6eSPetar Avramovic     // G_UNMERGE_VALUES.
295e3bb0a72SPetar Avramovic     if (!isAmbiguous(AdjMI->getOpcode())) {
296ec575f6eSPetar Avramovic       setTypes(MI, InstType::Integer);
297ec575f6eSPetar Avramovic       return true;
298ec575f6eSPetar Avramovic     }
299e3bb0a72SPetar Avramovic 
300e3bb0a72SPetar Avramovic     // When AdjMI was visited first, MI has to continue to explore remaining
301e3bb0a72SPetar Avramovic     // adjacent instructions and determine InstType without visiting AdjMI.
302e3bb0a72SPetar Avramovic     if (!wasVisited(AdjMI) ||
303e3bb0a72SPetar Avramovic         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
304e3bb0a72SPetar Avramovic       if (visit(AdjMI, MI)) {
305e3bb0a72SPetar Avramovic         // InstType is successfully determined and is same as for AdjMI.
306e3bb0a72SPetar Avramovic         setTypes(MI, getRecordedTypeForInstr(AdjMI));
307e3bb0a72SPetar Avramovic         return true;
308e3bb0a72SPetar Avramovic       }
309e3bb0a72SPetar Avramovic     }
310e3bb0a72SPetar Avramovic   }
311ec575f6eSPetar Avramovic   return false;
312ec575f6eSPetar Avramovic }
313ec575f6eSPetar Avramovic 
314ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
315ec575f6eSPetar Avramovic                                                    InstType InstTy) {
316ec575f6eSPetar Avramovic   changeRecordedTypeForInstr(MI, InstTy);
317e3bb0a72SPetar Avramovic   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
318e3bb0a72SPetar Avramovic     setTypes(WaitingInstr, InstTy);
319e3bb0a72SPetar Avramovic   }
320ec575f6eSPetar Avramovic }
321ec575f6eSPetar Avramovic 
322ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
323ec575f6eSPetar Avramovic     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
3242bea69bfSDaniel Sanders   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
325ec575f6eSPetar Avramovic          "Copies of non physical registers should not be considered here.\n");
326ec575f6eSPetar Avramovic 
327ec575f6eSPetar Avramovic   const MachineFunction &MF = *CopyInst->getMF();
328ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
329ec575f6eSPetar Avramovic   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
330ec575f6eSPetar Avramovic   const RegisterBankInfo &RBI =
331ec575f6eSPetar Avramovic       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
332ec575f6eSPetar Avramovic   const RegisterBank *Bank =
333ec575f6eSPetar Avramovic       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
334ec575f6eSPetar Avramovic 
335ec575f6eSPetar Avramovic   if (Bank == &Mips::FPRBRegBank)
336ec575f6eSPetar Avramovic     setTypes(MI, InstType::FloatingPoint);
337ec575f6eSPetar Avramovic   else if (Bank == &Mips::GPRBRegBank)
338ec575f6eSPetar Avramovic     setTypes(MI, InstType::Integer);
339ec575f6eSPetar Avramovic   else
340ec575f6eSPetar Avramovic     llvm_unreachable("Unsupported register bank.\n");
341ec575f6eSPetar Avramovic }
342ec575f6eSPetar Avramovic 
343ec575f6eSPetar Avramovic MipsRegisterBankInfo::InstType
344ec575f6eSPetar Avramovic MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
345e3bb0a72SPetar Avramovic   visit(MI, nullptr);
346ec575f6eSPetar Avramovic   return getRecordedTypeForInstr(MI);
347ec575f6eSPetar Avramovic }
348ec575f6eSPetar Avramovic 
349ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
350ec575f6eSPetar Avramovic     llvm::StringRef FunctionName) {
351ec575f6eSPetar Avramovic   if (MFName != FunctionName) {
352ec575f6eSPetar Avramovic     MFName = FunctionName;
353e3bb0a72SPetar Avramovic     WaitingQueues.clear();
354ec575f6eSPetar Avramovic     Types.clear();
355ec575f6eSPetar Avramovic   }
356ec575f6eSPetar Avramovic }
357ec575f6eSPetar Avramovic 
358366857a2SPetar Jovanovic const RegisterBankInfo::InstructionMapping &
359366857a2SPetar Jovanovic MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
360366857a2SPetar Jovanovic 
361ec575f6eSPetar Avramovic   static TypeInfoForMF TI;
362ec575f6eSPetar Avramovic 
363ec575f6eSPetar Avramovic   // Reset TI internal data when MF changes.
364ec575f6eSPetar Avramovic   TI.cleanupIfNewFunction(MI.getMF()->getName());
365ec575f6eSPetar Avramovic 
366366857a2SPetar Jovanovic   unsigned Opc = MI.getOpcode();
3671af05df3SPetar Avramovic   const MachineFunction &MF = *MI.getParent()->getParent();
3681af05df3SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
369366857a2SPetar Jovanovic 
370be20e361SPetar Avramovic   if (MI.getOpcode() != TargetOpcode::G_PHI) {
371be20e361SPetar Avramovic     const RegisterBankInfo::InstructionMapping &Mapping =
372be20e361SPetar Avramovic         getInstrMappingImpl(MI);
373366857a2SPetar Jovanovic     if (Mapping.isValid())
374366857a2SPetar Jovanovic       return Mapping;
375be20e361SPetar Avramovic   }
376366857a2SPetar Jovanovic 
377366857a2SPetar Jovanovic   using namespace TargetOpcode;
378366857a2SPetar Jovanovic 
379366857a2SPetar Jovanovic   unsigned NumOperands = MI.getNumOperands();
380366857a2SPetar Jovanovic   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
381ec575f6eSPetar Avramovic   unsigned MappingID = DefaultMappingID;
382ec575f6eSPetar Avramovic   const unsigned CustomMappingID = 1;
383366857a2SPetar Jovanovic 
384366857a2SPetar Jovanovic   switch (Opc) {
3857cecadb9SPetar Avramovic   case G_TRUNC:
386366857a2SPetar Jovanovic   case G_ADD:
3877cecadb9SPetar Avramovic   case G_SUB:
38856dc218dSPetar Avramovic   case G_MUL:
389a48285a1SPetar Avramovic   case G_UMULH:
39079df8596SPetar Avramovic   case G_ZEXTLOAD:
39179df8596SPetar Avramovic   case G_SEXTLOAD:
392021e4c82SPetar Jovanovic   case G_GEP:
393b1fc6f61SPetar Avramovic   case G_INTTOPTR:
394b1fc6f61SPetar Avramovic   case G_PTRTOINT:
3953b953c37SPetar Jovanovic   case G_AND:
3963b953c37SPetar Jovanovic   case G_OR:
3973b953c37SPetar Jovanovic   case G_XOR:
3983b953c37SPetar Jovanovic   case G_SHL:
3993b953c37SPetar Jovanovic   case G_ASHR:
4003b953c37SPetar Jovanovic   case G_LSHR:
4010a5e4eb7SPetar Avramovic   case G_SDIV:
4020a5e4eb7SPetar Avramovic   case G_UDIV:
4030a5e4eb7SPetar Avramovic   case G_SREM:
4040a5e4eb7SPetar Avramovic   case G_UREM:
405*ff6ac1ebSPetar Avramovic   case G_BRINDIRECT:
406366857a2SPetar Jovanovic     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
407366857a2SPetar Jovanovic     break;
408aa699b20SPetar Avramovic   case G_LOAD: {
409aa699b20SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
410aa699b20SPetar Avramovic     InstType InstTy = InstType::Integer;
411aa699b20SPetar Avramovic     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
412aa699b20SPetar Avramovic       InstTy = TI.determineInstType(&MI);
413aa699b20SPetar Avramovic     }
414aa699b20SPetar Avramovic 
415e3bb0a72SPetar Avramovic     if (InstTy == InstType::FloatingPoint ||
416e3bb0a72SPetar Avramovic         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
417aa699b20SPetar Avramovic       OperandsMapping =
418aa699b20SPetar Avramovic           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
419aa699b20SPetar Avramovic                                          : &Mips::ValueMappings[Mips::DPRIdx],
420aa699b20SPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
421aa699b20SPetar Avramovic       break;
422aa699b20SPetar Avramovic     } else { // gprb
423aa699b20SPetar Avramovic       OperandsMapping =
424aa699b20SPetar Avramovic           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
425aa699b20SPetar Avramovic                                          : &Mips::ValueMappings[Mips::DPRIdx],
426aa699b20SPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
427aa699b20SPetar Avramovic       if (Size == 64)
428aa699b20SPetar Avramovic         MappingID = CustomMappingID;
429aa699b20SPetar Avramovic     }
430aa699b20SPetar Avramovic 
431aa699b20SPetar Avramovic     break;
432aa699b20SPetar Avramovic   }
433ec575f6eSPetar Avramovic   case G_STORE: {
434ec575f6eSPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
435ec575f6eSPetar Avramovic     InstType InstTy = InstType::Integer;
436ec575f6eSPetar Avramovic     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
437ec575f6eSPetar Avramovic       InstTy = TI.determineInstType(&MI);
438ec575f6eSPetar Avramovic     }
439ec575f6eSPetar Avramovic 
440e3bb0a72SPetar Avramovic     if (InstTy == InstType::FloatingPoint ||
441e3bb0a72SPetar Avramovic         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
442ec575f6eSPetar Avramovic       OperandsMapping =
443ec575f6eSPetar Avramovic           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
444ec575f6eSPetar Avramovic                                          : &Mips::ValueMappings[Mips::DPRIdx],
445ec575f6eSPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
446ec575f6eSPetar Avramovic       break;
447ec575f6eSPetar Avramovic     } else { // gprb
448ec575f6eSPetar Avramovic       OperandsMapping =
449ec575f6eSPetar Avramovic           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
450ec575f6eSPetar Avramovic                                          : &Mips::ValueMappings[Mips::DPRIdx],
451ec575f6eSPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
452ec575f6eSPetar Avramovic       if (Size == 64)
453ec575f6eSPetar Avramovic         MappingID = CustomMappingID;
454ec575f6eSPetar Avramovic     }
455ec575f6eSPetar Avramovic     break;
456ec575f6eSPetar Avramovic   }
457be20e361SPetar Avramovic   case G_PHI: {
458be20e361SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
459be20e361SPetar Avramovic     InstType InstTy = InstType::Integer;
460be20e361SPetar Avramovic     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
461be20e361SPetar Avramovic       InstTy = TI.determineInstType(&MI);
462be20e361SPetar Avramovic     }
463be20e361SPetar Avramovic 
464be20e361SPetar Avramovic     // PHI is copylike and should have one regbank in mapping for def register.
465be20e361SPetar Avramovic     if (InstTy == InstType::Integer && Size == 64) { // fprb
466be20e361SPetar Avramovic       OperandsMapping =
467be20e361SPetar Avramovic           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
468be20e361SPetar Avramovic       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
469be20e361SPetar Avramovic                                    /*NumOperands=*/1);
470be20e361SPetar Avramovic     }
471be20e361SPetar Avramovic     // Use default handling for PHI, i.e. set reg bank of def operand to match
472be20e361SPetar Avramovic     // register banks of use operands.
473be20e361SPetar Avramovic     const RegisterBankInfo::InstructionMapping &Mapping =
474be20e361SPetar Avramovic         getInstrMappingImpl(MI);
475be20e361SPetar Avramovic     return Mapping;
476be20e361SPetar Avramovic   }
477dbb6d01dSPetar Avramovic   case G_SELECT: {
478dbb6d01dSPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
479dbb6d01dSPetar Avramovic     InstType InstTy = InstType::Integer;
480dbb6d01dSPetar Avramovic     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
481dbb6d01dSPetar Avramovic       InstTy = TI.determineInstType(&MI);
482dbb6d01dSPetar Avramovic     }
483dbb6d01dSPetar Avramovic 
484e3bb0a72SPetar Avramovic     if (InstTy == InstType::FloatingPoint ||
485e3bb0a72SPetar Avramovic         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
486dbb6d01dSPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank =
487dbb6d01dSPetar Avramovic           Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
488dbb6d01dSPetar Avramovic                      : &Mips::ValueMappings[Mips::DPRIdx];
489dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
490dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
491dbb6d01dSPetar Avramovic       break;
492dbb6d01dSPetar Avramovic     } else { // gprb
493dbb6d01dSPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank =
494dbb6d01dSPetar Avramovic           Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
495dbb6d01dSPetar Avramovic                      : &Mips::ValueMappings[Mips::DPRIdx];
496dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
497dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
498dbb6d01dSPetar Avramovic       if (Size == 64)
499dbb6d01dSPetar Avramovic         MappingID = CustomMappingID;
500dbb6d01dSPetar Avramovic     }
501dbb6d01dSPetar Avramovic     break;
502dbb6d01dSPetar Avramovic   }
50375e43a60SPetar Avramovic   case G_IMPLICIT_DEF: {
50475e43a60SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
50575e43a60SPetar Avramovic     InstType InstTy = InstType::Integer;
50675e43a60SPetar Avramovic     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
50775e43a60SPetar Avramovic       InstTy = TI.determineInstType(&MI);
50875e43a60SPetar Avramovic     }
50975e43a60SPetar Avramovic 
51075e43a60SPetar Avramovic     if (InstTy == InstType::FloatingPoint) { // fprb
51175e43a60SPetar Avramovic       OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
51275e43a60SPetar Avramovic                                    : &Mips::ValueMappings[Mips::DPRIdx];
51375e43a60SPetar Avramovic     } else { // gprb
51475e43a60SPetar Avramovic       OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::GPRIdx]
51575e43a60SPetar Avramovic                                    : &Mips::ValueMappings[Mips::DPRIdx];
51675e43a60SPetar Avramovic       if (Size == 64)
51775e43a60SPetar Avramovic         MappingID = CustomMappingID;
51875e43a60SPetar Avramovic     }
51975e43a60SPetar Avramovic     break;
52075e43a60SPetar Avramovic   }
521aa699b20SPetar Avramovic   case G_UNMERGE_VALUES: {
522aa699b20SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
523aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
524aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
525aa699b20SPetar Avramovic     MappingID = CustomMappingID;
526aa699b20SPetar Avramovic     break;
527aa699b20SPetar Avramovic   }
528ec575f6eSPetar Avramovic   case G_MERGE_VALUES: {
529ec575f6eSPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
530ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
531ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx]});
532ec575f6eSPetar Avramovic     MappingID = CustomMappingID;
533ec575f6eSPetar Avramovic     break;
534ec575f6eSPetar Avramovic   }
535afa3afa3SPetar Avramovic   case G_FADD:
536afa3afa3SPetar Avramovic   case G_FSUB:
537afa3afa3SPetar Avramovic   case G_FMUL:
5380a1fd355SPetar Avramovic   case G_FDIV:
53981132ce0SPetar Avramovic   case G_FABS:
54081132ce0SPetar Avramovic   case G_FSQRT:{
541afa3afa3SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
542afa3afa3SPetar Avramovic     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
543afa3afa3SPetar Avramovic     OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
544afa3afa3SPetar Avramovic                                  : &Mips::ValueMappings[Mips::DPRIdx];
545afa3afa3SPetar Avramovic     break;
546afa3afa3SPetar Avramovic   }
5471af05df3SPetar Avramovic   case G_FCONSTANT: {
548afa3afa3SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
549afa3afa3SPetar Avramovic     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
5501af05df3SPetar Avramovic     const RegisterBankInfo::ValueMapping *FPRValueMapping =
5511af05df3SPetar Avramovic         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
5521af05df3SPetar Avramovic                    : &Mips::ValueMappings[Mips::DPRIdx];
5531af05df3SPetar Avramovic     OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
5541af05df3SPetar Avramovic     break;
5551af05df3SPetar Avramovic   }
55622e99c43SPetar Avramovic   case G_FCMP: {
55722e99c43SPetar Avramovic     unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
55822e99c43SPetar Avramovic     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
55922e99c43SPetar Avramovic     const RegisterBankInfo::ValueMapping *FPRValueMapping =
56022e99c43SPetar Avramovic         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
56122e99c43SPetar Avramovic                    : &Mips::ValueMappings[Mips::DPRIdx];
56222e99c43SPetar Avramovic     OperandsMapping =
56322e99c43SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
56422e99c43SPetar Avramovic                             FPRValueMapping, FPRValueMapping});
56522e99c43SPetar Avramovic     break;
56622e99c43SPetar Avramovic   }
567a7d00064SPetar Avramovic   case G_FPEXT:
568a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
569a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::SPRIdx]});
570a7d00064SPetar Avramovic     break;
571a7d00064SPetar Avramovic   case G_FPTRUNC:
572a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
573a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
574a7d00064SPetar Avramovic     break;
5754b4dae1cSPetar Avramovic   case G_FPTOSI: {
5764b4dae1cSPetar Avramovic     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
577ddd056c9SFangrui Song     assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
578ddd056c9SFangrui Song            "Unsupported integer size");
5794b4dae1cSPetar Avramovic     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
5804b4dae1cSPetar Avramovic     OperandsMapping = getOperandsMapping({
5814b4dae1cSPetar Avramovic         &Mips::ValueMappings[Mips::GPRIdx],
5824b4dae1cSPetar Avramovic         SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
5834b4dae1cSPetar Avramovic                      : &Mips::ValueMappings[Mips::DPRIdx],
5844b4dae1cSPetar Avramovic     });
5854b4dae1cSPetar Avramovic     break;
5864b4dae1cSPetar Avramovic   }
587153bd24eSPetar Avramovic   case G_SITOFP: {
588153bd24eSPetar Avramovic     unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
589153bd24eSPetar Avramovic     unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
590ddd056c9SFangrui Song     (void)SizeInt;
591153bd24eSPetar Avramovic     assert((SizeInt == 32) && "Unsupported integer size");
592153bd24eSPetar Avramovic     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
593153bd24eSPetar Avramovic     OperandsMapping =
594153bd24eSPetar Avramovic         getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
595153bd24eSPetar Avramovic                                          : &Mips::ValueMappings[Mips::DPRIdx],
596153bd24eSPetar Avramovic                             &Mips::ValueMappings[Mips::GPRIdx]});
597153bd24eSPetar Avramovic     break;
598153bd24eSPetar Avramovic   }
599021e4c82SPetar Jovanovic   case G_CONSTANT:
600021e4c82SPetar Jovanovic   case G_FRAME_INDEX:
60164c10ba8SPetar Jovanovic   case G_GLOBAL_VALUE:
602caef9306SPetar Avramovic   case G_JUMP_TABLE:
6035d9b8eedSPetar Avramovic   case G_BRCOND:
604021e4c82SPetar Jovanovic     OperandsMapping =
605021e4c82SPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
606021e4c82SPetar Jovanovic     break;
607caef9306SPetar Avramovic   case G_BRJT:
608caef9306SPetar Avramovic     OperandsMapping =
609caef9306SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
610caef9306SPetar Avramovic                             &Mips::ValueMappings[Mips::GPRIdx]});
611caef9306SPetar Avramovic     break;
612ce4dd0aeSPetar Jovanovic   case G_ICMP:
613ce4dd0aeSPetar Jovanovic     OperandsMapping =
614ce4dd0aeSPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
615ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx],
616ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx]});
617ce4dd0aeSPetar Jovanovic     break;
618366857a2SPetar Jovanovic   default:
619366857a2SPetar Jovanovic     return getInvalidInstructionMapping();
620366857a2SPetar Jovanovic   }
621366857a2SPetar Jovanovic 
622ec575f6eSPetar Avramovic   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
623366857a2SPetar Jovanovic                                NumOperands);
624366857a2SPetar Jovanovic }
625ec575f6eSPetar Avramovic 
626ec575f6eSPetar Avramovic using InstListTy = GISelWorkList<4>;
627ec575f6eSPetar Avramovic namespace {
628ec575f6eSPetar Avramovic class InstManager : public GISelChangeObserver {
629ec575f6eSPetar Avramovic   InstListTy &InstList;
630ec575f6eSPetar Avramovic 
631ec575f6eSPetar Avramovic public:
632ec575f6eSPetar Avramovic   InstManager(InstListTy &Insts) : InstList(Insts) {}
633ec575f6eSPetar Avramovic 
634ec575f6eSPetar Avramovic   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
635ec575f6eSPetar Avramovic   void erasingInstr(MachineInstr &MI) override {}
636ec575f6eSPetar Avramovic   void changingInstr(MachineInstr &MI) override {}
637ec575f6eSPetar Avramovic   void changedInstr(MachineInstr &MI) override {}
638ec575f6eSPetar Avramovic };
639ec575f6eSPetar Avramovic } // end anonymous namespace
640ec575f6eSPetar Avramovic 
641ec575f6eSPetar Avramovic /// Here we have to narrowScalar s64 operands to s32, combine away
642ec575f6eSPetar Avramovic /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
643ec575f6eSPetar Avramovic /// We manually assign 32 bit gprb to register operands of all new instructions
644ec575f6eSPetar Avramovic /// that got created in the process since they will not end up in RegBankSelect
645ec575f6eSPetar Avramovic /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
646ec575f6eSPetar Avramovic void MipsRegisterBankInfo::applyMappingImpl(
647ec575f6eSPetar Avramovic     const OperandsMapper &OpdMapper) const {
648ec575f6eSPetar Avramovic   MachineInstr &MI = OpdMapper.getMI();
649ec575f6eSPetar Avramovic   InstListTy NewInstrs;
650ec575f6eSPetar Avramovic   MachineIRBuilder B(MI);
651ec575f6eSPetar Avramovic   MachineFunction *MF = MI.getMF();
652ec575f6eSPetar Avramovic   MachineRegisterInfo &MRI = OpdMapper.getMRI();
653ec575f6eSPetar Avramovic 
654ec575f6eSPetar Avramovic   InstManager NewInstrObserver(NewInstrs);
655ec575f6eSPetar Avramovic   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
656ec575f6eSPetar Avramovic   LegalizerHelper Helper(*MF, WrapperObserver, B);
657ec575f6eSPetar Avramovic   LegalizationArtifactCombiner ArtCombiner(
658ec575f6eSPetar Avramovic       B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
659ec575f6eSPetar Avramovic 
660ec575f6eSPetar Avramovic   switch (MI.getOpcode()) {
661aa699b20SPetar Avramovic   case TargetOpcode::G_LOAD:
662dbb6d01dSPetar Avramovic   case TargetOpcode::G_STORE:
663be20e361SPetar Avramovic   case TargetOpcode::G_PHI:
66475e43a60SPetar Avramovic   case TargetOpcode::G_SELECT:
66575e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF: {
666ec575f6eSPetar Avramovic     Helper.narrowScalar(MI, 0, LLT::scalar(32));
667ec575f6eSPetar Avramovic     // Handle new instructions.
668ec575f6eSPetar Avramovic     while (!NewInstrs.empty()) {
669ec575f6eSPetar Avramovic       MachineInstr *NewMI = NewInstrs.pop_back_val();
670ec575f6eSPetar Avramovic       // This is new G_UNMERGE that was created during narrowScalar and will
671ec575f6eSPetar Avramovic       // not be considered for regbank selection. RegBankSelect for mips
672ec575f6eSPetar Avramovic       // visits/makes corresponding G_MERGE first. Combine them here.
673ec575f6eSPetar Avramovic       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
674ec575f6eSPetar Avramovic         SmallVector<MachineInstr *, 2> DeadInstrs;
675ec575f6eSPetar Avramovic         ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
676ec575f6eSPetar Avramovic         for (MachineInstr *DeadMI : DeadInstrs)
677ec575f6eSPetar Avramovic           DeadMI->eraseFromParent();
678aa699b20SPetar Avramovic       }
679aa699b20SPetar Avramovic       // This G_MERGE will be combined away when its corresponding G_UNMERGE
680aa699b20SPetar Avramovic       // gets regBankSelected.
681aa699b20SPetar Avramovic       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
682aa699b20SPetar Avramovic         continue;
683aa699b20SPetar Avramovic       else
684ec575f6eSPetar Avramovic         // Manually set register banks for all register operands to 32 bit gprb.
685ec575f6eSPetar Avramovic         for (auto Op : NewMI->operands()) {
686ec575f6eSPetar Avramovic           if (Op.isReg()) {
687ec575f6eSPetar Avramovic             assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
688ec575f6eSPetar Avramovic                    "Only 32 bit gprb is handled here.\n");
689ec575f6eSPetar Avramovic             MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
690ec575f6eSPetar Avramovic           }
691ec575f6eSPetar Avramovic         }
692ec575f6eSPetar Avramovic     }
693ec575f6eSPetar Avramovic     return;
694ec575f6eSPetar Avramovic   }
695aa699b20SPetar Avramovic   case TargetOpcode::G_UNMERGE_VALUES: {
696aa699b20SPetar Avramovic     SmallVector<MachineInstr *, 2> DeadInstrs;
697aa699b20SPetar Avramovic     ArtCombiner.tryCombineMerges(MI, DeadInstrs);
698aa699b20SPetar Avramovic     for (MachineInstr *DeadMI : DeadInstrs)
699aa699b20SPetar Avramovic       DeadMI->eraseFromParent();
700aa699b20SPetar Avramovic     return;
701aa699b20SPetar Avramovic   }
702ec575f6eSPetar Avramovic   default:
703ec575f6eSPetar Avramovic     break;
704ec575f6eSPetar Avramovic   }
705ec575f6eSPetar Avramovic 
706ec575f6eSPetar Avramovic   return applyDefaultMapping(OpdMapper);
707ec575f6eSPetar Avramovic }
708