MipsRegisterBankInfo.cpp revision 360784
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
25namespace llvm {
26namespace Mips {
27enum PartialMappingIdx {
28  PMI_GPR,
29  PMI_SPR,
30  PMI_DPR,
31  PMI_MSA,
32  PMI_Min = PMI_GPR,
33};
34
35RegisterBankInfo::PartialMapping PartMappings[]{
36    {0, 32, GPRBRegBank},
37    {0, 32, FPRBRegBank},
38    {0, 64, FPRBRegBank},
39    {0, 128, FPRBRegBank}
40};
41
42enum ValueMappingIdx {
43    InvalidIdx = 0,
44    GPRIdx = 1,
45    SPRIdx = 4,
46    DPRIdx = 7,
47    MSAIdx = 10
48};
49
50RegisterBankInfo::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
74using namespace llvm;
75
76MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
77    : MipsGenRegisterBankInfo() {}
78
79const RegisterBank &
80MipsRegisterBankInfo::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.
109static 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.
130static 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.
146static 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
159static 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
172void 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
187void 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
195MachineInstr *
196MipsRegisterBankInfo::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
209MachineInstr *
210MipsRegisterBankInfo::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
221MipsRegisterBankInfo::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
252bool 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
287bool 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
327void 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
335void 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
356MipsRegisterBankInfo::InstType
357MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
358  visit(MI, nullptr);
359  return getRecordedTypeForInstr(MI);
360}
361
362void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
363    llvm::StringRef FunctionName) {
364  if (MFName != FunctionName) {
365    MFName = FunctionName;
366    WaitingQueues.clear();
367    Types.clear();
368  }
369}
370
371static const MipsRegisterBankInfo::ValueMapping *
372getMSAMapping(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
378static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
379  return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
380                    : &Mips::ValueMappings[Mips::DPRIdx];
381}
382
383static 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.
387static const MipsRegisterBankInfo::ValueMapping *
388getGprbOrCustomMapping(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
396const RegisterBankInfo::InstructionMapping &
397MipsRegisterBankInfo::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
612using InstListTy = GISelWorkList<4>;
613namespace {
614class InstManager : public GISelChangeObserver {
615  InstListTy &InstList;
616
617public:
618  InstManager(InstListTy &Insts) : InstList(Insts) {}
619
620  void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
621  void erasingInstr(MachineInstr &MI) override {}
622  void changingInstr(MachineInstr &MI) override {}
623  void changedInstr(MachineInstr &MI) override {}
624};
625} // end anonymous namespace
626
627void 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
653static void
654combineAwayG_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
663void 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