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