xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric /// \file
9*0b57cec5SDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for Mips.
10*0b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "MipsRegisterBankInfo.h"
14*0b57cec5SDimitry Andric #include "MipsInstrInfo.h"
15*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
16*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric #define GET_TARGET_REGBANK_IMPL
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric #include "MipsGenRegisterBank.inc"
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric namespace llvm {
25*0b57cec5SDimitry Andric namespace Mips {
26*0b57cec5SDimitry Andric enum PartialMappingIdx {
27*0b57cec5SDimitry Andric   PMI_GPR,
28*0b57cec5SDimitry Andric   PMI_SPR,
29*0b57cec5SDimitry Andric   PMI_DPR,
30*0b57cec5SDimitry Andric   PMI_Min = PMI_GPR,
31*0b57cec5SDimitry Andric };
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{
34*0b57cec5SDimitry Andric     {0, 32, GPRBRegBank},
35*0b57cec5SDimitry Andric     {0, 32, FPRBRegBank},
36*0b57cec5SDimitry Andric     {0, 64, FPRBRegBank}
37*0b57cec5SDimitry Andric };
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric enum ValueMappingIdx {
40*0b57cec5SDimitry Andric     InvalidIdx = 0,
41*0b57cec5SDimitry Andric     GPRIdx = 1,
42*0b57cec5SDimitry Andric     SPRIdx = 4,
43*0b57cec5SDimitry Andric     DPRIdx = 7
44*0b57cec5SDimitry Andric };
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = {
47*0b57cec5SDimitry Andric     // invalid
48*0b57cec5SDimitry Andric     {nullptr, 0},
49*0b57cec5SDimitry Andric     // up to 3 operands in GPRs
50*0b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
51*0b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
52*0b57cec5SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
53*0b57cec5SDimitry Andric     // up to 3 ops operands FPRs - single precission
54*0b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
55*0b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
56*0b57cec5SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
57*0b57cec5SDimitry Andric     // up to 3 ops operands FPRs - double precission
58*0b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
59*0b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
60*0b57cec5SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1}
61*0b57cec5SDimitry Andric };
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric } // end namespace Mips
64*0b57cec5SDimitry Andric } // end namespace llvm
65*0b57cec5SDimitry Andric 
66*0b57cec5SDimitry Andric using namespace llvm;
67*0b57cec5SDimitry Andric 
68*0b57cec5SDimitry Andric MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
69*0b57cec5SDimitry Andric     : MipsGenRegisterBankInfo() {}
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
72*0b57cec5SDimitry Andric     const TargetRegisterClass &RC) const {
73*0b57cec5SDimitry Andric   using namespace Mips;
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   switch (RC.getID()) {
76*0b57cec5SDimitry Andric   case Mips::GPR32RegClassID:
77*0b57cec5SDimitry Andric   case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
78*0b57cec5SDimitry Andric   case Mips::GPRMM16MovePPairFirstRegClassID:
79*0b57cec5SDimitry Andric   case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
80*0b57cec5SDimitry Andric   case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
81*0b57cec5SDimitry Andric   case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
82*0b57cec5SDimitry Andric   case Mips::SP32RegClassID:
83*0b57cec5SDimitry Andric   case Mips::GP32RegClassID:
84*0b57cec5SDimitry Andric     return getRegBank(Mips::GPRBRegBankID);
85*0b57cec5SDimitry Andric   case Mips::FGRCCRegClassID:
86*0b57cec5SDimitry Andric   case Mips::FGR32RegClassID:
87*0b57cec5SDimitry Andric   case Mips::FGR64RegClassID:
88*0b57cec5SDimitry Andric   case Mips::AFGR64RegClassID:
89*0b57cec5SDimitry Andric     return getRegBank(Mips::FPRBRegBankID);
90*0b57cec5SDimitry Andric   default:
91*0b57cec5SDimitry Andric     llvm_unreachable("Register class not supported");
92*0b57cec5SDimitry Andric   }
93*0b57cec5SDimitry Andric }
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric // Instructions where all register operands are floating point.
96*0b57cec5SDimitry Andric static bool isFloatingPointOpcode(unsigned Opc) {
97*0b57cec5SDimitry Andric   switch (Opc) {
98*0b57cec5SDimitry Andric   case TargetOpcode::G_FCONSTANT:
99*0b57cec5SDimitry Andric   case TargetOpcode::G_FADD:
100*0b57cec5SDimitry Andric   case TargetOpcode::G_FSUB:
101*0b57cec5SDimitry Andric   case TargetOpcode::G_FMUL:
102*0b57cec5SDimitry Andric   case TargetOpcode::G_FDIV:
103*0b57cec5SDimitry Andric   case TargetOpcode::G_FABS:
104*0b57cec5SDimitry Andric   case TargetOpcode::G_FSQRT:
105*0b57cec5SDimitry Andric   case TargetOpcode::G_FCEIL:
106*0b57cec5SDimitry Andric   case TargetOpcode::G_FFLOOR:
107*0b57cec5SDimitry Andric   case TargetOpcode::G_FPEXT:
108*0b57cec5SDimitry Andric   case TargetOpcode::G_FPTRUNC:
109*0b57cec5SDimitry Andric     return true;
110*0b57cec5SDimitry Andric   default:
111*0b57cec5SDimitry Andric     return false;
112*0b57cec5SDimitry Andric   }
113*0b57cec5SDimitry Andric }
114*0b57cec5SDimitry Andric 
115*0b57cec5SDimitry Andric // Instructions where use operands are floating point registers.
116*0b57cec5SDimitry Andric // Def operands are general purpose.
117*0b57cec5SDimitry Andric static bool isFloatingPointOpcodeUse(unsigned Opc) {
118*0b57cec5SDimitry Andric   switch (Opc) {
119*0b57cec5SDimitry Andric   case TargetOpcode::G_FPTOSI:
120*0b57cec5SDimitry Andric   case TargetOpcode::G_FPTOUI:
121*0b57cec5SDimitry Andric   case TargetOpcode::G_FCMP:
122*0b57cec5SDimitry Andric   case Mips::MFC1:
123*0b57cec5SDimitry Andric   case Mips::ExtractElementF64:
124*0b57cec5SDimitry Andric   case Mips::ExtractElementF64_64:
125*0b57cec5SDimitry Andric     return true;
126*0b57cec5SDimitry Andric   default:
127*0b57cec5SDimitry Andric     return isFloatingPointOpcode(Opc);
128*0b57cec5SDimitry Andric   }
129*0b57cec5SDimitry Andric }
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric // Instructions where def operands are floating point registers.
132*0b57cec5SDimitry Andric // Use operands are general purpose.
133*0b57cec5SDimitry Andric static bool isFloatingPointOpcodeDef(unsigned Opc) {
134*0b57cec5SDimitry Andric   switch (Opc) {
135*0b57cec5SDimitry Andric   case TargetOpcode::G_SITOFP:
136*0b57cec5SDimitry Andric   case TargetOpcode::G_UITOFP:
137*0b57cec5SDimitry Andric   case Mips::MTC1:
138*0b57cec5SDimitry Andric   case Mips::BuildPairF64:
139*0b57cec5SDimitry Andric   case Mips::BuildPairF64_64:
140*0b57cec5SDimitry Andric     return true;
141*0b57cec5SDimitry Andric   default:
142*0b57cec5SDimitry Andric     return isFloatingPointOpcode(Opc);
143*0b57cec5SDimitry Andric   }
144*0b57cec5SDimitry Andric }
145*0b57cec5SDimitry Andric 
146*0b57cec5SDimitry Andric static bool isAmbiguous(unsigned Opc) {
147*0b57cec5SDimitry Andric   switch (Opc) {
148*0b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
149*0b57cec5SDimitry Andric   case TargetOpcode::G_STORE:
150*0b57cec5SDimitry Andric   case TargetOpcode::G_PHI:
151*0b57cec5SDimitry Andric   case TargetOpcode::G_SELECT:
152*0b57cec5SDimitry Andric     return true;
153*0b57cec5SDimitry Andric   default:
154*0b57cec5SDimitry Andric     return false;
155*0b57cec5SDimitry Andric   }
156*0b57cec5SDimitry Andric }
157*0b57cec5SDimitry Andric 
158*0b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
159*0b57cec5SDimitry Andric     Register Reg, const MachineRegisterInfo &MRI) {
160*0b57cec5SDimitry Andric   assert(!MRI.getType(Reg).isPointer() &&
161*0b57cec5SDimitry Andric          "Pointers are gprb, they should not be considered as ambiguous.\n");
162*0b57cec5SDimitry Andric   for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
163*0b57cec5SDimitry Andric     MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
164*0b57cec5SDimitry Andric     // Copy with many uses.
165*0b57cec5SDimitry Andric     if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
166*0b57cec5SDimitry Andric         !TargetRegisterInfo::isPhysicalRegister(
167*0b57cec5SDimitry Andric             NonCopyInstr->getOperand(0).getReg()))
168*0b57cec5SDimitry Andric       addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
169*0b57cec5SDimitry Andric     else
170*0b57cec5SDimitry Andric       DefUses.push_back(skipCopiesOutgoing(&UseMI));
171*0b57cec5SDimitry Andric   }
172*0b57cec5SDimitry Andric }
173*0b57cec5SDimitry Andric 
174*0b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
175*0b57cec5SDimitry Andric     Register Reg, const MachineRegisterInfo &MRI) {
176*0b57cec5SDimitry Andric   assert(!MRI.getType(Reg).isPointer() &&
177*0b57cec5SDimitry Andric          "Pointers are gprb, they should not be considered as ambiguous.\n");
178*0b57cec5SDimitry Andric   MachineInstr *DefMI = MRI.getVRegDef(Reg);
179*0b57cec5SDimitry Andric   UseDefs.push_back(skipCopiesIncoming(DefMI));
180*0b57cec5SDimitry Andric }
181*0b57cec5SDimitry Andric 
182*0b57cec5SDimitry Andric MachineInstr *
183*0b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
184*0b57cec5SDimitry Andric     MachineInstr *MI) const {
185*0b57cec5SDimitry Andric   const MachineFunction &MF = *MI->getParent()->getParent();
186*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
187*0b57cec5SDimitry Andric   MachineInstr *Ret = MI;
188*0b57cec5SDimitry Andric   while (Ret->getOpcode() == TargetOpcode::COPY &&
189*0b57cec5SDimitry Andric          !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
190*0b57cec5SDimitry Andric          MRI.hasOneUse(Ret->getOperand(0).getReg())) {
191*0b57cec5SDimitry Andric     Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
192*0b57cec5SDimitry Andric   }
193*0b57cec5SDimitry Andric   return Ret;
194*0b57cec5SDimitry Andric }
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric MachineInstr *
197*0b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
198*0b57cec5SDimitry Andric     MachineInstr *MI) const {
199*0b57cec5SDimitry Andric   const MachineFunction &MF = *MI->getParent()->getParent();
200*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
201*0b57cec5SDimitry Andric   MachineInstr *Ret = MI;
202*0b57cec5SDimitry Andric   while (Ret->getOpcode() == TargetOpcode::COPY &&
203*0b57cec5SDimitry Andric          !TargetRegisterInfo::isPhysicalRegister(Ret->getOperand(1).getReg()))
204*0b57cec5SDimitry Andric     Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
205*0b57cec5SDimitry Andric   return Ret;
206*0b57cec5SDimitry Andric }
207*0b57cec5SDimitry Andric 
208*0b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
209*0b57cec5SDimitry Andric     const MachineInstr *MI) {
210*0b57cec5SDimitry Andric   assert(isAmbiguous(MI->getOpcode()) &&
211*0b57cec5SDimitry Andric          "Not implemented for non Ambiguous opcode.\n");
212*0b57cec5SDimitry Andric 
213*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
214*0b57cec5SDimitry Andric 
215*0b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_LOAD)
216*0b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_STORE)
219*0b57cec5SDimitry Andric     addUseDef(MI->getOperand(0).getReg(), MRI);
220*0b57cec5SDimitry Andric 
221*0b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_PHI) {
222*0b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
223*0b57cec5SDimitry Andric 
224*0b57cec5SDimitry Andric     for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
225*0b57cec5SDimitry Andric       addUseDef(MI->getOperand(i).getReg(), MRI);
226*0b57cec5SDimitry Andric   }
227*0b57cec5SDimitry Andric 
228*0b57cec5SDimitry Andric   if (MI->getOpcode() == TargetOpcode::G_SELECT) {
229*0b57cec5SDimitry Andric     addDefUses(MI->getOperand(0).getReg(), MRI);
230*0b57cec5SDimitry Andric 
231*0b57cec5SDimitry Andric     addUseDef(MI->getOperand(2).getReg(), MRI);
232*0b57cec5SDimitry Andric     addUseDef(MI->getOperand(3).getReg(), MRI);
233*0b57cec5SDimitry Andric   }
234*0b57cec5SDimitry Andric }
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visit(
237*0b57cec5SDimitry Andric     const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
238*0b57cec5SDimitry Andric   assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
239*0b57cec5SDimitry Andric   if (wasVisited(MI))
240*0b57cec5SDimitry Andric     return true; // InstType has already been determined for MI.
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric   startVisit(MI);
243*0b57cec5SDimitry Andric   AmbiguousRegDefUseContainer DefUseContainer(MI);
244*0b57cec5SDimitry Andric 
245*0b57cec5SDimitry Andric   // Visit instructions where MI's DEF operands are USED.
246*0b57cec5SDimitry Andric   if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
247*0b57cec5SDimitry Andric     return true;
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric   // Visit instructions that DEFINE MI's USE operands.
250*0b57cec5SDimitry Andric   if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
251*0b57cec5SDimitry Andric     return true;
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric   // All MI's adjacent instructions, are ambiguous.
254*0b57cec5SDimitry Andric   if (!WaitingForTypeOfMI) {
255*0b57cec5SDimitry Andric     // This is chain of ambiguous instructions.
256*0b57cec5SDimitry Andric     setTypes(MI, InstType::Ambiguous);
257*0b57cec5SDimitry Andric     return true;
258*0b57cec5SDimitry Andric   }
259*0b57cec5SDimitry Andric   // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
260*0b57cec5SDimitry Andric   // instructions or has no other adjacent instructions. Anyway InstType could
261*0b57cec5SDimitry Andric   // not be determined. There could be unexplored path from some of
262*0b57cec5SDimitry Andric   // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
263*0b57cec5SDimitry Andric   // mapping available.
264*0b57cec5SDimitry Andric   // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
265*0b57cec5SDimitry Andric   // this way when WaitingForTypeOfMI figures out its InstType same InstType
266*0b57cec5SDimitry Andric   // will be assigned to all instructions in this branch.
267*0b57cec5SDimitry Andric   addToWaitingQueue(WaitingForTypeOfMI, MI);
268*0b57cec5SDimitry Andric   return false;
269*0b57cec5SDimitry Andric }
270*0b57cec5SDimitry Andric 
271*0b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
272*0b57cec5SDimitry Andric     const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
273*0b57cec5SDimitry Andric     bool isDefUse) {
274*0b57cec5SDimitry Andric   while (!AdjacentInstrs.empty()) {
275*0b57cec5SDimitry Andric     MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric     if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
278*0b57cec5SDimitry Andric                  : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
279*0b57cec5SDimitry Andric       setTypes(MI, InstType::FloatingPoint);
280*0b57cec5SDimitry Andric       return true;
281*0b57cec5SDimitry Andric     }
282*0b57cec5SDimitry Andric 
283*0b57cec5SDimitry Andric     // Determine InstType from register bank of phys register that is
284*0b57cec5SDimitry Andric     // 'isDefUse ? def : use' of this copy.
285*0b57cec5SDimitry Andric     if (AdjMI->getOpcode() == TargetOpcode::COPY) {
286*0b57cec5SDimitry Andric       setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
287*0b57cec5SDimitry Andric       return true;
288*0b57cec5SDimitry Andric     }
289*0b57cec5SDimitry Andric 
290*0b57cec5SDimitry Andric     // Defaults to integer instruction. Includes G_MERGE_VALUES and
291*0b57cec5SDimitry Andric     // G_UNMERGE_VALUES.
292*0b57cec5SDimitry Andric     if (!isAmbiguous(AdjMI->getOpcode())) {
293*0b57cec5SDimitry Andric       setTypes(MI, InstType::Integer);
294*0b57cec5SDimitry Andric       return true;
295*0b57cec5SDimitry Andric     }
296*0b57cec5SDimitry Andric 
297*0b57cec5SDimitry Andric     // When AdjMI was visited first, MI has to continue to explore remaining
298*0b57cec5SDimitry Andric     // adjacent instructions and determine InstType without visiting AdjMI.
299*0b57cec5SDimitry Andric     if (!wasVisited(AdjMI) ||
300*0b57cec5SDimitry Andric         getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
301*0b57cec5SDimitry Andric       if (visit(AdjMI, MI)) {
302*0b57cec5SDimitry Andric         // InstType is successfully determined and is same as for AdjMI.
303*0b57cec5SDimitry Andric         setTypes(MI, getRecordedTypeForInstr(AdjMI));
304*0b57cec5SDimitry Andric         return true;
305*0b57cec5SDimitry Andric       }
306*0b57cec5SDimitry Andric     }
307*0b57cec5SDimitry Andric   }
308*0b57cec5SDimitry Andric   return false;
309*0b57cec5SDimitry Andric }
310*0b57cec5SDimitry Andric 
311*0b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
312*0b57cec5SDimitry Andric                                                    InstType InstTy) {
313*0b57cec5SDimitry Andric   changeRecordedTypeForInstr(MI, InstTy);
314*0b57cec5SDimitry Andric   for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
315*0b57cec5SDimitry Andric     setTypes(WaitingInstr, InstTy);
316*0b57cec5SDimitry Andric   }
317*0b57cec5SDimitry Andric }
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
320*0b57cec5SDimitry Andric     const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
321*0b57cec5SDimitry Andric   assert((TargetRegisterInfo::isPhysicalRegister(
322*0b57cec5SDimitry Andric              CopyInst->getOperand(Op).getReg())) &&
323*0b57cec5SDimitry Andric          "Copies of non physical registers should not be considered here.\n");
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric   const MachineFunction &MF = *CopyInst->getMF();
326*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
327*0b57cec5SDimitry Andric   const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
328*0b57cec5SDimitry Andric   const RegisterBankInfo &RBI =
329*0b57cec5SDimitry Andric       *CopyInst->getMF()->getSubtarget().getRegBankInfo();
330*0b57cec5SDimitry Andric   const RegisterBank *Bank =
331*0b57cec5SDimitry Andric       RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
332*0b57cec5SDimitry Andric 
333*0b57cec5SDimitry Andric   if (Bank == &Mips::FPRBRegBank)
334*0b57cec5SDimitry Andric     setTypes(MI, InstType::FloatingPoint);
335*0b57cec5SDimitry Andric   else if (Bank == &Mips::GPRBRegBank)
336*0b57cec5SDimitry Andric     setTypes(MI, InstType::Integer);
337*0b57cec5SDimitry Andric   else
338*0b57cec5SDimitry Andric     llvm_unreachable("Unsupported register bank.\n");
339*0b57cec5SDimitry Andric }
340*0b57cec5SDimitry Andric 
341*0b57cec5SDimitry Andric MipsRegisterBankInfo::InstType
342*0b57cec5SDimitry Andric MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
343*0b57cec5SDimitry Andric   visit(MI, nullptr);
344*0b57cec5SDimitry Andric   return getRecordedTypeForInstr(MI);
345*0b57cec5SDimitry Andric }
346*0b57cec5SDimitry Andric 
347*0b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
348*0b57cec5SDimitry Andric     llvm::StringRef FunctionName) {
349*0b57cec5SDimitry Andric   if (MFName != FunctionName) {
350*0b57cec5SDimitry Andric     MFName = FunctionName;
351*0b57cec5SDimitry Andric     WaitingQueues.clear();
352*0b57cec5SDimitry Andric     Types.clear();
353*0b57cec5SDimitry Andric   }
354*0b57cec5SDimitry Andric }
355*0b57cec5SDimitry Andric 
356*0b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &
357*0b57cec5SDimitry Andric MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
358*0b57cec5SDimitry Andric 
359*0b57cec5SDimitry Andric   static TypeInfoForMF TI;
360*0b57cec5SDimitry Andric 
361*0b57cec5SDimitry Andric   // Reset TI internal data when MF changes.
362*0b57cec5SDimitry Andric   TI.cleanupIfNewFunction(MI.getMF()->getName());
363*0b57cec5SDimitry Andric 
364*0b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
365*0b57cec5SDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
366*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
367*0b57cec5SDimitry Andric 
368*0b57cec5SDimitry Andric   if (MI.getOpcode() != TargetOpcode::G_PHI) {
369*0b57cec5SDimitry Andric     const RegisterBankInfo::InstructionMapping &Mapping =
370*0b57cec5SDimitry Andric         getInstrMappingImpl(MI);
371*0b57cec5SDimitry Andric     if (Mapping.isValid())
372*0b57cec5SDimitry Andric       return Mapping;
373*0b57cec5SDimitry Andric   }
374*0b57cec5SDimitry Andric 
375*0b57cec5SDimitry Andric   using namespace TargetOpcode;
376*0b57cec5SDimitry Andric 
377*0b57cec5SDimitry Andric   unsigned NumOperands = MI.getNumOperands();
378*0b57cec5SDimitry Andric   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
379*0b57cec5SDimitry Andric   unsigned MappingID = DefaultMappingID;
380*0b57cec5SDimitry Andric   const unsigned CustomMappingID = 1;
381*0b57cec5SDimitry Andric 
382*0b57cec5SDimitry Andric   switch (Opc) {
383*0b57cec5SDimitry Andric   case G_TRUNC:
384*0b57cec5SDimitry Andric   case G_ADD:
385*0b57cec5SDimitry Andric   case G_SUB:
386*0b57cec5SDimitry Andric   case G_MUL:
387*0b57cec5SDimitry Andric   case G_UMULH:
388*0b57cec5SDimitry Andric   case G_ZEXTLOAD:
389*0b57cec5SDimitry Andric   case G_SEXTLOAD:
390*0b57cec5SDimitry Andric   case G_GEP:
391*0b57cec5SDimitry Andric   case G_AND:
392*0b57cec5SDimitry Andric   case G_OR:
393*0b57cec5SDimitry Andric   case G_XOR:
394*0b57cec5SDimitry Andric   case G_SHL:
395*0b57cec5SDimitry Andric   case G_ASHR:
396*0b57cec5SDimitry Andric   case G_LSHR:
397*0b57cec5SDimitry Andric   case G_SDIV:
398*0b57cec5SDimitry Andric   case G_UDIV:
399*0b57cec5SDimitry Andric   case G_SREM:
400*0b57cec5SDimitry Andric   case G_UREM:
401*0b57cec5SDimitry Andric     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
402*0b57cec5SDimitry Andric     break;
403*0b57cec5SDimitry Andric   case G_LOAD: {
404*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
405*0b57cec5SDimitry Andric     InstType InstTy = InstType::Integer;
406*0b57cec5SDimitry Andric     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
407*0b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
408*0b57cec5SDimitry Andric     }
409*0b57cec5SDimitry Andric 
410*0b57cec5SDimitry Andric     if (InstTy == InstType::FloatingPoint ||
411*0b57cec5SDimitry Andric         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
412*0b57cec5SDimitry Andric       OperandsMapping =
413*0b57cec5SDimitry Andric           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
414*0b57cec5SDimitry Andric                                          : &Mips::ValueMappings[Mips::DPRIdx],
415*0b57cec5SDimitry Andric                               &Mips::ValueMappings[Mips::GPRIdx]});
416*0b57cec5SDimitry Andric       break;
417*0b57cec5SDimitry Andric     } else { // gprb
418*0b57cec5SDimitry Andric       OperandsMapping =
419*0b57cec5SDimitry Andric           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
420*0b57cec5SDimitry Andric                                          : &Mips::ValueMappings[Mips::DPRIdx],
421*0b57cec5SDimitry Andric                               &Mips::ValueMappings[Mips::GPRIdx]});
422*0b57cec5SDimitry Andric       if (Size == 64)
423*0b57cec5SDimitry Andric         MappingID = CustomMappingID;
424*0b57cec5SDimitry Andric     }
425*0b57cec5SDimitry Andric 
426*0b57cec5SDimitry Andric     break;
427*0b57cec5SDimitry Andric   }
428*0b57cec5SDimitry Andric   case G_STORE: {
429*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
430*0b57cec5SDimitry Andric     InstType InstTy = InstType::Integer;
431*0b57cec5SDimitry Andric     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
432*0b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
433*0b57cec5SDimitry Andric     }
434*0b57cec5SDimitry Andric 
435*0b57cec5SDimitry Andric     if (InstTy == InstType::FloatingPoint ||
436*0b57cec5SDimitry Andric         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
437*0b57cec5SDimitry Andric       OperandsMapping =
438*0b57cec5SDimitry Andric           getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
439*0b57cec5SDimitry Andric                                          : &Mips::ValueMappings[Mips::DPRIdx],
440*0b57cec5SDimitry Andric                               &Mips::ValueMappings[Mips::GPRIdx]});
441*0b57cec5SDimitry Andric       break;
442*0b57cec5SDimitry Andric     } else { // gprb
443*0b57cec5SDimitry Andric       OperandsMapping =
444*0b57cec5SDimitry Andric           getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
445*0b57cec5SDimitry Andric                                          : &Mips::ValueMappings[Mips::DPRIdx],
446*0b57cec5SDimitry Andric                               &Mips::ValueMappings[Mips::GPRIdx]});
447*0b57cec5SDimitry Andric       if (Size == 64)
448*0b57cec5SDimitry Andric         MappingID = CustomMappingID;
449*0b57cec5SDimitry Andric     }
450*0b57cec5SDimitry Andric     break;
451*0b57cec5SDimitry Andric   }
452*0b57cec5SDimitry Andric   case G_PHI: {
453*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
454*0b57cec5SDimitry Andric     InstType InstTy = InstType::Integer;
455*0b57cec5SDimitry Andric     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
456*0b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
457*0b57cec5SDimitry Andric     }
458*0b57cec5SDimitry Andric 
459*0b57cec5SDimitry Andric     // PHI is copylike and should have one regbank in mapping for def register.
460*0b57cec5SDimitry Andric     if (InstTy == InstType::Integer && Size == 64) { // fprb
461*0b57cec5SDimitry Andric       OperandsMapping =
462*0b57cec5SDimitry Andric           getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
463*0b57cec5SDimitry Andric       return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
464*0b57cec5SDimitry Andric                                    /*NumOperands=*/1);
465*0b57cec5SDimitry Andric     }
466*0b57cec5SDimitry Andric     // Use default handling for PHI, i.e. set reg bank of def operand to match
467*0b57cec5SDimitry Andric     // register banks of use operands.
468*0b57cec5SDimitry Andric     const RegisterBankInfo::InstructionMapping &Mapping =
469*0b57cec5SDimitry Andric         getInstrMappingImpl(MI);
470*0b57cec5SDimitry Andric     return Mapping;
471*0b57cec5SDimitry Andric   }
472*0b57cec5SDimitry Andric   case G_SELECT: {
473*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
474*0b57cec5SDimitry Andric     InstType InstTy = InstType::Integer;
475*0b57cec5SDimitry Andric     if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
476*0b57cec5SDimitry Andric       InstTy = TI.determineInstType(&MI);
477*0b57cec5SDimitry Andric     }
478*0b57cec5SDimitry Andric 
479*0b57cec5SDimitry Andric     if (InstTy == InstType::FloatingPoint ||
480*0b57cec5SDimitry Andric         (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
481*0b57cec5SDimitry Andric       const RegisterBankInfo::ValueMapping *Bank =
482*0b57cec5SDimitry Andric           Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
483*0b57cec5SDimitry Andric                      : &Mips::ValueMappings[Mips::DPRIdx];
484*0b57cec5SDimitry Andric       OperandsMapping = getOperandsMapping(
485*0b57cec5SDimitry Andric           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
486*0b57cec5SDimitry Andric       break;
487*0b57cec5SDimitry Andric     } else { // gprb
488*0b57cec5SDimitry Andric       const RegisterBankInfo::ValueMapping *Bank =
489*0b57cec5SDimitry Andric           Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
490*0b57cec5SDimitry Andric                      : &Mips::ValueMappings[Mips::DPRIdx];
491*0b57cec5SDimitry Andric       OperandsMapping = getOperandsMapping(
492*0b57cec5SDimitry Andric           {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
493*0b57cec5SDimitry Andric       if (Size == 64)
494*0b57cec5SDimitry Andric         MappingID = CustomMappingID;
495*0b57cec5SDimitry Andric     }
496*0b57cec5SDimitry Andric     break;
497*0b57cec5SDimitry Andric   }
498*0b57cec5SDimitry Andric   case G_UNMERGE_VALUES: {
499*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
500*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx],
501*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::DPRIdx]});
502*0b57cec5SDimitry Andric     MappingID = CustomMappingID;
503*0b57cec5SDimitry Andric     break;
504*0b57cec5SDimitry Andric   }
505*0b57cec5SDimitry Andric   case G_MERGE_VALUES: {
506*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
507*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx],
508*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::GPRIdx]});
509*0b57cec5SDimitry Andric     MappingID = CustomMappingID;
510*0b57cec5SDimitry Andric     break;
511*0b57cec5SDimitry Andric   }
512*0b57cec5SDimitry Andric   case G_FADD:
513*0b57cec5SDimitry Andric   case G_FSUB:
514*0b57cec5SDimitry Andric   case G_FMUL:
515*0b57cec5SDimitry Andric   case G_FDIV:
516*0b57cec5SDimitry Andric   case G_FABS:
517*0b57cec5SDimitry Andric   case G_FSQRT:{
518*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
519*0b57cec5SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
520*0b57cec5SDimitry Andric     OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
521*0b57cec5SDimitry Andric                                  : &Mips::ValueMappings[Mips::DPRIdx];
522*0b57cec5SDimitry Andric     break;
523*0b57cec5SDimitry Andric   }
524*0b57cec5SDimitry Andric   case G_FCONSTANT: {
525*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
526*0b57cec5SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
527*0b57cec5SDimitry Andric     const RegisterBankInfo::ValueMapping *FPRValueMapping =
528*0b57cec5SDimitry Andric         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
529*0b57cec5SDimitry Andric                    : &Mips::ValueMappings[Mips::DPRIdx];
530*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
531*0b57cec5SDimitry Andric     break;
532*0b57cec5SDimitry Andric   }
533*0b57cec5SDimitry Andric   case G_FCMP: {
534*0b57cec5SDimitry Andric     unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
535*0b57cec5SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported floating point size");
536*0b57cec5SDimitry Andric     const RegisterBankInfo::ValueMapping *FPRValueMapping =
537*0b57cec5SDimitry Andric         Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
538*0b57cec5SDimitry Andric                    : &Mips::ValueMappings[Mips::DPRIdx];
539*0b57cec5SDimitry Andric     OperandsMapping =
540*0b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
541*0b57cec5SDimitry Andric                             FPRValueMapping, FPRValueMapping});
542*0b57cec5SDimitry Andric     break;
543*0b57cec5SDimitry Andric   }
544*0b57cec5SDimitry Andric   case G_FPEXT:
545*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
546*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::SPRIdx]});
547*0b57cec5SDimitry Andric     break;
548*0b57cec5SDimitry Andric   case G_FPTRUNC:
549*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
550*0b57cec5SDimitry Andric                                           &Mips::ValueMappings[Mips::DPRIdx]});
551*0b57cec5SDimitry Andric     break;
552*0b57cec5SDimitry Andric   case G_FPTOSI: {
553*0b57cec5SDimitry Andric     unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
554*0b57cec5SDimitry Andric     assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
555*0b57cec5SDimitry Andric            "Unsupported integer size");
556*0b57cec5SDimitry Andric     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
557*0b57cec5SDimitry Andric     OperandsMapping = getOperandsMapping({
558*0b57cec5SDimitry Andric         &Mips::ValueMappings[Mips::GPRIdx],
559*0b57cec5SDimitry Andric         SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
560*0b57cec5SDimitry Andric                      : &Mips::ValueMappings[Mips::DPRIdx],
561*0b57cec5SDimitry Andric     });
562*0b57cec5SDimitry Andric     break;
563*0b57cec5SDimitry Andric   }
564*0b57cec5SDimitry Andric   case G_SITOFP: {
565*0b57cec5SDimitry Andric     unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
566*0b57cec5SDimitry Andric     unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
567*0b57cec5SDimitry Andric     (void)SizeInt;
568*0b57cec5SDimitry Andric     assert((SizeInt == 32) && "Unsupported integer size");
569*0b57cec5SDimitry Andric     assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
570*0b57cec5SDimitry Andric     OperandsMapping =
571*0b57cec5SDimitry Andric         getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
572*0b57cec5SDimitry Andric                                          : &Mips::ValueMappings[Mips::DPRIdx],
573*0b57cec5SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx]});
574*0b57cec5SDimitry Andric     break;
575*0b57cec5SDimitry Andric   }
576*0b57cec5SDimitry Andric   case G_CONSTANT:
577*0b57cec5SDimitry Andric   case G_FRAME_INDEX:
578*0b57cec5SDimitry Andric   case G_GLOBAL_VALUE:
579*0b57cec5SDimitry Andric   case G_BRCOND:
580*0b57cec5SDimitry Andric     OperandsMapping =
581*0b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
582*0b57cec5SDimitry Andric     break;
583*0b57cec5SDimitry Andric   case G_ICMP:
584*0b57cec5SDimitry Andric     OperandsMapping =
585*0b57cec5SDimitry Andric         getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
586*0b57cec5SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx],
587*0b57cec5SDimitry Andric                             &Mips::ValueMappings[Mips::GPRIdx]});
588*0b57cec5SDimitry Andric     break;
589*0b57cec5SDimitry Andric   default:
590*0b57cec5SDimitry Andric     return getInvalidInstructionMapping();
591*0b57cec5SDimitry Andric   }
592*0b57cec5SDimitry Andric 
593*0b57cec5SDimitry Andric   return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
594*0b57cec5SDimitry Andric                                NumOperands);
595*0b57cec5SDimitry Andric }
596*0b57cec5SDimitry Andric 
597*0b57cec5SDimitry Andric using InstListTy = GISelWorkList<4>;
598*0b57cec5SDimitry Andric namespace {
599*0b57cec5SDimitry Andric class InstManager : public GISelChangeObserver {
600*0b57cec5SDimitry Andric   InstListTy &InstList;
601*0b57cec5SDimitry Andric 
602*0b57cec5SDimitry Andric public:
603*0b57cec5SDimitry Andric   InstManager(InstListTy &Insts) : InstList(Insts) {}
604*0b57cec5SDimitry Andric 
605*0b57cec5SDimitry Andric   void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
606*0b57cec5SDimitry Andric   void erasingInstr(MachineInstr &MI) override {}
607*0b57cec5SDimitry Andric   void changingInstr(MachineInstr &MI) override {}
608*0b57cec5SDimitry Andric   void changedInstr(MachineInstr &MI) override {}
609*0b57cec5SDimitry Andric };
610*0b57cec5SDimitry Andric } // end anonymous namespace
611*0b57cec5SDimitry Andric 
612*0b57cec5SDimitry Andric /// Here we have to narrowScalar s64 operands to s32, combine away
613*0b57cec5SDimitry Andric /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
614*0b57cec5SDimitry Andric /// We manually assign 32 bit gprb to register operands of all new instructions
615*0b57cec5SDimitry Andric /// that got created in the process since they will not end up in RegBankSelect
616*0b57cec5SDimitry Andric /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
617*0b57cec5SDimitry Andric void MipsRegisterBankInfo::applyMappingImpl(
618*0b57cec5SDimitry Andric     const OperandsMapper &OpdMapper) const {
619*0b57cec5SDimitry Andric   MachineInstr &MI = OpdMapper.getMI();
620*0b57cec5SDimitry Andric   InstListTy NewInstrs;
621*0b57cec5SDimitry Andric   MachineIRBuilder B(MI);
622*0b57cec5SDimitry Andric   MachineFunction *MF = MI.getMF();
623*0b57cec5SDimitry Andric   MachineRegisterInfo &MRI = OpdMapper.getMRI();
624*0b57cec5SDimitry Andric 
625*0b57cec5SDimitry Andric   InstManager NewInstrObserver(NewInstrs);
626*0b57cec5SDimitry Andric   GISelObserverWrapper WrapperObserver(&NewInstrObserver);
627*0b57cec5SDimitry Andric   LegalizerHelper Helper(*MF, WrapperObserver, B);
628*0b57cec5SDimitry Andric   LegalizationArtifactCombiner ArtCombiner(
629*0b57cec5SDimitry Andric       B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
630*0b57cec5SDimitry Andric 
631*0b57cec5SDimitry Andric   switch (MI.getOpcode()) {
632*0b57cec5SDimitry Andric   case TargetOpcode::G_LOAD:
633*0b57cec5SDimitry Andric   case TargetOpcode::G_STORE:
634*0b57cec5SDimitry Andric   case TargetOpcode::G_PHI:
635*0b57cec5SDimitry Andric   case TargetOpcode::G_SELECT: {
636*0b57cec5SDimitry Andric     Helper.narrowScalar(MI, 0, LLT::scalar(32));
637*0b57cec5SDimitry Andric     // Handle new instructions.
638*0b57cec5SDimitry Andric     while (!NewInstrs.empty()) {
639*0b57cec5SDimitry Andric       MachineInstr *NewMI = NewInstrs.pop_back_val();
640*0b57cec5SDimitry Andric       // This is new G_UNMERGE that was created during narrowScalar and will
641*0b57cec5SDimitry Andric       // not be considered for regbank selection. RegBankSelect for mips
642*0b57cec5SDimitry Andric       // visits/makes corresponding G_MERGE first. Combine them here.
643*0b57cec5SDimitry Andric       if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
644*0b57cec5SDimitry Andric         SmallVector<MachineInstr *, 2> DeadInstrs;
645*0b57cec5SDimitry Andric         ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
646*0b57cec5SDimitry Andric         for (MachineInstr *DeadMI : DeadInstrs)
647*0b57cec5SDimitry Andric           DeadMI->eraseFromParent();
648*0b57cec5SDimitry Andric       }
649*0b57cec5SDimitry Andric       // This G_MERGE will be combined away when its corresponding G_UNMERGE
650*0b57cec5SDimitry Andric       // gets regBankSelected.
651*0b57cec5SDimitry Andric       else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
652*0b57cec5SDimitry Andric         continue;
653*0b57cec5SDimitry Andric       else
654*0b57cec5SDimitry Andric         // Manually set register banks for all register operands to 32 bit gprb.
655*0b57cec5SDimitry Andric         for (auto Op : NewMI->operands()) {
656*0b57cec5SDimitry Andric           if (Op.isReg()) {
657*0b57cec5SDimitry Andric             assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
658*0b57cec5SDimitry Andric                    "Only 32 bit gprb is handled here.\n");
659*0b57cec5SDimitry Andric             MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
660*0b57cec5SDimitry Andric           }
661*0b57cec5SDimitry Andric         }
662*0b57cec5SDimitry Andric     }
663*0b57cec5SDimitry Andric     return;
664*0b57cec5SDimitry Andric   }
665*0b57cec5SDimitry Andric   case TargetOpcode::G_UNMERGE_VALUES: {
666*0b57cec5SDimitry Andric     SmallVector<MachineInstr *, 2> DeadInstrs;
667*0b57cec5SDimitry Andric     ArtCombiner.tryCombineMerges(MI, DeadInstrs);
668*0b57cec5SDimitry Andric     for (MachineInstr *DeadMI : DeadInstrs)
669*0b57cec5SDimitry Andric       DeadMI->eraseFromParent();
670*0b57cec5SDimitry Andric     return;
671*0b57cec5SDimitry Andric   }
672*0b57cec5SDimitry Andric   default:
673*0b57cec5SDimitry Andric     break;
674*0b57cec5SDimitry Andric   }
675*0b57cec5SDimitry Andric 
676*0b57cec5SDimitry Andric   return applyDefaultMapping(OpdMapper);
677*0b57cec5SDimitry Andric }
678