[MIPS GlobalISel] Select MSA vector generic and builtin add
[llvm-complete.git] / lib / Target / Mips / MipsRegisterBankInfo.cpp
blobd334366e727cd88bf3b1938da8ee4b419a86582b
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 //===----------------------------------------------------------------------===//
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"
21 #define GET_TARGET_REGBANK_IMPL
23 #include "MipsGenRegisterBank.inc"
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,
35 RegisterBankInfo::PartialMapping PartMappings[]{
36 {0, 32, GPRBRegBank},
37 {0, 32, FPRBRegBank},
38 {0, 64, FPRBRegBank},
39 {0, 128, FPRBRegBank}
42 enum ValueMappingIdx {
43 InvalidIdx = 0,
44 GPRIdx = 1,
45 SPRIdx = 4,
46 DPRIdx = 7,
47 MSAIdx = 10
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}
71 } // end namespace Mips
72 } // end namespace llvm
74 using namespace llvm;
76 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
77 : MipsGenRegisterBankInfo() {}
79 const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
80 const TargetRegisterClass &RC) const {
81 using namespace Mips;
83 switch (RC.getID()) {
84 case Mips::GPR32RegClassID:
85 case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
86 case Mips::GPRMM16MovePPairFirstRegClassID:
87 case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
88 case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
89 case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
90 case Mips::SP32RegClassID:
91 case Mips::GP32RegClassID:
92 return getRegBank(Mips::GPRBRegBankID);
93 case Mips::FGRCCRegClassID:
94 case Mips::FGR32RegClassID:
95 case Mips::FGR64RegClassID:
96 case Mips::AFGR64RegClassID:
97 case Mips::MSA128BRegClassID:
98 case Mips::MSA128HRegClassID:
99 case Mips::MSA128WRegClassID:
100 case Mips::MSA128DRegClassID:
101 return getRegBank(Mips::FPRBRegBankID);
102 default:
103 llvm_unreachable("Register class not supported");
107 // Instructions where all register operands are floating point.
108 static bool isFloatingPointOpcode(unsigned Opc) {
109 switch (Opc) {
110 case TargetOpcode::G_FCONSTANT:
111 case TargetOpcode::G_FADD:
112 case TargetOpcode::G_FSUB:
113 case TargetOpcode::G_FMUL:
114 case TargetOpcode::G_FDIV:
115 case TargetOpcode::G_FABS:
116 case TargetOpcode::G_FSQRT:
117 case TargetOpcode::G_FCEIL:
118 case TargetOpcode::G_FFLOOR:
119 case TargetOpcode::G_FPEXT:
120 case TargetOpcode::G_FPTRUNC:
121 return true;
122 default:
123 return false;
127 // Instructions where use operands are floating point registers.
128 // Def operands are general purpose.
129 static bool isFloatingPointOpcodeUse(unsigned Opc) {
130 switch (Opc) {
131 case TargetOpcode::G_FPTOSI:
132 case TargetOpcode::G_FPTOUI:
133 case TargetOpcode::G_FCMP:
134 case Mips::MFC1:
135 case Mips::ExtractElementF64:
136 case Mips::ExtractElementF64_64:
137 return true;
138 default:
139 return isFloatingPointOpcode(Opc);
143 // Instructions where def operands are floating point registers.
144 // Use operands are general purpose.
145 static bool isFloatingPointOpcodeDef(unsigned Opc) {
146 switch (Opc) {
147 case TargetOpcode::G_SITOFP:
148 case TargetOpcode::G_UITOFP:
149 case Mips::MTC1:
150 case Mips::BuildPairF64:
151 case Mips::BuildPairF64_64:
152 return true;
153 default:
154 return isFloatingPointOpcode(Opc);
158 static bool isAmbiguous(unsigned Opc) {
159 switch (Opc) {
160 case TargetOpcode::G_LOAD:
161 case TargetOpcode::G_STORE:
162 case TargetOpcode::G_PHI:
163 case TargetOpcode::G_SELECT:
164 case TargetOpcode::G_IMPLICIT_DEF:
165 return true;
166 default:
167 return false;
171 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
172 Register Reg, const MachineRegisterInfo &MRI) {
173 assert(!MRI.getType(Reg).isPointer() &&
174 "Pointers are gprb, they should not be considered as ambiguous.\n");
175 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
176 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
177 // Copy with many uses.
178 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
179 !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
180 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
181 else
182 DefUses.push_back(skipCopiesOutgoing(&UseMI));
186 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
187 Register Reg, const MachineRegisterInfo &MRI) {
188 assert(!MRI.getType(Reg).isPointer() &&
189 "Pointers are gprb, they should not be considered as ambiguous.\n");
190 MachineInstr *DefMI = MRI.getVRegDef(Reg);
191 UseDefs.push_back(skipCopiesIncoming(DefMI));
194 MachineInstr *
195 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
196 MachineInstr *MI) const {
197 const MachineFunction &MF = *MI->getParent()->getParent();
198 const MachineRegisterInfo &MRI = MF.getRegInfo();
199 MachineInstr *Ret = MI;
200 while (Ret->getOpcode() == TargetOpcode::COPY &&
201 !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
202 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
203 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
205 return Ret;
208 MachineInstr *
209 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
210 MachineInstr *MI) const {
211 const MachineFunction &MF = *MI->getParent()->getParent();
212 const MachineRegisterInfo &MRI = MF.getRegInfo();
213 MachineInstr *Ret = MI;
214 while (Ret->getOpcode() == TargetOpcode::COPY &&
215 !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
216 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
217 return Ret;
220 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
221 const MachineInstr *MI) {
222 assert(isAmbiguous(MI->getOpcode()) &&
223 "Not implemented for non Ambiguous opcode.\n");
225 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
227 if (MI->getOpcode() == TargetOpcode::G_LOAD)
228 addDefUses(MI->getOperand(0).getReg(), MRI);
230 if (MI->getOpcode() == TargetOpcode::G_STORE)
231 addUseDef(MI->getOperand(0).getReg(), MRI);
233 if (MI->getOpcode() == TargetOpcode::G_PHI) {
234 addDefUses(MI->getOperand(0).getReg(), MRI);
236 for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
237 addUseDef(MI->getOperand(i).getReg(), MRI);
240 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
241 addDefUses(MI->getOperand(0).getReg(), MRI);
243 addUseDef(MI->getOperand(2).getReg(), MRI);
244 addUseDef(MI->getOperand(3).getReg(), MRI);
247 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
248 addDefUses(MI->getOperand(0).getReg(), MRI);
251 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
252 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
253 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
254 if (wasVisited(MI))
255 return true; // InstType has already been determined for MI.
257 startVisit(MI);
258 AmbiguousRegDefUseContainer DefUseContainer(MI);
260 // Visit instructions where MI's DEF operands are USED.
261 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
262 return true;
264 // Visit instructions that DEFINE MI's USE operands.
265 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
266 return true;
268 // All MI's adjacent instructions, are ambiguous.
269 if (!WaitingForTypeOfMI) {
270 // This is chain of ambiguous instructions.
271 setTypes(MI, InstType::Ambiguous);
272 return true;
274 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
275 // instructions or has no other adjacent instructions. Anyway InstType could
276 // not be determined. There could be unexplored path from some of
277 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
278 // mapping available.
279 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
280 // this way when WaitingForTypeOfMI figures out its InstType same InstType
281 // will be assigned to all instructions in this branch.
282 addToWaitingQueue(WaitingForTypeOfMI, MI);
283 return false;
286 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
287 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
288 bool isDefUse) {
289 while (!AdjacentInstrs.empty()) {
290 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
292 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
293 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
294 setTypes(MI, InstType::FloatingPoint);
295 return true;
298 // Determine InstType from register bank of phys register that is
299 // 'isDefUse ? def : use' of this copy.
300 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
301 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
302 return true;
305 // Defaults to integer instruction. Includes G_MERGE_VALUES and
306 // G_UNMERGE_VALUES.
307 if (!isAmbiguous(AdjMI->getOpcode())) {
308 setTypes(MI, InstType::Integer);
309 return true;
312 // When AdjMI was visited first, MI has to continue to explore remaining
313 // adjacent instructions and determine InstType without visiting AdjMI.
314 if (!wasVisited(AdjMI) ||
315 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
316 if (visit(AdjMI, MI)) {
317 // InstType is successfully determined and is same as for AdjMI.
318 setTypes(MI, getRecordedTypeForInstr(AdjMI));
319 return true;
323 return false;
326 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
327 InstType InstTy) {
328 changeRecordedTypeForInstr(MI, InstTy);
329 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
330 setTypes(WaitingInstr, InstTy);
334 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
335 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
336 assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
337 "Copies of non physical registers should not be considered here.\n");
339 const MachineFunction &MF = *CopyInst->getMF();
340 const MachineRegisterInfo &MRI = MF.getRegInfo();
341 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
342 const RegisterBankInfo &RBI =
343 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
344 const RegisterBank *Bank =
345 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
347 if (Bank == &Mips::FPRBRegBank)
348 setTypes(MI, InstType::FloatingPoint);
349 else if (Bank == &Mips::GPRBRegBank)
350 setTypes(MI, InstType::Integer);
351 else
352 llvm_unreachable("Unsupported register bank.\n");
355 MipsRegisterBankInfo::InstType
356 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
357 visit(MI, nullptr);
358 return getRecordedTypeForInstr(MI);
361 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
362 llvm::StringRef FunctionName) {
363 if (MFName != FunctionName) {
364 MFName = FunctionName;
365 WaitingQueues.clear();
366 Types.clear();
370 static const MipsRegisterBankInfo::ValueMapping *
371 getMSAMapping(const MachineFunction &MF) {
372 assert(static_cast<const MipsSubtarget &>(MF.getSubtarget()).hasMSA() &&
373 "MSA mapping not available on target without MSA.");
374 return &Mips::ValueMappings[Mips::MSAIdx];
377 static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
378 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
379 : &Mips::ValueMappings[Mips::DPRIdx];
382 static const unsigned CustomMappingID = 1;
384 // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
385 // will be split into two 32 bit registers in gprb.
386 static const MipsRegisterBankInfo::ValueMapping *
387 getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
388 if (Size == 32)
389 return &Mips::ValueMappings[Mips::GPRIdx];
391 MappingID = CustomMappingID;
392 return &Mips::ValueMappings[Mips::DPRIdx];
395 const RegisterBankInfo::InstructionMapping &
396 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
398 static TypeInfoForMF TI;
400 // Reset TI internal data when MF changes.
401 TI.cleanupIfNewFunction(MI.getMF()->getName());
403 unsigned Opc = MI.getOpcode();
404 const MachineFunction &MF = *MI.getParent()->getParent();
405 const MachineRegisterInfo &MRI = MF.getRegInfo();
407 if (MI.getOpcode() != TargetOpcode::G_PHI) {
408 const RegisterBankInfo::InstructionMapping &Mapping =
409 getInstrMappingImpl(MI);
410 if (Mapping.isValid())
411 return Mapping;
414 using namespace TargetOpcode;
416 unsigned NumOperands = MI.getNumOperands();
417 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
418 unsigned MappingID = DefaultMappingID;
420 // Check if LLT sizes match sizes of available register banks.
421 for (const MachineOperand &Op : MI.operands()) {
422 if (Op.isReg()) {
423 LLT RegTy = MRI.getType(Op.getReg());
425 if (RegTy.isScalar() &&
426 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
427 return getInvalidInstructionMapping();
429 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
430 return getInvalidInstructionMapping();
434 const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
435 unsigned Op0Size = Op0Ty.getSizeInBits();
436 InstType InstTy = InstType::Integer;
438 switch (Opc) {
439 case G_TRUNC:
440 case G_SUB:
441 case G_MUL:
442 case G_UMULH:
443 case G_ZEXTLOAD:
444 case G_SEXTLOAD:
445 case G_GEP:
446 case G_INTTOPTR:
447 case G_PTRTOINT:
448 case G_AND:
449 case G_OR:
450 case G_XOR:
451 case G_SHL:
452 case G_ASHR:
453 case G_LSHR:
454 case G_SDIV:
455 case G_UDIV:
456 case G_SREM:
457 case G_UREM:
458 case G_BRINDIRECT:
459 case G_VASTART:
460 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
461 break;
462 case G_ADD:
463 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
464 if (Op0Size == 128)
465 OperandsMapping = getMSAMapping(MF);
466 break;
467 case G_STORE:
468 case G_LOAD:
469 if (Op0Size == 128) {
470 OperandsMapping = getOperandsMapping(
471 {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
472 break;
475 if (!Op0Ty.isPointer())
476 InstTy = TI.determineInstType(&MI);
478 if (InstTy == InstType::FloatingPoint ||
479 (Op0Size == 64 && InstTy == InstType::Ambiguous))
480 OperandsMapping = getOperandsMapping(
481 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
482 else
483 OperandsMapping =
484 getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
485 &Mips::ValueMappings[Mips::GPRIdx]});
487 break;
488 case G_PHI:
489 if (!Op0Ty.isPointer())
490 InstTy = TI.determineInstType(&MI);
492 // PHI is copylike and should have one regbank in mapping for def register.
493 if (InstTy == InstType::Integer && Op0Size == 64) {
494 OperandsMapping =
495 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
496 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
497 /*NumOperands=*/1);
499 // Use default handling for PHI, i.e. set reg bank of def operand to match
500 // register banks of use operands.
501 return getInstrMappingImpl(MI);
502 case G_SELECT: {
503 if (!Op0Ty.isPointer())
504 InstTy = TI.determineInstType(&MI);
506 if (InstTy == InstType::FloatingPoint ||
507 (Op0Size == 64 && InstTy == InstType::Ambiguous)) {
508 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
509 OperandsMapping = getOperandsMapping(
510 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
511 break;
512 } else {
513 const RegisterBankInfo::ValueMapping *Bank =
514 getGprbOrCustomMapping(Op0Size, MappingID);
515 OperandsMapping = getOperandsMapping(
516 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
518 break;
520 case G_IMPLICIT_DEF:
521 if (!Op0Ty.isPointer())
522 InstTy = TI.determineInstType(&MI);
524 if (InstTy == InstType::FloatingPoint)
525 OperandsMapping = getFprbMapping(Op0Size);
526 else
527 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
529 break;
530 case G_UNMERGE_VALUES:
531 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
532 &Mips::ValueMappings[Mips::GPRIdx],
533 &Mips::ValueMappings[Mips::DPRIdx]});
534 MappingID = CustomMappingID;
535 break;
536 case G_MERGE_VALUES:
537 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
538 &Mips::ValueMappings[Mips::GPRIdx],
539 &Mips::ValueMappings[Mips::GPRIdx]});
540 MappingID = CustomMappingID;
541 break;
542 case G_FADD:
543 case G_FSUB:
544 case G_FMUL:
545 case G_FDIV:
546 case G_FABS:
547 case G_FSQRT:
548 OperandsMapping = getFprbMapping(Op0Size);
549 break;
550 case G_FCONSTANT:
551 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
552 break;
553 case G_FCMP: {
554 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
555 OperandsMapping =
556 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
557 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
558 break;
560 case G_FPEXT:
561 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
562 &Mips::ValueMappings[Mips::SPRIdx]});
563 break;
564 case G_FPTRUNC:
565 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
566 &Mips::ValueMappings[Mips::DPRIdx]});
567 break;
568 case G_FPTOSI: {
569 assert((Op0Size == 32) && "Unsupported integer size");
570 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
571 OperandsMapping = getOperandsMapping(
572 {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
573 break;
575 case G_SITOFP:
576 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
577 "Unsupported integer size");
578 OperandsMapping = getOperandsMapping(
579 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
580 break;
581 case G_CONSTANT:
582 case G_FRAME_INDEX:
583 case G_GLOBAL_VALUE:
584 case G_JUMP_TABLE:
585 case G_BRCOND:
586 OperandsMapping =
587 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
588 break;
589 case G_BRJT:
590 OperandsMapping =
591 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
592 &Mips::ValueMappings[Mips::GPRIdx]});
593 break;
594 case G_ICMP:
595 OperandsMapping =
596 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
597 &Mips::ValueMappings[Mips::GPRIdx],
598 &Mips::ValueMappings[Mips::GPRIdx]});
599 break;
600 default:
601 return getInvalidInstructionMapping();
604 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
605 NumOperands);
608 using InstListTy = GISelWorkList<4>;
609 namespace {
610 class InstManager : public GISelChangeObserver {
611 InstListTy &InstList;
613 public:
614 InstManager(InstListTy &Insts) : InstList(Insts) {}
616 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
617 void erasingInstr(MachineInstr &MI) override {}
618 void changingInstr(MachineInstr &MI) override {}
619 void changedInstr(MachineInstr &MI) override {}
621 } // end anonymous namespace
623 void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
624 MachineRegisterInfo &MRI) const {
625 Register Dest = MI.getOperand(0).getReg();
626 switch (MI.getOpcode()) {
627 case TargetOpcode::G_STORE:
628 // No def operands, skip this instruction.
629 break;
630 case TargetOpcode::G_CONSTANT:
631 case TargetOpcode::G_LOAD:
632 case TargetOpcode::G_SELECT:
633 case TargetOpcode::G_PHI:
634 case TargetOpcode::G_IMPLICIT_DEF: {
635 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
636 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
637 break;
639 case TargetOpcode::G_GEP: {
640 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
641 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
642 break;
644 default:
645 llvm_unreachable("Unexpected opcode.");
649 static void
650 combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
651 MachineInstr &MI) {
652 SmallVector<MachineInstr *, 2> DeadInstrs;
653 ArtCombiner.tryCombineMerges(MI, DeadInstrs);
654 for (MachineInstr *DeadMI : DeadInstrs)
655 DeadMI->eraseFromParent();
658 void MipsRegisterBankInfo::applyMappingImpl(
659 const OperandsMapper &OpdMapper) const {
660 MachineInstr &MI = OpdMapper.getMI();
661 InstListTy NewInstrs;
662 MachineIRBuilder B(MI);
663 MachineFunction *MF = MI.getMF();
664 MachineRegisterInfo &MRI = OpdMapper.getMRI();
665 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
667 InstManager NewInstrObserver(NewInstrs);
668 GISelObserverWrapper WrapperObserver(&NewInstrObserver);
669 LegalizerHelper Helper(*MF, WrapperObserver, B);
670 LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
672 switch (MI.getOpcode()) {
673 case TargetOpcode::G_LOAD:
674 case TargetOpcode::G_STORE:
675 case TargetOpcode::G_PHI:
676 case TargetOpcode::G_SELECT:
677 case TargetOpcode::G_IMPLICIT_DEF: {
678 Helper.narrowScalar(MI, 0, LLT::scalar(32));
679 // Handle new instructions.
680 while (!NewInstrs.empty()) {
681 MachineInstr *NewMI = NewInstrs.pop_back_val();
682 // This is new G_UNMERGE that was created during narrowScalar and will
683 // not be considered for regbank selection. RegBankSelect for mips
684 // visits/makes corresponding G_MERGE first. Combine them here.
685 if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
686 combineAwayG_UNMERGE_VALUES(ArtCombiner, *NewMI);
687 // This G_MERGE will be combined away when its corresponding G_UNMERGE
688 // gets regBankSelected.
689 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
690 continue;
691 else
692 // Manually set register banks for def operands to 32 bit gprb.
693 setRegBank(*NewMI, MRI);
695 return;
697 case TargetOpcode::G_UNMERGE_VALUES:
698 combineAwayG_UNMERGE_VALUES(ArtCombiner, MI);
699 return;
700 default:
701 break;
704 return applyDefaultMapping(OpdMapper);