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 
76*62128719SKazu Hirata MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {}
77366857a2SPetar Jovanovic 
7821309eafSMatt Arsenault const RegisterBank &
7921309eafSMatt Arsenault MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
8021309eafSMatt Arsenault                                              LLT) 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     return true;
135aa699b20SPetar Avramovic   default:
136aa699b20SPetar Avramovic     return isFloatingPointOpcode(Opc);
137aa699b20SPetar Avramovic   }
138aa699b20SPetar Avramovic }
139aa699b20SPetar Avramovic 
140ec575f6eSPetar Avramovic // Instructions where def operands are floating point registers.
141ec575f6eSPetar Avramovic // Use operands are general purpose.
142ec575f6eSPetar Avramovic static bool isFloatingPointOpcodeDef(unsigned Opc) {
143ec575f6eSPetar Avramovic   switch (Opc) {
144ec575f6eSPetar Avramovic   case TargetOpcode::G_SITOFP:
145ec575f6eSPetar Avramovic   case TargetOpcode::G_UITOFP:
146ec575f6eSPetar Avramovic     return true;
147ec575f6eSPetar Avramovic   default:
148ec575f6eSPetar Avramovic     return isFloatingPointOpcode(Opc);
149ec575f6eSPetar Avramovic   }
150ec575f6eSPetar Avramovic }
151ec575f6eSPetar Avramovic 
1525171d152SPetar Avramovic static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
1535171d152SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_LOAD ||
1545171d152SPetar Avramovic       MI->getOpcode() == TargetOpcode::G_STORE) {
1555171d152SPetar Avramovic     auto MMO = *MI->memoperands_begin();
1565171d152SPetar Avramovic     const MipsSubtarget &STI =
1575171d152SPetar Avramovic         static_cast<const MipsSubtarget &>(MI->getMF()->getSubtarget());
1585171d152SPetar Avramovic     if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
15974eac903SGuillaume Chatelet                                 MMO->getAlign() < MMO->getSize()))
1605171d152SPetar Avramovic       return true;
1615171d152SPetar Avramovic   }
1625171d152SPetar Avramovic   return false;
1635171d152SPetar Avramovic }
1645171d152SPetar Avramovic 
165ec575f6eSPetar Avramovic static bool isAmbiguous(unsigned Opc) {
166ec575f6eSPetar Avramovic   switch (Opc) {
167ec575f6eSPetar Avramovic   case TargetOpcode::G_LOAD:
168ec575f6eSPetar Avramovic   case TargetOpcode::G_STORE:
169ec575f6eSPetar Avramovic   case TargetOpcode::G_PHI:
170ec575f6eSPetar Avramovic   case TargetOpcode::G_SELECT:
17175e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF:
17292c80529SPetar Avramovic   case TargetOpcode::G_UNMERGE_VALUES:
17392c80529SPetar Avramovic   case TargetOpcode::G_MERGE_VALUES:
174ec575f6eSPetar Avramovic     return true;
175ec575f6eSPetar Avramovic   default:
176ec575f6eSPetar Avramovic     return false;
177ec575f6eSPetar Avramovic   }
178ec575f6eSPetar Avramovic }
179ec575f6eSPetar Avramovic 
180aa699b20SPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
181aa699b20SPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
182aa699b20SPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
183aa699b20SPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
184aa699b20SPetar Avramovic   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
18596252407SPetar Avramovic     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
18696252407SPetar Avramovic     // Copy with many uses.
18796252407SPetar Avramovic     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
1882bea69bfSDaniel Sanders         !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
18996252407SPetar Avramovic       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
19096252407SPetar Avramovic     else
19196252407SPetar Avramovic       DefUses.push_back(skipCopiesOutgoing(&UseMI));
192aa699b20SPetar Avramovic   }
193aa699b20SPetar Avramovic }
194aa699b20SPetar Avramovic 
195ec575f6eSPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
196ec575f6eSPetar Avramovic     Register Reg, const MachineRegisterInfo &MRI) {
197ec575f6eSPetar Avramovic   assert(!MRI.getType(Reg).isPointer() &&
198ec575f6eSPetar Avramovic          "Pointers are gprb, they should not be considered as ambiguous.\n");
199ec575f6eSPetar Avramovic   MachineInstr *DefMI = MRI.getVRegDef(Reg);
20096252407SPetar Avramovic   UseDefs.push_back(skipCopiesIncoming(DefMI));
20196252407SPetar Avramovic }
202ec575f6eSPetar Avramovic 
20396252407SPetar Avramovic MachineInstr *
20496252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
20596252407SPetar Avramovic     MachineInstr *MI) const {
20696252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
20796252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
20896252407SPetar Avramovic   MachineInstr *Ret = MI;
20996252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
2102bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
21196252407SPetar Avramovic          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
21296252407SPetar Avramovic     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
21396252407SPetar Avramovic   }
21496252407SPetar Avramovic   return Ret;
21596252407SPetar Avramovic }
21696252407SPetar Avramovic 
21796252407SPetar Avramovic MachineInstr *
21896252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
21996252407SPetar Avramovic     MachineInstr *MI) const {
22096252407SPetar Avramovic   const MachineFunction &MF = *MI->getParent()->getParent();
22196252407SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
22296252407SPetar Avramovic   MachineInstr *Ret = MI;
22396252407SPetar Avramovic   while (Ret->getOpcode() == TargetOpcode::COPY &&
2242bea69bfSDaniel Sanders          !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
22596252407SPetar Avramovic     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
22696252407SPetar Avramovic   return Ret;
227ec575f6eSPetar Avramovic }
228ec575f6eSPetar Avramovic 
229ec575f6eSPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
230ec575f6eSPetar Avramovic     const MachineInstr *MI) {
231ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) &&
232ec575f6eSPetar Avramovic          "Not implemented for non Ambiguous opcode.\n");
233ec575f6eSPetar Avramovic 
234ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
235ec575f6eSPetar Avramovic 
236aa699b20SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_LOAD)
237aa699b20SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
238aa699b20SPetar Avramovic 
239ec575f6eSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_STORE)
240ec575f6eSPetar Avramovic     addUseDef(MI->getOperand(0).getReg(), MRI);
241dbb6d01dSPetar Avramovic 
242be20e361SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_PHI) {
243be20e361SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
244be20e361SPetar Avramovic 
245be20e361SPetar Avramovic     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
246be20e361SPetar Avramovic       addUseDef(MI->getOperand(i).getReg(), MRI);
247be20e361SPetar Avramovic   }
248be20e361SPetar Avramovic 
249dbb6d01dSPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
250dbb6d01dSPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
251dbb6d01dSPetar Avramovic 
252dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(2).getReg(), MRI);
253dbb6d01dSPetar Avramovic     addUseDef(MI->getOperand(3).getReg(), MRI);
254dbb6d01dSPetar Avramovic   }
25575e43a60SPetar Avramovic 
25675e43a60SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
25775e43a60SPetar Avramovic     addDefUses(MI->getOperand(0).getReg(), MRI);
25892c80529SPetar Avramovic 
25992c80529SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
26092c80529SPetar Avramovic     addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
26192c80529SPetar Avramovic 
26292c80529SPetar Avramovic   if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
26392c80529SPetar Avramovic       addDefUses(MI->getOperand(0).getReg(), MRI);
264ec575f6eSPetar Avramovic }
265ec575f6eSPetar Avramovic 
266e3bb0a72SPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visit(
26792c80529SPetar Avramovic     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
26892c80529SPetar Avramovic     InstType &AmbiguousTy) {
269ec575f6eSPetar Avramovic   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
270e3bb0a72SPetar Avramovic   if (wasVisited(MI))
271e3bb0a72SPetar Avramovic     return true; // InstType has already been determined for MI.
272ec575f6eSPetar Avramovic 
273ec575f6eSPetar Avramovic   startVisit(MI);
274ec575f6eSPetar Avramovic   AmbiguousRegDefUseContainer DefUseContainer(MI);
275ec575f6eSPetar Avramovic 
2765171d152SPetar Avramovic   if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
2775171d152SPetar Avramovic     setTypes(MI, Integer);
2785171d152SPetar Avramovic     return true;
2795171d152SPetar Avramovic   }
2805171d152SPetar Avramovic 
28192c80529SPetar Avramovic   if (AmbiguousTy == InstType::Ambiguous &&
28292c80529SPetar Avramovic       (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
28392c80529SPetar Avramovic        MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
28492c80529SPetar Avramovic     AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
28592c80529SPetar Avramovic 
286aa699b20SPetar Avramovic   // Visit instructions where MI's DEF operands are USED.
28792c80529SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
288aa699b20SPetar Avramovic     return true;
289aa699b20SPetar Avramovic 
290ec575f6eSPetar Avramovic   // Visit instructions that DEFINE MI's USE operands.
29192c80529SPetar Avramovic   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
292ec575f6eSPetar Avramovic     return true;
293ec575f6eSPetar Avramovic 
294e3bb0a72SPetar Avramovic   // All MI's adjacent instructions, are ambiguous.
295e3bb0a72SPetar Avramovic   if (!WaitingForTypeOfMI) {
296e3bb0a72SPetar Avramovic     // This is chain of ambiguous instructions.
29792c80529SPetar Avramovic     setTypes(MI, AmbiguousTy);
298e3bb0a72SPetar Avramovic     return true;
299e3bb0a72SPetar Avramovic   }
300e3bb0a72SPetar Avramovic   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
301e3bb0a72SPetar Avramovic   // instructions or has no other adjacent instructions. Anyway InstType could
302e3bb0a72SPetar Avramovic   // not be determined. There could be unexplored path from some of
303e3bb0a72SPetar Avramovic   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
304e3bb0a72SPetar Avramovic   // mapping available.
305e3bb0a72SPetar Avramovic   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
306e3bb0a72SPetar Avramovic   // this way when WaitingForTypeOfMI figures out its InstType same InstType
307e3bb0a72SPetar Avramovic   // will be assigned to all instructions in this branch.
308e3bb0a72SPetar Avramovic   addToWaitingQueue(WaitingForTypeOfMI, MI);
309ec575f6eSPetar Avramovic   return false;
310ec575f6eSPetar Avramovic }
311ec575f6eSPetar Avramovic 
312ec575f6eSPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
313aa699b20SPetar Avramovic     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
31492c80529SPetar Avramovic     bool isDefUse, InstType &AmbiguousTy) {
315ec575f6eSPetar Avramovic   while (!AdjacentInstrs.empty()) {
316ec575f6eSPetar Avramovic     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
317ec575f6eSPetar Avramovic 
318aa699b20SPetar Avramovic     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
319aa699b20SPetar Avramovic                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
320ec575f6eSPetar Avramovic       setTypes(MI, InstType::FloatingPoint);
321ec575f6eSPetar Avramovic       return true;
322ec575f6eSPetar Avramovic     }
323ec575f6eSPetar Avramovic 
324ec575f6eSPetar Avramovic     // Determine InstType from register bank of phys register that is
325aa699b20SPetar Avramovic     // 'isDefUse ? def : use' of this copy.
326ec575f6eSPetar Avramovic     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
327aa699b20SPetar Avramovic       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
328ec575f6eSPetar Avramovic       return true;
329ec575f6eSPetar Avramovic     }
330ec575f6eSPetar Avramovic 
33192c80529SPetar Avramovic     // Defaults to integer instruction. Small registers in G_MERGE (uses) and
33292c80529SPetar Avramovic     // G_UNMERGE (defs) will always be gprb.
33392c80529SPetar Avramovic     if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
33492c80529SPetar Avramovic         (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
33592c80529SPetar Avramovic         !isAmbiguous(AdjMI->getOpcode())) {
336ec575f6eSPetar Avramovic       setTypes(MI, InstType::Integer);
337ec575f6eSPetar Avramovic       return true;
338ec575f6eSPetar Avramovic     }
339e3bb0a72SPetar Avramovic 
340e3bb0a72SPetar Avramovic     // When AdjMI was visited first, MI has to continue to explore remaining
341e3bb0a72SPetar Avramovic     // adjacent instructions and determine InstType without visiting AdjMI.
342e3bb0a72SPetar Avramovic     if (!wasVisited(AdjMI) ||
343e3bb0a72SPetar Avramovic         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
34492c80529SPetar Avramovic       if (visit(AdjMI, MI, AmbiguousTy)) {
345e3bb0a72SPetar Avramovic         // InstType is successfully determined and is same as for AdjMI.
346e3bb0a72SPetar Avramovic         setTypes(MI, getRecordedTypeForInstr(AdjMI));
347e3bb0a72SPetar Avramovic         return true;
348e3bb0a72SPetar Avramovic       }
349e3bb0a72SPetar Avramovic     }
350e3bb0a72SPetar Avramovic   }
351ec575f6eSPetar Avramovic   return false;
352ec575f6eSPetar Avramovic }
353ec575f6eSPetar Avramovic 
354ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
355ec575f6eSPetar Avramovic                                                    InstType InstTy) {
356ec575f6eSPetar Avramovic   changeRecordedTypeForInstr(MI, InstTy);
357e3bb0a72SPetar Avramovic   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
358e3bb0a72SPetar Avramovic     setTypes(WaitingInstr, InstTy);
359e3bb0a72SPetar Avramovic   }
360ec575f6eSPetar Avramovic }
361ec575f6eSPetar Avramovic 
362ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
363ec575f6eSPetar Avramovic     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
3642bea69bfSDaniel Sanders   assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
365ec575f6eSPetar Avramovic          "Copies of non physical registers should not be considered here.\n");
366ec575f6eSPetar Avramovic 
367ec575f6eSPetar Avramovic   const MachineFunction &MF = *CopyInst->getMF();
368ec575f6eSPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
369ec575f6eSPetar Avramovic   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
370ec575f6eSPetar Avramovic   const RegisterBankInfo &RBI =
371ec575f6eSPetar Avramovic       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
372ec575f6eSPetar Avramovic   const RegisterBank *Bank =
373ec575f6eSPetar Avramovic       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
374ec575f6eSPetar Avramovic 
375ec575f6eSPetar Avramovic   if (Bank == &Mips::FPRBRegBank)
376ec575f6eSPetar Avramovic     setTypes(MI, InstType::FloatingPoint);
377ec575f6eSPetar Avramovic   else if (Bank == &Mips::GPRBRegBank)
378ec575f6eSPetar Avramovic     setTypes(MI, InstType::Integer);
379ec575f6eSPetar Avramovic   else
380ec575f6eSPetar Avramovic     llvm_unreachable("Unsupported register bank.\n");
381ec575f6eSPetar Avramovic }
382ec575f6eSPetar Avramovic 
383ec575f6eSPetar Avramovic MipsRegisterBankInfo::InstType
384ec575f6eSPetar Avramovic MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
38592c80529SPetar Avramovic   InstType DefaultAmbiguousType = InstType::Ambiguous;
38692c80529SPetar Avramovic   visit(MI, nullptr, DefaultAmbiguousType);
387ec575f6eSPetar Avramovic   return getRecordedTypeForInstr(MI);
388ec575f6eSPetar Avramovic }
389ec575f6eSPetar Avramovic 
390ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
391ec575f6eSPetar Avramovic     llvm::StringRef FunctionName) {
392ec575f6eSPetar Avramovic   if (MFName != FunctionName) {
393adcd0268SBenjamin Kramer     MFName = std::string(FunctionName);
394e3bb0a72SPetar Avramovic     WaitingQueues.clear();
395ec575f6eSPetar Avramovic     Types.clear();
396ec575f6eSPetar Avramovic   }
397ec575f6eSPetar Avramovic }
398ec575f6eSPetar Avramovic 
399599591f3SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
400599591f3SPetar Avramovic getMSAMapping(const MachineFunction &MF) {
401599591f3SPetar Avramovic   assert(static_cast<const MipsSubtarget &>(MF.getSubtarget()).hasMSA() &&
402599591f3SPetar Avramovic          "MSA mapping not available on target without MSA.");
403599591f3SPetar Avramovic   return &Mips::ValueMappings[Mips::MSAIdx];
404599591f3SPetar Avramovic }
405599591f3SPetar Avramovic 
406f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
407f7c213c9SPetar Avramovic   return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
408f7c213c9SPetar Avramovic                     : &Mips::ValueMappings[Mips::DPRIdx];
409f7c213c9SPetar Avramovic }
410f7c213c9SPetar Avramovic 
411f7c213c9SPetar Avramovic static const unsigned CustomMappingID = 1;
412f7c213c9SPetar Avramovic 
413f7c213c9SPetar Avramovic // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
414f7c213c9SPetar Avramovic // will be split into two 32 bit registers in gprb.
415f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
416f7c213c9SPetar Avramovic getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
417f7c213c9SPetar Avramovic   if (Size == 32)
418f7c213c9SPetar Avramovic     return &Mips::ValueMappings[Mips::GPRIdx];
419f7c213c9SPetar Avramovic 
420f7c213c9SPetar Avramovic   MappingID = CustomMappingID;
421f7c213c9SPetar Avramovic   return &Mips::ValueMappings[Mips::DPRIdx];
422f7c213c9SPetar Avramovic }
423f7c213c9SPetar Avramovic 
424366857a2SPetar Jovanovic const RegisterBankInfo::InstructionMapping &
425366857a2SPetar Jovanovic MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
426366857a2SPetar Jovanovic 
427ec575f6eSPetar Avramovic   static TypeInfoForMF TI;
428ec575f6eSPetar Avramovic 
429ec575f6eSPetar Avramovic   // Reset TI internal data when MF changes.
430ec575f6eSPetar Avramovic   TI.cleanupIfNewFunction(MI.getMF()->getName());
431ec575f6eSPetar Avramovic 
432366857a2SPetar Jovanovic   unsigned Opc = MI.getOpcode();
4331af05df3SPetar Avramovic   const MachineFunction &MF = *MI.getParent()->getParent();
4341af05df3SPetar Avramovic   const MachineRegisterInfo &MRI = MF.getRegInfo();
435366857a2SPetar Jovanovic 
436be20e361SPetar Avramovic   if (MI.getOpcode() != TargetOpcode::G_PHI) {
437be20e361SPetar Avramovic     const RegisterBankInfo::InstructionMapping &Mapping =
438be20e361SPetar Avramovic         getInstrMappingImpl(MI);
439366857a2SPetar Jovanovic     if (Mapping.isValid())
440366857a2SPetar Jovanovic       return Mapping;
441be20e361SPetar Avramovic   }
442366857a2SPetar Jovanovic 
443366857a2SPetar Jovanovic   using namespace TargetOpcode;
444366857a2SPetar Jovanovic 
445366857a2SPetar Jovanovic   unsigned NumOperands = MI.getNumOperands();
446366857a2SPetar Jovanovic   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
447ec575f6eSPetar Avramovic   unsigned MappingID = DefaultMappingID;
448f7c213c9SPetar Avramovic 
449f7c213c9SPetar Avramovic   // Check if LLT sizes match sizes of available register banks.
450f7c213c9SPetar Avramovic   for (const MachineOperand &Op : MI.operands()) {
451f7c213c9SPetar Avramovic     if (Op.isReg()) {
452f7c213c9SPetar Avramovic       LLT RegTy = MRI.getType(Op.getReg());
453f7c213c9SPetar Avramovic 
454f7c213c9SPetar Avramovic       if (RegTy.isScalar() &&
455f7c213c9SPetar Avramovic           (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
456f7c213c9SPetar Avramovic         return getInvalidInstructionMapping();
457599591f3SPetar Avramovic 
458599591f3SPetar Avramovic       if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
459599591f3SPetar Avramovic         return getInvalidInstructionMapping();
460f7c213c9SPetar Avramovic     }
461f7c213c9SPetar Avramovic   }
462f7c213c9SPetar Avramovic 
463f7c213c9SPetar Avramovic   const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
464f7c213c9SPetar Avramovic   unsigned Op0Size = Op0Ty.getSizeInBits();
465f7c213c9SPetar Avramovic   InstType InstTy = InstType::Integer;
466366857a2SPetar Jovanovic 
467366857a2SPetar Jovanovic   switch (Opc) {
4687cecadb9SPetar Avramovic   case G_TRUNC:
469a48285a1SPetar Avramovic   case G_UMULH:
47079df8596SPetar Avramovic   case G_ZEXTLOAD:
47179df8596SPetar Avramovic   case G_SEXTLOAD:
472e74c5b96SDaniel Sanders   case G_PTR_ADD:
473b1fc6f61SPetar Avramovic   case G_INTTOPTR:
474b1fc6f61SPetar Avramovic   case G_PTRTOINT:
4753b953c37SPetar Jovanovic   case G_AND:
4763b953c37SPetar Jovanovic   case G_OR:
4773b953c37SPetar Jovanovic   case G_XOR:
4783b953c37SPetar Jovanovic   case G_SHL:
4793b953c37SPetar Jovanovic   case G_ASHR:
4803b953c37SPetar Jovanovic   case G_LSHR:
481ff6ac1ebSPetar Avramovic   case G_BRINDIRECT:
482c063b0b0SPetar Avramovic   case G_VASTART:
48394a24e7aSPetar Avramovic   case G_BSWAP:
4842b66d32fSPetar Avramovic   case G_CTLZ:
485366857a2SPetar Jovanovic     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
486366857a2SPetar Jovanovic     break;
487e4af9de3SPetar Avramovic   case G_ADD:
488c46d24f5SPetar Avramovic   case G_SUB:
489d1815dacSPetar Avramovic   case G_MUL:
4901d7f79c0SPetar Avramovic   case G_SDIV:
4911d7f79c0SPetar Avramovic   case G_SREM:
4921d7f79c0SPetar Avramovic   case G_UDIV:
4931d7f79c0SPetar Avramovic   case G_UREM:
494e4af9de3SPetar Avramovic     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
495e4af9de3SPetar Avramovic     if (Op0Size == 128)
496e4af9de3SPetar Avramovic       OperandsMapping = getMSAMapping(MF);
497e4af9de3SPetar Avramovic     break;
498f7c213c9SPetar Avramovic   case G_STORE:
49992c80529SPetar Avramovic   case G_LOAD: {
500599591f3SPetar Avramovic     if (Op0Size == 128) {
501599591f3SPetar Avramovic       OperandsMapping = getOperandsMapping(
502599591f3SPetar Avramovic           {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
503599591f3SPetar Avramovic       break;
504599591f3SPetar Avramovic     }
505599591f3SPetar Avramovic 
506f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
507aa699b20SPetar Avramovic       InstTy = TI.determineInstType(&MI);
508aa699b20SPetar Avramovic 
50992c80529SPetar Avramovic     if (isFloatingPoint_32or64(InstTy, Op0Size) ||
51092c80529SPetar Avramovic         isAmbiguous_64(InstTy, Op0Size)) {
511f7c213c9SPetar Avramovic       OperandsMapping = getOperandsMapping(
512f7c213c9SPetar Avramovic           {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
51392c80529SPetar Avramovic     } else {
51492c80529SPetar Avramovic       assert((isInteger_32(InstTy, Op0Size) ||
51592c80529SPetar Avramovic               isAmbiguous_32(InstTy, Op0Size) ||
51692c80529SPetar Avramovic               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
51792c80529SPetar Avramovic              "Unexpected Inst type");
518aa699b20SPetar Avramovic       OperandsMapping =
519f7c213c9SPetar Avramovic           getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
520aa699b20SPetar Avramovic                               &Mips::ValueMappings[Mips::GPRIdx]});
52192c80529SPetar Avramovic     }
522aa699b20SPetar Avramovic 
523aa699b20SPetar Avramovic     break;
52492c80529SPetar Avramovic   }
52592c80529SPetar Avramovic   case G_PHI: {
526f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
527ec575f6eSPetar Avramovic       InstTy = TI.determineInstType(&MI);
528be20e361SPetar Avramovic 
529be20e361SPetar Avramovic     // PHI is copylike and should have one regbank in mapping for def register.
53092c80529SPetar Avramovic     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
531be20e361SPetar Avramovic       OperandsMapping =
532be20e361SPetar Avramovic           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
53392c80529SPetar Avramovic       TI.clearTypeInfoData(&MI);
534be20e361SPetar Avramovic       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
535be20e361SPetar Avramovic                                    /*NumOperands=*/1);
536be20e361SPetar Avramovic     }
53792c80529SPetar Avramovic     assert((isInteger_32(InstTy, Op0Size) ||
53892c80529SPetar Avramovic             isFloatingPoint_32or64(InstTy, Op0Size) ||
53992c80529SPetar Avramovic             isAmbiguous_32or64(InstTy, Op0Size)) &&
54092c80529SPetar Avramovic            "Unexpected Inst type");
541be20e361SPetar Avramovic     // Use default handling for PHI, i.e. set reg bank of def operand to match
542be20e361SPetar Avramovic     // register banks of use operands.
543f7c213c9SPetar Avramovic     return getInstrMappingImpl(MI);
54492c80529SPetar Avramovic   }
545dbb6d01dSPetar Avramovic   case G_SELECT: {
546f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
547dbb6d01dSPetar Avramovic       InstTy = TI.determineInstType(&MI);
54892c80529SPetar Avramovic     if (isFloatingPoint_32or64(InstTy, Op0Size) ||
54992c80529SPetar Avramovic         isAmbiguous_64(InstTy, Op0Size)) {
550f7c213c9SPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
551dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
552dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
553dbb6d01dSPetar Avramovic       break;
554f7c213c9SPetar Avramovic     } else {
55592c80529SPetar Avramovic       assert((isInteger_32(InstTy, Op0Size) ||
55692c80529SPetar Avramovic               isAmbiguous_32(InstTy, Op0Size) ||
55792c80529SPetar Avramovic               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
55892c80529SPetar Avramovic              "Unexpected Inst type");
559dbb6d01dSPetar Avramovic       const RegisterBankInfo::ValueMapping *Bank =
560f7c213c9SPetar Avramovic           getGprbOrCustomMapping(Op0Size, MappingID);
561dbb6d01dSPetar Avramovic       OperandsMapping = getOperandsMapping(
562dbb6d01dSPetar Avramovic           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
563dbb6d01dSPetar Avramovic     }
564dbb6d01dSPetar Avramovic     break;
565dbb6d01dSPetar Avramovic   }
56692c80529SPetar Avramovic   case G_IMPLICIT_DEF: {
567f7c213c9SPetar Avramovic     if (!Op0Ty.isPointer())
56875e43a60SPetar Avramovic       InstTy = TI.determineInstType(&MI);
56975e43a60SPetar Avramovic 
57092c80529SPetar Avramovic     if (isFloatingPoint_32or64(InstTy, Op0Size))
571f7c213c9SPetar Avramovic       OperandsMapping = getFprbMapping(Op0Size);
57292c80529SPetar Avramovic     else {
57392c80529SPetar Avramovic       assert((isInteger_32(InstTy, Op0Size) ||
57492c80529SPetar Avramovic               isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
57592c80529SPetar Avramovic              "Unexpected Inst type");
576f7c213c9SPetar Avramovic       OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
57792c80529SPetar Avramovic     }
57892c80529SPetar Avramovic   } break;
57992c80529SPetar Avramovic   case G_UNMERGE_VALUES: {
58092c80529SPetar Avramovic     assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
58192c80529SPetar Avramovic     unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
58292c80529SPetar Avramovic     InstTy = TI.determineInstType(&MI);
58392c80529SPetar Avramovic     assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
58492c80529SPetar Avramovic             isFloatingPoint_64(InstTy, Op3Size)) &&
58592c80529SPetar Avramovic            "Unexpected Inst type");
586aa699b20SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
587aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
588aa699b20SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
58992c80529SPetar Avramovic     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
590aa699b20SPetar Avramovic       MappingID = CustomMappingID;
591aa699b20SPetar Avramovic     break;
59292c80529SPetar Avramovic   }
59392c80529SPetar Avramovic   case G_MERGE_VALUES: {
59492c80529SPetar Avramovic     InstTy = TI.determineInstType(&MI);
59592c80529SPetar Avramovic     assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
59692c80529SPetar Avramovic             isFloatingPoint_64(InstTy, Op0Size)) &&
59792c80529SPetar Avramovic            "Unexpected Inst type");
598ec575f6eSPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
599ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx],
600ec575f6eSPetar Avramovic                                           &Mips::ValueMappings[Mips::GPRIdx]});
60192c80529SPetar Avramovic     if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
602ec575f6eSPetar Avramovic       MappingID = CustomMappingID;
603ec575f6eSPetar Avramovic     break;
60492c80529SPetar Avramovic   }
605afa3afa3SPetar Avramovic   case G_FADD:
606afa3afa3SPetar Avramovic   case G_FSUB:
607afa3afa3SPetar Avramovic   case G_FMUL:
6080a1fd355SPetar Avramovic   case G_FDIV:
609e3b49df5SPetar Avramovic   case G_FABS:
610417dd678SPetar Avramovic   case G_FSQRT:
611f7c213c9SPetar Avramovic     OperandsMapping = getFprbMapping(Op0Size);
612914ce664SPetar Avramovic     if (Op0Size == 128)
613914ce664SPetar Avramovic       OperandsMapping = getMSAMapping(MF);
614afa3afa3SPetar Avramovic     break;
615f7c213c9SPetar Avramovic   case G_FCONSTANT:
616f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
6171af05df3SPetar Avramovic     break;
61822e99c43SPetar Avramovic   case G_FCMP: {
619f7c213c9SPetar Avramovic     unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
62022e99c43SPetar Avramovic     OperandsMapping =
62122e99c43SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
622f7c213c9SPetar Avramovic                             getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
62322e99c43SPetar Avramovic     break;
62422e99c43SPetar Avramovic   }
625a7d00064SPetar Avramovic   case G_FPEXT:
626a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
627a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::SPRIdx]});
628a7d00064SPetar Avramovic     break;
629a7d00064SPetar Avramovic   case G_FPTRUNC:
630a7d00064SPetar Avramovic     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
631a7d00064SPetar Avramovic                                           &Mips::ValueMappings[Mips::DPRIdx]});
632a7d00064SPetar Avramovic     break;
6334b4dae1cSPetar Avramovic   case G_FPTOSI: {
634f7c213c9SPetar Avramovic     assert((Op0Size == 32) && "Unsupported integer size");
6354b4dae1cSPetar Avramovic     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
636f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping(
637f7c213c9SPetar Avramovic         {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
638f7c213c9SPetar Avramovic     break;
639f7c213c9SPetar Avramovic   }
640f7c213c9SPetar Avramovic   case G_SITOFP:
641f7c213c9SPetar Avramovic     assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
642ddd056c9SFangrui Song            "Unsupported integer size");
643f7c213c9SPetar Avramovic     OperandsMapping = getOperandsMapping(
644f7c213c9SPetar Avramovic         {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
6454b4dae1cSPetar Avramovic     break;
646021e4c82SPetar Jovanovic   case G_CONSTANT:
647021e4c82SPetar Jovanovic   case G_FRAME_INDEX:
64864c10ba8SPetar Jovanovic   case G_GLOBAL_VALUE:
649caef9306SPetar Avramovic   case G_JUMP_TABLE:
6505d9b8eedSPetar Avramovic   case G_BRCOND:
651021e4c82SPetar Jovanovic     OperandsMapping =
652021e4c82SPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
653021e4c82SPetar Jovanovic     break;
654caef9306SPetar Avramovic   case G_BRJT:
655caef9306SPetar Avramovic     OperandsMapping =
656caef9306SPetar Avramovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
657caef9306SPetar Avramovic                             &Mips::ValueMappings[Mips::GPRIdx]});
658caef9306SPetar Avramovic     break;
659ce4dd0aeSPetar Jovanovic   case G_ICMP:
660ce4dd0aeSPetar Jovanovic     OperandsMapping =
661ce4dd0aeSPetar Jovanovic         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
662ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx],
663ce4dd0aeSPetar Jovanovic                             &Mips::ValueMappings[Mips::GPRIdx]});
664ce4dd0aeSPetar Jovanovic     break;
665366857a2SPetar Jovanovic   default:
666366857a2SPetar Jovanovic     return getInvalidInstructionMapping();
667366857a2SPetar Jovanovic   }
668366857a2SPetar Jovanovic 
66992c80529SPetar Avramovic   if (MappingID == CustomMappingID)
67092c80529SPetar Avramovic     TI.clearTypeInfoData(&MI);
671ec575f6eSPetar Avramovic   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
672366857a2SPetar Jovanovic                                NumOperands);
673366857a2SPetar Jovanovic }
674ec575f6eSPetar Avramovic 
675ec575f6eSPetar Avramovic using InstListTy = GISelWorkList<4>;
676ec575f6eSPetar Avramovic namespace {
677ec575f6eSPetar Avramovic class InstManager : public GISelChangeObserver {
678ec575f6eSPetar Avramovic   InstListTy &InstList;
679ec575f6eSPetar Avramovic 
680ec575f6eSPetar Avramovic public:
681ec575f6eSPetar Avramovic   InstManager(InstListTy &Insts) : InstList(Insts) {}
682ec575f6eSPetar Avramovic 
683ec575f6eSPetar Avramovic   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
684ec575f6eSPetar Avramovic   void erasingInstr(MachineInstr &MI) override {}
685ec575f6eSPetar Avramovic   void changingInstr(MachineInstr &MI) override {}
686ec575f6eSPetar Avramovic   void changedInstr(MachineInstr &MI) override {}
687ec575f6eSPetar Avramovic };
688ec575f6eSPetar Avramovic } // end anonymous namespace
689ec575f6eSPetar Avramovic 
690f7c213c9SPetar Avramovic void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
691f7c213c9SPetar Avramovic                                       MachineRegisterInfo &MRI) const {
692f7c213c9SPetar Avramovic   Register Dest = MI.getOperand(0).getReg();
693f7c213c9SPetar Avramovic   switch (MI.getOpcode()) {
694f7c213c9SPetar Avramovic   case TargetOpcode::G_STORE:
695f7c213c9SPetar Avramovic     // No def operands, skip this instruction.
696f7c213c9SPetar Avramovic     break;
697f7c213c9SPetar Avramovic   case TargetOpcode::G_CONSTANT:
698f7c213c9SPetar Avramovic   case TargetOpcode::G_LOAD:
699f7c213c9SPetar Avramovic   case TargetOpcode::G_SELECT:
700f7c213c9SPetar Avramovic   case TargetOpcode::G_PHI:
701f7c213c9SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF: {
702f7c213c9SPetar Avramovic     assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
703f7c213c9SPetar Avramovic     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
704f7c213c9SPetar Avramovic     break;
705f7c213c9SPetar Avramovic   }
706e74c5b96SDaniel Sanders   case TargetOpcode::G_PTR_ADD: {
707f7c213c9SPetar Avramovic     assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
708f7c213c9SPetar Avramovic     MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
709f7c213c9SPetar Avramovic     break;
710f7c213c9SPetar Avramovic   }
711f7c213c9SPetar Avramovic   default:
712f7c213c9SPetar Avramovic     llvm_unreachable("Unexpected opcode.");
713f7c213c9SPetar Avramovic   }
714f7c213c9SPetar Avramovic }
715f7c213c9SPetar Avramovic 
716f7c213c9SPetar Avramovic static void
717f7c213c9SPetar Avramovic combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
7185ec0f051SAmara Emerson                             GUnmerge &MI, GISelChangeObserver &Observer) {
7198731799fSRoman Tereshin   SmallVector<Register, 4> UpdatedDefs;
720f7c213c9SPetar Avramovic   SmallVector<MachineInstr *, 2> DeadInstrs;
7215ec0f051SAmara Emerson   ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
7225ec0f051SAmara Emerson                                       UpdatedDefs, Observer);
723f7c213c9SPetar Avramovic   for (MachineInstr *DeadMI : DeadInstrs)
724f7c213c9SPetar Avramovic     DeadMI->eraseFromParent();
725f7c213c9SPetar Avramovic }
726f7c213c9SPetar Avramovic 
727ec575f6eSPetar Avramovic void MipsRegisterBankInfo::applyMappingImpl(
728ec575f6eSPetar Avramovic     const OperandsMapper &OpdMapper) const {
729ec575f6eSPetar Avramovic   MachineInstr &MI = OpdMapper.getMI();
730ec575f6eSPetar Avramovic   InstListTy NewInstrs;
731ec575f6eSPetar Avramovic   MachineFunction *MF = MI.getMF();
732ec575f6eSPetar Avramovic   MachineRegisterInfo &MRI = OpdMapper.getMRI();
733f7c213c9SPetar Avramovic   const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
734ec575f6eSPetar Avramovic 
735ec575f6eSPetar Avramovic   InstManager NewInstrObserver(NewInstrs);
736d55d592aSMatt Arsenault   MachineIRBuilder B(MI, NewInstrObserver);
737d55d592aSMatt Arsenault   LegalizerHelper Helper(*MF, NewInstrObserver, B);
738f7c213c9SPetar Avramovic   LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
739ec575f6eSPetar Avramovic 
740ec575f6eSPetar Avramovic   switch (MI.getOpcode()) {
741aa699b20SPetar Avramovic   case TargetOpcode::G_LOAD:
742dbb6d01dSPetar Avramovic   case TargetOpcode::G_STORE:
743be20e361SPetar Avramovic   case TargetOpcode::G_PHI:
74475e43a60SPetar Avramovic   case TargetOpcode::G_SELECT:
74575e43a60SPetar Avramovic   case TargetOpcode::G_IMPLICIT_DEF: {
746ec575f6eSPetar Avramovic     Helper.narrowScalar(MI, 0, LLT::scalar(32));
747ec575f6eSPetar Avramovic     // Handle new instructions.
748ec575f6eSPetar Avramovic     while (!NewInstrs.empty()) {
749ec575f6eSPetar Avramovic       MachineInstr *NewMI = NewInstrs.pop_back_val();
750ec575f6eSPetar Avramovic       // This is new G_UNMERGE that was created during narrowScalar and will
751ec575f6eSPetar Avramovic       // not be considered for regbank selection. RegBankSelect for mips
752ec575f6eSPetar Avramovic       // visits/makes corresponding G_MERGE first. Combine them here.
7535ec0f051SAmara Emerson       if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
7545ec0f051SAmara Emerson         combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
755aa699b20SPetar Avramovic       // This G_MERGE will be combined away when its corresponding G_UNMERGE
756aa699b20SPetar Avramovic       // gets regBankSelected.
757aa699b20SPetar Avramovic       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
758aa699b20SPetar Avramovic         continue;
759aa699b20SPetar Avramovic       else
760f7c213c9SPetar Avramovic         // Manually set register banks for def operands to 32 bit gprb.
761f7c213c9SPetar Avramovic         setRegBank(*NewMI, MRI);
762ec575f6eSPetar Avramovic     }
763ec575f6eSPetar Avramovic     return;
764ec575f6eSPetar Avramovic   }
765f7c213c9SPetar Avramovic   case TargetOpcode::G_UNMERGE_VALUES:
7665ec0f051SAmara Emerson     combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
7675ec0f051SAmara Emerson                                 NewInstrObserver);
768aa699b20SPetar Avramovic     return;
769ec575f6eSPetar Avramovic   default:
770ec575f6eSPetar Avramovic     break;
771ec575f6eSPetar Avramovic   }
772ec575f6eSPetar Avramovic 
773ec575f6eSPetar Avramovic   return applyDefaultMapping(OpdMapper);
774ec575f6eSPetar Avramovic }
775