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"
15599591f3SPetar Avramovic #include "MipsTargetMachine.h"
16ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
18ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
19fac93e28SPetar Jovanovic #include "llvm/CodeGen/MachineRegisterInfo.h"
20fac93e28SPetar Jovanovic 
21366857a2SPetar Jovanovic #define GET_TARGET_REGBANK_IMPL
22fac93e28SPetar Jovanovic 
23366857a2SPetar Jovanovic #include "MipsGenRegisterBank.inc"
24366857a2SPetar Jovanovic 
25366857a2SPetar Jovanovic namespace llvm {
26366857a2SPetar Jovanovic namespace Mips {
27366857a2SPetar Jovanovic enum PartialMappingIdx {
28366857a2SPetar Jovanovic   PMI_GPR,
291af05df3SPetar Avramovic   PMI_SPR,
301af05df3SPetar Avramovic   PMI_DPR,
31599591f3SPetar Avramovic   PMI_MSA,
32366857a2SPetar Jovanovic   PMI_Min = PMI_GPR,
33366857a2SPetar Jovanovic };
34366857a2SPetar Jovanovic 
35366857a2SPetar Jovanovic RegisterBankInfo::PartialMapping PartMappings[]{
361af05df3SPetar Avramovic     {0, 32, GPRBRegBank},
371af05df3SPetar Avramovic     {0, 32, FPRBRegBank},
38599591f3SPetar Avramovic     {0, 64, FPRBRegBank},
39599591f3SPetar Avramovic     {0, 128, FPRBRegBank}
40366857a2SPetar Jovanovic };
41366857a2SPetar Jovanovic 
421af05df3SPetar Avramovic enum ValueMappingIdx {
431af05df3SPetar Avramovic     InvalidIdx = 0,
441af05df3SPetar Avramovic     GPRIdx = 1,
451af05df3SPetar Avramovic     SPRIdx = 4,
46599591f3SPetar Avramovic     DPRIdx = 7,
47599591f3SPetar Avramovic     MSAIdx = 10
481af05df3SPetar Avramovic };
49366857a2SPetar Jovanovic 
50366857a2SPetar Jovanovic RegisterBankInfo::ValueMapping ValueMappings[] = {
51366857a2SPetar Jovanovic     // invalid
52366857a2SPetar Jovanovic     {nullptr, 0},
531af05df3SPetar Avramovic     // up to 3 operands in GPRs
54366857a2SPetar Jovanovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
55366857a2SPetar Jovanovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
561af05df3SPetar Avramovic     {&PartMappings[PMI_GPR - PMI_Min], 1},
57f7c213c9SPetar Avramovic     // up to 3 operands in FPRs - single precission
581af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
591af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
601af05df3SPetar Avramovic     {&PartMappings[PMI_SPR - PMI_Min], 1},
61f7c213c9SPetar Avramovic     // up to 3 operands in FPRs - double precission
621af05df3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1},
631af05df3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1},
64599591f3SPetar Avramovic     {&PartMappings[PMI_DPR - PMI_Min], 1},
65599591f3SPetar Avramovic     // up to 3 operands in FPRs - MSA
66599591f3SPetar Avramovic     {&PartMappings[PMI_MSA - PMI_Min], 1},
67599591f3SPetar Avramovic     {&PartMappings[PMI_MSA - PMI_Min], 1},
68599591f3SPetar Avramovic     {&PartMappings[PMI_MSA - PMI_Min], 1}
691af05df3SPetar Avramovic };
70366857a2SPetar Jovanovic 
71366857a2SPetar Jovanovic } // end namespace Mips
72366857a2SPetar Jovanovic } // end namespace llvm
73366857a2SPetar Jovanovic 
74366857a2SPetar Jovanovic using namespace llvm;
75fac93e28SPetar Jovanovic 
76fac93e28SPetar Jovanovic MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
77fac93e28SPetar Jovanovic     : MipsGenRegisterBankInfo() {}
78366857a2SPetar Jovanovic 
79366857a2SPetar Jovanovic const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
80366857a2SPetar Jovanovic     const TargetRegisterClass &RC) const {
81366857a2SPetar Jovanovic   using namespace Mips;
82366857a2SPetar Jovanovic 
83366857a2SPetar Jovanovic   switch (RC.getID()) {
84366857a2SPetar Jovanovic   case Mips::GPR32RegClassID:
85366857a2SPetar Jovanovic   case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
86852dd83bSSimon Atanasyan   case Mips::GPRMM16MovePPairFirstRegClassID:
87852dd83bSSimon Atanasyan   case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
88366857a2SPetar Jovanovic   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
89852dd83bSSimon Atanasyan   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
90021e4c82SPetar Jovanovic   case Mips::SP32RegClassID:
91efcd3c00SPetar Avramovic   case Mips::GP32RegClassID:
92366857a2SPetar Jovanovic     return getRegBank(Mips::GPRBRegBankID);
933dfa368dSPetar Avramovic   case Mips::FGRCCRegClassID:
94afa3afa3SPetar Avramovic   case Mips::FGR32RegClassID:
953dfa368dSPetar Avramovic   case Mips::FGR64RegClassID:
963dfa368dSPetar Avramovic   case Mips::AFGR64RegClassID:
97599591f3SPetar Avramovic   case Mips::MSA128BRegClassID:
98599591f3SPetar Avramovic   case Mips::MSA128HRegClassID:
99599591f3SPetar Avramovic   case Mips::MSA128WRegClassID:
100599591f3SPetar Avramovic   case Mips::MSA128DRegClassID:
1013dfa368dSPetar Avramovic     return getRegBank(Mips::FPRBRegBankID);
102366857a2SPetar Jovanovic   default:
103366857a2SPetar Jovanovic     llvm_unreachable("Register class not supported");
104366857a2SPetar Jovanovic   }
105366857a2SPetar Jovanovic }
106366857a2SPetar Jovanovic 
107ec575f6eSPetar Avramovic // Instructions where all register operands are floating point.
108ec575f6eSPetar Avramovic static bool isFloatingPointOpcode(unsigned Opc) {
109ec575f6eSPetar Avramovic   switch (Opc) {
110ec575f6eSPetar Avramovic   case TargetOpcode::G_FCONSTANT:
111ec575f6eSPetar Avramovic   case TargetOpcode::G_FADD:
112ec575f6eSPetar Avramovic   case TargetOpcode::G_FSUB:
113ec575f6eSPetar Avramovic   case TargetOpcode::G_FMUL:
114ec575f6eSPetar Avramovic   case TargetOpcode::G_FDIV:
115ec575f6eSPetar Avramovic   case TargetOpcode::G_FABS:
116ec575f6eSPetar Avramovic   case TargetOpcode::G_FSQRT:
117ec575f6eSPetar Avramovic   case TargetOpcode::G_FCEIL:
118ec575f6eSPetar Avramovic   case TargetOpcode::G_FFLOOR:
119ec575f6eSPetar Avramovic   case TargetOpcode::G_FPEXT:
120ec575f6eSPetar Avramovic   case TargetOpcode::G_FPTRUNC:
121ec575f6eSPetar Avramovic     return true;
122ec575f6eSPetar Avramovic   default:
123ec575f6eSPetar Avramovic     return false;
124ec575f6eSPetar Avramovic   }
125ec575f6eSPetar Avramovic }
126ec575f6eSPetar Avramovic 
127aa699b20SPetar Avramovic // Instructions where use operands are floating point registers.
128aa699b20SPetar Avramovic // Def operands are general purpose.
129aa699b20SPetar Avramovic static bool isFloatingPointOpcodeUse(unsigned Opc) {
130aa699b20SPetar Avramovic   switch (Opc) {
131aa699b20SPetar Avramovic   case TargetOpcode::G_FPTOSI:
132aa699b20SPetar Avramovic   case TargetOpcode::G_FPTOUI:
133aa699b20SPetar Avramovic   case TargetOpcode::G_FCMP:
134aa699b20SPetar Avramovic   case Mips::MFC1:
135aa699b20SPetar Avramovic   case Mips::ExtractElementF64:
136aa699b20SPetar Avramovic   case Mips::ExtractElementF64_64:
137aa699b20SPetar Avramovic     return true;
138aa699b20SPetar Avramovic   default:
139aa699b20SPetar Avramovic     return isFloatingPointOpcode(Opc);
140aa699b20SPetar Avramovic   }
141aa699b20SPetar Avramovic }
142aa699b20SPetar Avramovic 
143ec575f6eSPetar Avramovic // Instructions where def operands are floating point registers.
144ec575f6eSPetar Avramovic // Use operands are general purpose.
145ec575f6eSPetar Avramovic static bool isFloatingPointOpcodeDef(unsigned Opc) {
146ec575f6eSPetar Avramovic   switch (Opc) {
147ec575f6eSPetar Avramovic   case TargetOpcode::G_SITOFP:
148ec575f6eSPetar Avramovic   case TargetOpcode::G_UITOFP:
149ec575f6eSPetar Avramovic   case Mips::MTC1:
150ec575f6eSPetar Avramovic   case Mips::BuildPairF64:
151ec575f6eSPetar Avramovic   case Mips::BuildPairF64_64:
152ec575f6eSPetar Avramovic     return true;
153ec575f6eSPetar Avramovic   default:
154ec575f6eSPetar Avramovic     return isFloatingPointOpcode(Opc);
155ec575f6eSPetar Avramovic   }
156ec575f6eSPetar Avramovic }
157ec575f6eSPetar Avramovic 
158ec575f6eSPetar Avramovic static bool isAmbiguous(unsigned Opc) {
159ec575f6eSPetar Avramovic   switch (Opc) {
160ec575f6eSPetar Avramovic   case TargetOpcode::G_LOAD:
161ec575f6eSPetar Avramovic   case TargetOpcode::G_STORE:
162ec575f6eSPetar Avramovic   case TargetOpcode::G_PHI:
163ec575f6eSPetar Avramovic   case TargetOpcode::G_SELECT:
16475e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF:
165ec575f6eSPetar Avramovic     return true;
166ec575f6eSPetar Avramovic   default:
167ec575f6eSPetar Avramovic     return false;
168ec575f6eSPetar Avramovic   }
169ec575f6eSPetar Avramovic }
170ec575f6eSPetar Avramovic 
171aa699b20SPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
172aa699b20SPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
173aa699b20SPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
174aa699b20SPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
175aa699b20SPetar Avramovic   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
17696252407SPetar Avramovic     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
17796252407SPetar Avramovic     // Copy with many uses.
17896252407SPetar Avramovic     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
1792bea69bfSDaniel Sanders         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
18096252407SPetar Avramovic       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
18196252407SPetar Avramovic     else
18296252407SPetar Avramovic       DefUses.push_back(skipCopiesOutgoing(&UseMI));
183aa699b20SPetar Avramovic   }
184aa699b20SPetar Avramovic }
185aa699b20SPetar Avramovic 
186ec575f6eSPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
187ec575f6eSPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
188ec575f6eSPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
189ec575f6eSPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
190ec575f6eSPetar Avramovic   MachineInstr *DefMI = MRI.getVRegDef(Reg);
19196252407SPetar Avramovic   UseDefs.push_back(skipCopiesIncoming(DefMI));
19296252407SPetar Avramovic }
193ec575f6eSPetar Avramovic 
19496252407SPetar Avramovic MachineInstr *
19596252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
19696252407SPetar Avramovic     MachineInstr *MI) const {
19796252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
19896252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
19996252407SPetar Avramovic   MachineInstr *Ret = MI;
20096252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
2012bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
20296252407SPetar Avramovic          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
20396252407SPetar Avramovic     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
20496252407SPetar Avramovic   }
20596252407SPetar Avramovic   return Ret;
20696252407SPetar Avramovic }
20796252407SPetar Avramovic 
20896252407SPetar Avramovic MachineInstr *
20996252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
21096252407SPetar Avramovic     MachineInstr *MI) const {
21196252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
21296252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
21396252407SPetar Avramovic   MachineInstr *Ret = MI;
21496252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
2152bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
21696252407SPetar Avramovic     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
21796252407SPetar Avramovic   return Ret;
218ec575f6eSPetar Avramovic }
219ec575f6eSPetar Avramovic 
220ec575f6eSPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
221ec575f6eSPetar Avramovic     const MachineInstr *MI) {
222ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) &&
223ec575f6eSPetar Avramovic          "Not implemented for non Ambiguous opcode.\n");
224ec575f6eSPetar Avramovic 
225ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
226ec575f6eSPetar Avramovic 
227aa699b20SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_LOAD)
228aa699b20SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
229aa699b20SPetar Avramovic 
230ec575f6eSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_STORE)
231ec575f6eSPetar Avramovic     addUseDef(MI->getOperand(0).getReg(), MRI);
232dbb6d01dSPetar Avramovic 
233be20e361SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_PHI) {
234be20e361SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
235be20e361SPetar Avramovic 
236be20e361SPetar Avramovic     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
237be20e361SPetar Avramovic       addUseDef(MI->getOperand(i).getReg(), MRI);
238be20e361SPetar Avramovic   }
239be20e361SPetar Avramovic 
240dbb6d01dSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
241dbb6d01dSPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
242dbb6d01dSPetar Avramovic 
243dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(2).getReg(), MRI);
244dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(3).getReg(), MRI);
245dbb6d01dSPetar Avramovic   }
24675e43a60SPetar Avramovic 
24775e43a60SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
24875e43a60SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
249ec575f6eSPetar Avramovic }
250ec575f6eSPetar Avramovic 
251e3bb0a72SPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visit(
252e3bb0a72SPetar Avramovic     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
253ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
254e3bb0a72SPetar Avramovic   if (wasVisited(MI))
255e3bb0a72SPetar Avramovic     return true; // InstType has already been determined for MI.
256ec575f6eSPetar Avramovic 
257ec575f6eSPetar Avramovic   startVisit(MI);
258ec575f6eSPetar Avramovic   AmbiguousRegDefUseContainer DefUseContainer(MI);
259ec575f6eSPetar Avramovic 
260aa699b20SPetar Avramovic   // Visit instructions where MI's DEF operands are USED.
261aa699b20SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
262aa699b20SPetar Avramovic     return true;
263aa699b20SPetar Avramovic 
264ec575f6eSPetar Avramovic   // Visit instructions that DEFINE MI's USE operands.
265aa699b20SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
266ec575f6eSPetar Avramovic     return true;
267ec575f6eSPetar Avramovic 
268e3bb0a72SPetar Avramovic   // All MI's adjacent instructions, are ambiguous.
269e3bb0a72SPetar Avramovic   if (!WaitingForTypeOfMI) {
270e3bb0a72SPetar Avramovic     // This is chain of ambiguous instructions.
271e3bb0a72SPetar Avramovic     setTypes(MI, InstType::Ambiguous);
272e3bb0a72SPetar Avramovic     return true;
273e3bb0a72SPetar Avramovic   }
274e3bb0a72SPetar Avramovic   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
275e3bb0a72SPetar Avramovic   // instructions or has no other adjacent instructions. Anyway InstType could
276e3bb0a72SPetar Avramovic   // not be determined. There could be unexplored path from some of
277e3bb0a72SPetar Avramovic   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
278e3bb0a72SPetar Avramovic   // mapping available.
279e3bb0a72SPetar Avramovic   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
280e3bb0a72SPetar Avramovic   // this way when WaitingForTypeOfMI figures out its InstType same InstType
281e3bb0a72SPetar Avramovic   // will be assigned to all instructions in this branch.
282e3bb0a72SPetar Avramovic   addToWaitingQueue(WaitingForTypeOfMI, MI);
283ec575f6eSPetar Avramovic   return false;
284ec575f6eSPetar Avramovic }
285ec575f6eSPetar Avramovic 
286ec575f6eSPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
287aa699b20SPetar Avramovic     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
288aa699b20SPetar Avramovic     bool isDefUse) {
289ec575f6eSPetar Avramovic   while (!AdjacentInstrs.empty()) {
290ec575f6eSPetar Avramovic     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
291ec575f6eSPetar Avramovic 
292aa699b20SPetar Avramovic     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
293aa699b20SPetar Avramovic                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
294ec575f6eSPetar Avramovic       setTypes(MI, InstType::FloatingPoint);
295ec575f6eSPetar Avramovic       return true;
296ec575f6eSPetar Avramovic     }
297ec575f6eSPetar Avramovic 
298ec575f6eSPetar Avramovic     // Determine InstType from register bank of phys register that is
299aa699b20SPetar Avramovic     // 'isDefUse ? def : use' of this copy.
300ec575f6eSPetar Avramovic     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
301aa699b20SPetar Avramovic       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
302ec575f6eSPetar Avramovic       return true;
303ec575f6eSPetar Avramovic     }
304ec575f6eSPetar Avramovic 
305ec575f6eSPetar Avramovic     // Defaults to integer instruction. Includes G_MERGE_VALUES and
306ec575f6eSPetar Avramovic     // G_UNMERGE_VALUES.
307e3bb0a72SPetar Avramovic     if (!isAmbiguous(AdjMI->getOpcode())) {
308ec575f6eSPetar Avramovic       setTypes(MI, InstType::Integer);
309ec575f6eSPetar Avramovic       return true;
310ec575f6eSPetar Avramovic     }
311e3bb0a72SPetar Avramovic 
312e3bb0a72SPetar Avramovic     // When AdjMI was visited first, MI has to continue to explore remaining
313e3bb0a72SPetar Avramovic     // adjacent instructions and determine InstType without visiting AdjMI.
314e3bb0a72SPetar Avramovic     if (!wasVisited(AdjMI) ||
315e3bb0a72SPetar Avramovic         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
316e3bb0a72SPetar Avramovic       if (visit(AdjMI, MI)) {
317e3bb0a72SPetar Avramovic         // InstType is successfully determined and is same as for AdjMI.
318e3bb0a72SPetar Avramovic         setTypes(MI, getRecordedTypeForInstr(AdjMI));
319e3bb0a72SPetar Avramovic         return true;
320e3bb0a72SPetar Avramovic       }
321e3bb0a72SPetar Avramovic     }
322e3bb0a72SPetar Avramovic   }
323ec575f6eSPetar Avramovic   return false;
324ec575f6eSPetar Avramovic }
325ec575f6eSPetar Avramovic 
326ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
327ec575f6eSPetar Avramovic                                                    InstType InstTy) {
328ec575f6eSPetar Avramovic   changeRecordedTypeForInstr(MI, InstTy);
329e3bb0a72SPetar Avramovic   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
330e3bb0a72SPetar Avramovic     setTypes(WaitingInstr, InstTy);
331e3bb0a72SPetar Avramovic   }
332ec575f6eSPetar Avramovic }
333ec575f6eSPetar Avramovic 
334ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
335ec575f6eSPetar Avramovic     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
3362bea69bfSDaniel Sanders   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
337ec575f6eSPetar Avramovic          "Copies of non physical registers should not be considered here.\n");
338ec575f6eSPetar Avramovic 
339ec575f6eSPetar Avramovic   const MachineFunction &MF = *CopyInst->getMF();
340ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
341ec575f6eSPetar Avramovic   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
342ec575f6eSPetar Avramovic   const RegisterBankInfo &RBI =
343ec575f6eSPetar Avramovic       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
344ec575f6eSPetar Avramovic   const RegisterBank *Bank =
345ec575f6eSPetar Avramovic       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
346ec575f6eSPetar Avramovic 
347ec575f6eSPetar Avramovic   if (Bank == &Mips::FPRBRegBank)
348ec575f6eSPetar Avramovic     setTypes(MI, InstType::FloatingPoint);
349ec575f6eSPetar Avramovic   else if (Bank == &Mips::GPRBRegBank)
350ec575f6eSPetar Avramovic     setTypes(MI, InstType::Integer);
351ec575f6eSPetar Avramovic   else
352ec575f6eSPetar Avramovic     llvm_unreachable("Unsupported register bank.\n");
353ec575f6eSPetar Avramovic }
354ec575f6eSPetar Avramovic 
355ec575f6eSPetar Avramovic MipsRegisterBankInfo::InstType
356ec575f6eSPetar Avramovic MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
357e3bb0a72SPetar Avramovic   visit(MI, nullptr);
358ec575f6eSPetar Avramovic   return getRecordedTypeForInstr(MI);
359ec575f6eSPetar Avramovic }
360ec575f6eSPetar Avramovic 
361ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
362ec575f6eSPetar Avramovic     llvm::StringRef FunctionName) {
363ec575f6eSPetar Avramovic   if (MFName != FunctionName) {
364ec575f6eSPetar Avramovic     MFName = FunctionName;
365e3bb0a72SPetar Avramovic     WaitingQueues.clear();
366ec575f6eSPetar Avramovic     Types.clear();
367ec575f6eSPetar Avramovic   }
368ec575f6eSPetar Avramovic }
369ec575f6eSPetar Avramovic 
370599591f3SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
371599591f3SPetar Avramovic getMSAMapping(const MachineFunction &MF) {
372599591f3SPetar Avramovic   assert(static_cast<const MipsSubtarget &>(MF.getSubtarget()).hasMSA() &&
373599591f3SPetar Avramovic          "MSA mapping not available on target without MSA.");
374599591f3SPetar Avramovic   return &Mips::ValueMappings[Mips::MSAIdx];
375599591f3SPetar Avramovic }
376599591f3SPetar Avramovic 
377f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
378f7c213c9SPetar Avramovic   return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
379f7c213c9SPetar Avramovic                     : &Mips::ValueMappings[Mips::DPRIdx];
380f7c213c9SPetar Avramovic }
381f7c213c9SPetar Avramovic 
382f7c213c9SPetar Avramovic static const unsigned CustomMappingID = 1;
383f7c213c9SPetar Avramovic 
384f7c213c9SPetar Avramovic // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
385f7c213c9SPetar Avramovic // will be split into two 32 bit registers in gprb.
386f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
387f7c213c9SPetar Avramovic getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
388f7c213c9SPetar Avramovic   if (Size == 32)
389f7c213c9SPetar Avramovic     return &Mips::ValueMappings[Mips::GPRIdx];
390f7c213c9SPetar Avramovic 
391f7c213c9SPetar Avramovic   MappingID = CustomMappingID;
392f7c213c9SPetar Avramovic   return &Mips::ValueMappings[Mips::DPRIdx];
393f7c213c9SPetar Avramovic }
394f7c213c9SPetar Avramovic 
395366857a2SPetar Jovanovic const RegisterBankInfo::InstructionMapping &
396366857a2SPetar Jovanovic MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
397366857a2SPetar Jovanovic 
398ec575f6eSPetar Avramovic   static TypeInfoForMF TI;
399ec575f6eSPetar Avramovic 
400ec575f6eSPetar Avramovic   // Reset TI internal data when MF changes.
401ec575f6eSPetar Avramovic   TI.cleanupIfNewFunction(MI.getMF()->getName());
402ec575f6eSPetar Avramovic 
403366857a2SPetar Jovanovic   unsigned Opc = MI.getOpcode();
4041af05df3SPetar Avramovic   const MachineFunction &MF = *MI.getParent()->getParent();
4051af05df3SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
406366857a2SPetar Jovanovic 
407be20e361SPetar Avramovic   if (MI.getOpcode() != TargetOpcode::G_PHI) {
408be20e361SPetar Avramovic     const RegisterBankInfo::InstructionMapping &Mapping =
409be20e361SPetar Avramovic         getInstrMappingImpl(MI);
410366857a2SPetar Jovanovic     if (Mapping.isValid())
411366857a2SPetar Jovanovic       return Mapping;
412be20e361SPetar Avramovic   }
413366857a2SPetar Jovanovic 
414366857a2SPetar Jovanovic   using namespace TargetOpcode;
415366857a2SPetar Jovanovic 
416366857a2SPetar Jovanovic   unsigned NumOperands = MI.getNumOperands();
417366857a2SPetar Jovanovic   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
418ec575f6eSPetar Avramovic   unsigned MappingID = DefaultMappingID;
419f7c213c9SPetar Avramovic 
420f7c213c9SPetar Avramovic   // Check if LLT sizes match sizes of available register banks.
421f7c213c9SPetar Avramovic   for (const MachineOperand &Op : MI.operands()) {
422f7c213c9SPetar Avramovic     if (Op.isReg()) {
423f7c213c9SPetar Avramovic       LLT RegTy = MRI.getType(Op.getReg());
424f7c213c9SPetar Avramovic 
425f7c213c9SPetar Avramovic       if (RegTy.isScalar() &&
426f7c213c9SPetar Avramovic           (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
427f7c213c9SPetar Avramovic         return getInvalidInstructionMapping();
428599591f3SPetar Avramovic 
429599591f3SPetar Avramovic       if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
430599591f3SPetar Avramovic         return getInvalidInstructionMapping();
431f7c213c9SPetar Avramovic     }
432f7c213c9SPetar Avramovic   }
433f7c213c9SPetar Avramovic 
434f7c213c9SPetar Avramovic   const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
435f7c213c9SPetar Avramovic   unsigned Op0Size = Op0Ty.getSizeInBits();
436f7c213c9SPetar Avramovic   InstType InstTy = InstType::Integer;
437366857a2SPetar Jovanovic 
438366857a2SPetar Jovanovic   switch (Opc) {
4397cecadb9SPetar Avramovic   case G_TRUNC:
440a48285a1SPetar Avramovic   case G_UMULH:
44179df8596SPetar Avramovic   case G_ZEXTLOAD:
44279df8596SPetar Avramovic   case G_SEXTLOAD:
443021e4c82SPetar Jovanovic   case G_GEP:
444b1fc6f61SPetar Avramovic   case G_INTTOPTR:
445b1fc6f61SPetar Avramovic   case G_PTRTOINT:
4463b953c37SPetar Jovanovic   case G_AND:
4473b953c37SPetar Jovanovic   case G_OR:
4483b953c37SPetar Jovanovic   case G_XOR:
4493b953c37SPetar Jovanovic   case G_SHL:
4503b953c37SPetar Jovanovic   case G_ASHR:
4513b953c37SPetar Jovanovic   case G_LSHR:
452ff6ac1ebSPetar Avramovic   case G_BRINDIRECT:
453c063b0b0SPetar Avramovic   case G_VASTART:
454366857a2SPetar Jovanovic     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
455366857a2SPetar Jovanovic     break;
456e4af9de3SPetar Avramovic   case G_ADD:
457c46d24f5SPetar Avramovic   case G_SUB:
458d1815dacSPetar Avramovic   case G_MUL:
4591d7f79c0SPetar Avramovic   case G_SDIV:
4601d7f79c0SPetar Avramovic   case G_SREM:
4611d7f79c0SPetar Avramovic   case G_UDIV:
4621d7f79c0SPetar Avramovic   case G_UREM:
463e4af9de3SPetar Avramovic     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
464e4af9de3SPetar Avramovic     if (Op0Size == 128)
465e4af9de3SPetar Avramovic       OperandsMapping = getMSAMapping(MF);
466e4af9de3SPetar Avramovic     break;
467f7c213c9SPetar Avramovic   case G_STORE:
468f7c213c9SPetar Avramovic   case G_LOAD:
469599591f3SPetar Avramovic     if (Op0Size == 128) {
470599591f3SPetar Avramovic       OperandsMapping = getOperandsMapping(
471599591f3SPetar Avramovic           {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
472599591f3SPetar Avramovic       break;
473599591f3SPetar Avramovic     }
474599591f3SPetar Avramovic 
475f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
476aa699b20SPetar Avramovic       InstTy = TI.determineInstType(&MI);
477aa699b20SPetar Avramovic 
478e3bb0a72SPetar Avramovic     if (InstTy == InstType::FloatingPoint ||
479f7c213c9SPetar Avramovic         (Op0Size == 64 && InstTy == InstType::Ambiguous))
480f7c213c9SPetar Avramovic       OperandsMapping = getOperandsMapping(
481f7c213c9SPetar Avramovic           {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
482f7c213c9SPetar Avramovic     else
483aa699b20SPetar Avramovic       OperandsMapping =
484f7c213c9SPetar Avramovic           getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
485aa699b20SPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
486aa699b20SPetar Avramovic 
487aa699b20SPetar Avramovic     break;
488f7c213c9SPetar Avramovic   case G_PHI:
489f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
490ec575f6eSPetar Avramovic       InstTy = TI.determineInstType(&MI);
491be20e361SPetar Avramovic 
492be20e361SPetar Avramovic     // PHI is copylike and should have one regbank in mapping for def register.
493f7c213c9SPetar Avramovic     if (InstTy == InstType::Integer && Op0Size == 64) {
494be20e361SPetar Avramovic       OperandsMapping =
495be20e361SPetar Avramovic           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
496be20e361SPetar Avramovic       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
497be20e361SPetar Avramovic                                    /*NumOperands=*/1);
498be20e361SPetar Avramovic     }
499be20e361SPetar Avramovic     // Use default handling for PHI, i.e. set reg bank of def operand to match
500be20e361SPetar Avramovic     // register banks of use operands.
501f7c213c9SPetar Avramovic     return getInstrMappingImpl(MI);
502dbb6d01dSPetar Avramovic   case G_SELECT: {
503f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
504dbb6d01dSPetar Avramovic       InstTy = TI.determineInstType(&MI);
505dbb6d01dSPetar Avramovic 
506e3bb0a72SPetar Avramovic     if (InstTy == InstType::FloatingPoint ||
507f7c213c9SPetar Avramovic         (Op0Size == 64 && InstTy == InstType::Ambiguous)) {
508f7c213c9SPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
509dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
510dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
511dbb6d01dSPetar Avramovic       break;
512f7c213c9SPetar Avramovic     } else {
513dbb6d01dSPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank =
514f7c213c9SPetar Avramovic           getGprbOrCustomMapping(Op0Size, MappingID);
515dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
516dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
517dbb6d01dSPetar Avramovic     }
518dbb6d01dSPetar Avramovic     break;
519dbb6d01dSPetar Avramovic   }
520f7c213c9SPetar Avramovic   case G_IMPLICIT_DEF:
521f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
52275e43a60SPetar Avramovic       InstTy = TI.determineInstType(&MI);
52375e43a60SPetar Avramovic 
524f7c213c9SPetar Avramovic     if (InstTy == InstType::FloatingPoint)
525f7c213c9SPetar Avramovic       OperandsMapping = getFprbMapping(Op0Size);
526f7c213c9SPetar Avramovic     else
527f7c213c9SPetar Avramovic       OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
528f7c213c9SPetar Avramovic 
52975e43a60SPetar Avramovic     break;
530f7c213c9SPetar Avramovic   case G_UNMERGE_VALUES:
531aa699b20SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
532aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
533aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
534aa699b20SPetar Avramovic     MappingID = CustomMappingID;
535aa699b20SPetar Avramovic     break;
536f7c213c9SPetar Avramovic   case G_MERGE_VALUES:
537ec575f6eSPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
538ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
539ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx]});
540ec575f6eSPetar Avramovic     MappingID = CustomMappingID;
541ec575f6eSPetar Avramovic     break;
542afa3afa3SPetar Avramovic   case G_FADD:
543afa3afa3SPetar Avramovic   case G_FSUB:
544afa3afa3SPetar Avramovic   case G_FMUL:
5450a1fd355SPetar Avramovic   case G_FDIV:
546e3b49df5SPetar Avramovic   case G_FABS:
547*417dd678SPetar Avramovic   case G_FSQRT:
548f7c213c9SPetar Avramovic     OperandsMapping = getFprbMapping(Op0Size);
549914ce664SPetar Avramovic     if (Op0Size == 128)
550914ce664SPetar Avramovic       OperandsMapping = getMSAMapping(MF);
551afa3afa3SPetar Avramovic     break;
552f7c213c9SPetar Avramovic   case G_FCONSTANT:
553f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
5541af05df3SPetar Avramovic     break;
55522e99c43SPetar Avramovic   case G_FCMP: {
556f7c213c9SPetar Avramovic     unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
55722e99c43SPetar Avramovic     OperandsMapping =
55822e99c43SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
559f7c213c9SPetar Avramovic                             getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
56022e99c43SPetar Avramovic     break;
56122e99c43SPetar Avramovic   }
562a7d00064SPetar Avramovic   case G_FPEXT:
563a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
564a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::SPRIdx]});
565a7d00064SPetar Avramovic     break;
566a7d00064SPetar Avramovic   case G_FPTRUNC:
567a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
568a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
569a7d00064SPetar Avramovic     break;
5704b4dae1cSPetar Avramovic   case G_FPTOSI: {
571f7c213c9SPetar Avramovic     assert((Op0Size == 32) && "Unsupported integer size");
5724b4dae1cSPetar Avramovic     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
573f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping(
574f7c213c9SPetar Avramovic         {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
575f7c213c9SPetar Avramovic     break;
576f7c213c9SPetar Avramovic   }
577f7c213c9SPetar Avramovic   case G_SITOFP:
578f7c213c9SPetar Avramovic     assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
579ddd056c9SFangrui Song            "Unsupported integer size");
580f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping(
581f7c213c9SPetar Avramovic         {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
5824b4dae1cSPetar Avramovic     break;
583021e4c82SPetar Jovanovic   case G_CONSTANT:
584021e4c82SPetar Jovanovic   case G_FRAME_INDEX:
58564c10ba8SPetar Jovanovic   case G_GLOBAL_VALUE:
586caef9306SPetar Avramovic   case G_JUMP_TABLE:
5875d9b8eedSPetar Avramovic   case G_BRCOND:
588021e4c82SPetar Jovanovic     OperandsMapping =
589021e4c82SPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
590021e4c82SPetar Jovanovic     break;
591caef9306SPetar Avramovic   case G_BRJT:
592caef9306SPetar Avramovic     OperandsMapping =
593caef9306SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
594caef9306SPetar Avramovic                             &Mips::ValueMappings[Mips::GPRIdx]});
595caef9306SPetar Avramovic     break;
596ce4dd0aeSPetar Jovanovic   case G_ICMP:
597ce4dd0aeSPetar Jovanovic     OperandsMapping =
598ce4dd0aeSPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
599ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx],
600ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx]});
601ce4dd0aeSPetar Jovanovic     break;
602366857a2SPetar Jovanovic   default:
603366857a2SPetar Jovanovic     return getInvalidInstructionMapping();
604366857a2SPetar Jovanovic   }
605366857a2SPetar Jovanovic 
606ec575f6eSPetar Avramovic   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
607366857a2SPetar Jovanovic                                NumOperands);
608366857a2SPetar Jovanovic }
609ec575f6eSPetar Avramovic 
610ec575f6eSPetar Avramovic using InstListTy = GISelWorkList<4>;
611ec575f6eSPetar Avramovic namespace {
612ec575f6eSPetar Avramovic class InstManager : public GISelChangeObserver {
613ec575f6eSPetar Avramovic   InstListTy &InstList;
614ec575f6eSPetar Avramovic 
615ec575f6eSPetar Avramovic public:
616ec575f6eSPetar Avramovic   InstManager(InstListTy &Insts) : InstList(Insts) {}
617ec575f6eSPetar Avramovic 
618ec575f6eSPetar Avramovic   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
619ec575f6eSPetar Avramovic   void erasingInstr(MachineInstr &MI) override {}
620ec575f6eSPetar Avramovic   void changingInstr(MachineInstr &MI) override {}
621ec575f6eSPetar Avramovic   void changedInstr(MachineInstr &MI) override {}
622ec575f6eSPetar Avramovic };
623ec575f6eSPetar Avramovic } // end anonymous namespace
624ec575f6eSPetar Avramovic 
625f7c213c9SPetar Avramovic void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
626f7c213c9SPetar Avramovic                                       MachineRegisterInfo &MRI) const {
627f7c213c9SPetar Avramovic   Register Dest = MI.getOperand(0).getReg();
628f7c213c9SPetar Avramovic   switch (MI.getOpcode()) {
629f7c213c9SPetar Avramovic   case TargetOpcode::G_STORE:
630f7c213c9SPetar Avramovic     // No def operands, skip this instruction.
631f7c213c9SPetar Avramovic     break;
632f7c213c9SPetar Avramovic   case TargetOpcode::G_CONSTANT:
633f7c213c9SPetar Avramovic   case TargetOpcode::G_LOAD:
634f7c213c9SPetar Avramovic   case TargetOpcode::G_SELECT:
635f7c213c9SPetar Avramovic   case TargetOpcode::G_PHI:
636f7c213c9SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF: {
637f7c213c9SPetar Avramovic     assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
638f7c213c9SPetar Avramovic     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
639f7c213c9SPetar Avramovic     break;
640f7c213c9SPetar Avramovic   }
641f7c213c9SPetar Avramovic   case TargetOpcode::G_GEP: {
642f7c213c9SPetar Avramovic     assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
643f7c213c9SPetar Avramovic     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
644f7c213c9SPetar Avramovic     break;
645f7c213c9SPetar Avramovic   }
646f7c213c9SPetar Avramovic   default:
647f7c213c9SPetar Avramovic     llvm_unreachable("Unexpected opcode.");
648f7c213c9SPetar Avramovic   }
649f7c213c9SPetar Avramovic }
650f7c213c9SPetar Avramovic 
651f7c213c9SPetar Avramovic static void
652f7c213c9SPetar Avramovic combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
653f7c213c9SPetar Avramovic                             MachineInstr &MI) {
654f7c213c9SPetar Avramovic   SmallVector<MachineInstr *, 2> DeadInstrs;
655f7c213c9SPetar Avramovic   ArtCombiner.tryCombineMerges(MI, DeadInstrs);
656f7c213c9SPetar Avramovic   for (MachineInstr *DeadMI : DeadInstrs)
657f7c213c9SPetar Avramovic     DeadMI->eraseFromParent();
658f7c213c9SPetar Avramovic }
659f7c213c9SPetar Avramovic 
660ec575f6eSPetar Avramovic void MipsRegisterBankInfo::applyMappingImpl(
661ec575f6eSPetar Avramovic     const OperandsMapper &OpdMapper) const {
662ec575f6eSPetar Avramovic   MachineInstr &MI = OpdMapper.getMI();
663ec575f6eSPetar Avramovic   InstListTy NewInstrs;
664ec575f6eSPetar Avramovic   MachineIRBuilder B(MI);
665ec575f6eSPetar Avramovic   MachineFunction *MF = MI.getMF();
666ec575f6eSPetar Avramovic   MachineRegisterInfo &MRI = OpdMapper.getMRI();
667f7c213c9SPetar Avramovic   const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
668ec575f6eSPetar Avramovic 
669ec575f6eSPetar Avramovic   InstManager NewInstrObserver(NewInstrs);
670ec575f6eSPetar Avramovic   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
671ec575f6eSPetar Avramovic   LegalizerHelper Helper(*MF, WrapperObserver, B);
672f7c213c9SPetar Avramovic   LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
673ec575f6eSPetar Avramovic 
674ec575f6eSPetar Avramovic   switch (MI.getOpcode()) {
675aa699b20SPetar Avramovic   case TargetOpcode::G_LOAD:
676dbb6d01dSPetar Avramovic   case TargetOpcode::G_STORE:
677be20e361SPetar Avramovic   case TargetOpcode::G_PHI:
67875e43a60SPetar Avramovic   case TargetOpcode::G_SELECT:
67975e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF: {
680ec575f6eSPetar Avramovic     Helper.narrowScalar(MI, 0, LLT::scalar(32));
681ec575f6eSPetar Avramovic     // Handle new instructions.
682ec575f6eSPetar Avramovic     while (!NewInstrs.empty()) {
683ec575f6eSPetar Avramovic       MachineInstr *NewMI = NewInstrs.pop_back_val();
684ec575f6eSPetar Avramovic       // This is new G_UNMERGE that was created during narrowScalar and will
685ec575f6eSPetar Avramovic       // not be considered for regbank selection. RegBankSelect for mips
686ec575f6eSPetar Avramovic       // visits/makes corresponding G_MERGE first. Combine them here.
687f7c213c9SPetar Avramovic       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
688f7c213c9SPetar Avramovic         combineAwayG_UNMERGE_VALUES(ArtCombiner, *NewMI);
689aa699b20SPetar Avramovic       // This G_MERGE will be combined away when its corresponding G_UNMERGE
690aa699b20SPetar Avramovic       // gets regBankSelected.
691aa699b20SPetar Avramovic       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
692aa699b20SPetar Avramovic         continue;
693aa699b20SPetar Avramovic       else
694f7c213c9SPetar Avramovic         // Manually set register banks for def operands to 32 bit gprb.
695f7c213c9SPetar Avramovic         setRegBank(*NewMI, MRI);
696ec575f6eSPetar Avramovic     }
697ec575f6eSPetar Avramovic     return;
698ec575f6eSPetar Avramovic   }
699f7c213c9SPetar Avramovic   case TargetOpcode::G_UNMERGE_VALUES:
700f7c213c9SPetar Avramovic     combineAwayG_UNMERGE_VALUES(ArtCombiner, MI);
701aa699b20SPetar Avramovic     return;
702ec575f6eSPetar Avramovic   default:
703ec575f6eSPetar Avramovic     break;
704ec575f6eSPetar Avramovic   }
705ec575f6eSPetar Avramovic 
706ec575f6eSPetar Avramovic   return applyDefaultMapping(OpdMapper);
707ec575f6eSPetar Avramovic }
708