[RISCV] Match vcompress during shuffle lowering (#117748)
[llvm-project.git] / llvm / lib / Target / Mips / MipsRegisterBankInfo.cpp
blob4aecaf18db48060d0494115b0a2df43be3119e27
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 const 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 const 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) {}
78 // Instructions where use operands are floating point registers.
79 // Def operands are general purpose.
80 static bool isFloatingPointOpcodeUse(unsigned Opc) {
81 switch (Opc) {
82 case TargetOpcode::G_FPTOSI:
83 case TargetOpcode::G_FPTOUI:
84 case TargetOpcode::G_FCMP:
85 return true;
86 default:
87 return isPreISelGenericFloatingPointOpcode(Opc);
91 // Instructions where def operands are floating point registers.
92 // Use operands are general purpose.
93 static bool isFloatingPointOpcodeDef(unsigned Opc) {
94 switch (Opc) {
95 case TargetOpcode::G_SITOFP:
96 case TargetOpcode::G_UITOFP:
97 return true;
98 default:
99 return isPreISelGenericFloatingPointOpcode(Opc);
103 static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
104 if (MI->getOpcode() == TargetOpcode::G_LOAD ||
105 MI->getOpcode() == TargetOpcode::G_STORE) {
106 auto MMO = *MI->memoperands_begin();
107 const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
108 if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
109 (!MMO->getSize().hasValue() ||
110 MMO->getAlign() < MMO->getSize().getValue())))
111 return true;
113 return false;
116 static bool isAmbiguous(unsigned Opc) {
117 switch (Opc) {
118 case TargetOpcode::G_LOAD:
119 case TargetOpcode::G_STORE:
120 case TargetOpcode::G_PHI:
121 case TargetOpcode::G_SELECT:
122 case TargetOpcode::G_IMPLICIT_DEF:
123 case TargetOpcode::G_UNMERGE_VALUES:
124 case TargetOpcode::G_MERGE_VALUES:
125 return true;
126 default:
127 return false;
131 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
132 Register Reg, const MachineRegisterInfo &MRI) {
133 assert(!MRI.getType(Reg).isPointer() &&
134 "Pointers are gprb, they should not be considered as ambiguous.\n");
135 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
136 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
137 // Copy with many uses.
138 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
139 !NonCopyInstr->getOperand(0).getReg().isPhysical())
140 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
141 else
142 DefUses.push_back(skipCopiesOutgoing(&UseMI));
146 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
147 Register Reg, const MachineRegisterInfo &MRI) {
148 assert(!MRI.getType(Reg).isPointer() &&
149 "Pointers are gprb, they should not be considered as ambiguous.\n");
150 MachineInstr *DefMI = MRI.getVRegDef(Reg);
151 UseDefs.push_back(skipCopiesIncoming(DefMI));
154 MachineInstr *
155 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
156 MachineInstr *MI) const {
157 const MachineFunction &MF = *MI->getParent()->getParent();
158 const MachineRegisterInfo &MRI = MF.getRegInfo();
159 MachineInstr *Ret = MI;
160 while (Ret->getOpcode() == TargetOpcode::COPY &&
161 !Ret->getOperand(0).getReg().isPhysical() &&
162 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
163 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
165 return Ret;
168 MachineInstr *
169 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
170 MachineInstr *MI) const {
171 const MachineFunction &MF = *MI->getParent()->getParent();
172 const MachineRegisterInfo &MRI = MF.getRegInfo();
173 MachineInstr *Ret = MI;
174 while (Ret->getOpcode() == TargetOpcode::COPY &&
175 !Ret->getOperand(1).getReg().isPhysical())
176 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
177 return Ret;
180 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
181 const MachineInstr *MI) {
182 assert(isAmbiguous(MI->getOpcode()) &&
183 "Not implemented for non Ambiguous opcode.\n");
185 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
187 if (MI->getOpcode() == TargetOpcode::G_LOAD)
188 addDefUses(MI->getOperand(0).getReg(), MRI);
190 if (MI->getOpcode() == TargetOpcode::G_STORE)
191 addUseDef(MI->getOperand(0).getReg(), MRI);
193 if (auto *PHI = dyn_cast<GPhi>(MI)) {
194 addDefUses(PHI->getReg(0), MRI);
196 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
197 addUseDef(PHI->getIncomingValue(I), MRI);
200 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
201 addDefUses(MI->getOperand(0).getReg(), MRI);
203 addUseDef(MI->getOperand(2).getReg(), MRI);
204 addUseDef(MI->getOperand(3).getReg(), MRI);
207 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
208 addDefUses(MI->getOperand(0).getReg(), MRI);
210 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
211 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
213 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
214 addDefUses(MI->getOperand(0).getReg(), MRI);
217 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
218 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
219 InstType &AmbiguousTy) {
220 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
221 if (wasVisited(MI))
222 return true; // InstType has already been determined for MI.
224 startVisit(MI);
225 AmbiguousRegDefUseContainer DefUseContainer(MI);
227 if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
228 setTypes(MI, Integer);
229 return true;
232 if (AmbiguousTy == InstType::Ambiguous &&
233 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
234 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
235 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
237 // Visit instructions where MI's DEF operands are USED.
238 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
239 return true;
241 // Visit instructions that DEFINE MI's USE operands.
242 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
243 return true;
245 // All MI's adjacent instructions, are ambiguous.
246 if (!WaitingForTypeOfMI) {
247 // This is chain of ambiguous instructions.
248 setTypes(MI, AmbiguousTy);
249 return true;
251 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
252 // instructions or has no other adjacent instructions. Anyway InstType could
253 // not be determined. There could be unexplored path from some of
254 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
255 // mapping available.
256 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
257 // this way when WaitingForTypeOfMI figures out its InstType same InstType
258 // will be assigned to all instructions in this branch.
259 addToWaitingQueue(WaitingForTypeOfMI, MI);
260 return false;
263 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
264 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
265 bool isDefUse, InstType &AmbiguousTy) {
266 while (!AdjacentInstrs.empty()) {
267 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
269 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
270 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
271 setTypes(MI, InstType::FloatingPoint);
272 return true;
275 // Determine InstType from register bank of phys register that is
276 // 'isDefUse ? def : use' of this copy.
277 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
278 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
279 return true;
282 // Defaults to integer instruction. Small registers in G_MERGE (uses) and
283 // G_UNMERGE (defs) will always be gprb.
284 if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
285 (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
286 !isAmbiguous(AdjMI->getOpcode())) {
287 setTypes(MI, InstType::Integer);
288 return true;
291 // When AdjMI was visited first, MI has to continue to explore remaining
292 // adjacent instructions and determine InstType without visiting AdjMI.
293 if (!wasVisited(AdjMI) ||
294 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
295 if (visit(AdjMI, MI, AmbiguousTy)) {
296 // InstType is successfully determined and is same as for AdjMI.
297 setTypes(MI, getRecordedTypeForInstr(AdjMI));
298 return true;
302 return false;
305 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
306 InstType InstTy) {
307 changeRecordedTypeForInstr(MI, InstTy);
308 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
309 setTypes(WaitingInstr, InstTy);
313 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
314 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
315 assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&
316 "Copies of non physical registers should not be considered here.\n");
318 const MachineFunction &MF = *CopyInst->getMF();
319 const MachineRegisterInfo &MRI = MF.getRegInfo();
320 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
321 const RegisterBankInfo &RBI =
322 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
323 const RegisterBank *Bank =
324 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
326 if (Bank == &Mips::FPRBRegBank)
327 setTypes(MI, InstType::FloatingPoint);
328 else if (Bank == &Mips::GPRBRegBank)
329 setTypes(MI, InstType::Integer);
330 else
331 llvm_unreachable("Unsupported register bank.\n");
334 MipsRegisterBankInfo::InstType
335 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
336 InstType DefaultAmbiguousType = InstType::Ambiguous;
337 visit(MI, nullptr, DefaultAmbiguousType);
338 return getRecordedTypeForInstr(MI);
341 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
342 llvm::StringRef FunctionName) {
343 if (MFName != FunctionName) {
344 MFName = std::string(FunctionName);
345 WaitingQueues.clear();
346 Types.clear();
350 static const MipsRegisterBankInfo::ValueMapping *
351 getMSAMapping(const MachineFunction &MF) {
352 assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
353 "MSA mapping not available on target without MSA.");
354 return &Mips::ValueMappings[Mips::MSAIdx];
357 static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
358 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
359 : &Mips::ValueMappings[Mips::DPRIdx];
362 static const unsigned CustomMappingID = 1;
364 // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
365 // will be split into two 32 bit registers in gprb.
366 static const MipsRegisterBankInfo::ValueMapping *
367 getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
368 if (Size == 32)
369 return &Mips::ValueMappings[Mips::GPRIdx];
371 MappingID = CustomMappingID;
372 return &Mips::ValueMappings[Mips::DPRIdx];
375 const RegisterBankInfo::InstructionMapping &
376 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
378 static TypeInfoForMF TI;
380 // Reset TI internal data when MF changes.
381 TI.cleanupIfNewFunction(MI.getMF()->getName());
383 unsigned Opc = MI.getOpcode();
384 const MachineFunction &MF = *MI.getParent()->getParent();
385 const MachineRegisterInfo &MRI = MF.getRegInfo();
387 if (MI.getOpcode() != TargetOpcode::G_PHI) {
388 const RegisterBankInfo::InstructionMapping &Mapping =
389 getInstrMappingImpl(MI);
390 if (Mapping.isValid())
391 return Mapping;
394 using namespace TargetOpcode;
396 unsigned NumOperands = MI.getNumOperands();
397 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
398 unsigned MappingID = DefaultMappingID;
400 // Check if LLT sizes match sizes of available register banks.
401 for (const MachineOperand &Op : MI.operands()) {
402 if (Op.isReg()) {
403 LLT RegTy = MRI.getType(Op.getReg());
405 if (RegTy.isScalar() &&
406 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
407 return getInvalidInstructionMapping();
409 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
410 return getInvalidInstructionMapping();
414 const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
415 unsigned Op0Size = Op0Ty.getSizeInBits();
416 InstType InstTy = InstType::Integer;
418 switch (Opc) {
419 case G_TRUNC:
420 case G_UMULH:
421 case G_ZEXTLOAD:
422 case G_SEXTLOAD:
423 case G_PTR_ADD:
424 case G_INTTOPTR:
425 case G_PTRTOINT:
426 case G_AND:
427 case G_OR:
428 case G_XOR:
429 case G_SHL:
430 case G_ASHR:
431 case G_LSHR:
432 case G_BRINDIRECT:
433 case G_VASTART:
434 case G_BSWAP:
435 case G_CTLZ:
436 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
437 break;
438 case G_ADD:
439 case G_SUB:
440 case G_MUL:
441 case G_SDIV:
442 case G_SREM:
443 case G_UDIV:
444 case G_UREM:
445 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
446 if (Op0Size == 128)
447 OperandsMapping = getMSAMapping(MF);
448 break;
449 case G_STORE:
450 case G_LOAD: {
451 if (Op0Size == 128) {
452 OperandsMapping = getOperandsMapping(
453 {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
454 break;
457 if (!Op0Ty.isPointer())
458 InstTy = TI.determineInstType(&MI);
460 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
461 isAmbiguous_64(InstTy, Op0Size)) {
462 OperandsMapping = getOperandsMapping(
463 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
464 } else {
465 assert((isInteger_32(InstTy, Op0Size) ||
466 isAmbiguous_32(InstTy, Op0Size) ||
467 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
468 "Unexpected Inst type");
469 OperandsMapping =
470 getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
471 &Mips::ValueMappings[Mips::GPRIdx]});
474 break;
476 case G_PHI: {
477 if (!Op0Ty.isPointer())
478 InstTy = TI.determineInstType(&MI);
480 // PHI is copylike and should have one regbank in mapping for def register.
481 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
482 OperandsMapping =
483 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
484 TI.clearTypeInfoData(&MI);
485 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
486 /*NumOperands=*/1);
488 assert((isInteger_32(InstTy, Op0Size) ||
489 isFloatingPoint_32or64(InstTy, Op0Size) ||
490 isAmbiguous_32or64(InstTy, Op0Size)) &&
491 "Unexpected Inst type");
492 // Use default handling for PHI, i.e. set reg bank of def operand to match
493 // register banks of use operands.
494 return getInstrMappingImpl(MI);
496 case G_SELECT: {
497 if (!Op0Ty.isPointer())
498 InstTy = TI.determineInstType(&MI);
499 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
500 isAmbiguous_64(InstTy, Op0Size)) {
501 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
502 OperandsMapping = getOperandsMapping(
503 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
504 break;
505 } else {
506 assert((isInteger_32(InstTy, Op0Size) ||
507 isAmbiguous_32(InstTy, Op0Size) ||
508 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
509 "Unexpected Inst type");
510 const RegisterBankInfo::ValueMapping *Bank =
511 getGprbOrCustomMapping(Op0Size, MappingID);
512 OperandsMapping = getOperandsMapping(
513 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
515 break;
517 case G_IMPLICIT_DEF: {
518 if (!Op0Ty.isPointer())
519 InstTy = TI.determineInstType(&MI);
521 if (isFloatingPoint_32or64(InstTy, Op0Size))
522 OperandsMapping = getFprbMapping(Op0Size);
523 else {
524 assert((isInteger_32(InstTy, Op0Size) ||
525 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
526 "Unexpected Inst type");
527 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
529 } break;
530 case G_UNMERGE_VALUES: {
531 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
532 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
533 InstTy = TI.determineInstType(&MI);
534 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
535 isFloatingPoint_64(InstTy, Op3Size)) &&
536 "Unexpected Inst type");
537 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
538 &Mips::ValueMappings[Mips::GPRIdx],
539 &Mips::ValueMappings[Mips::DPRIdx]});
540 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
541 MappingID = CustomMappingID;
542 break;
544 case G_MERGE_VALUES: {
545 InstTy = TI.determineInstType(&MI);
546 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
547 isFloatingPoint_64(InstTy, Op0Size)) &&
548 "Unexpected Inst type");
549 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
550 &Mips::ValueMappings[Mips::GPRIdx],
551 &Mips::ValueMappings[Mips::GPRIdx]});
552 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
553 MappingID = CustomMappingID;
554 break;
556 case G_FADD:
557 case G_FSUB:
558 case G_FMUL:
559 case G_FDIV:
560 case G_FABS:
561 case G_FSQRT:
562 OperandsMapping = getFprbMapping(Op0Size);
563 if (Op0Size == 128)
564 OperandsMapping = getMSAMapping(MF);
565 break;
566 case G_FCONSTANT:
567 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
568 break;
569 case G_FCMP: {
570 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
571 OperandsMapping =
572 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
573 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
574 break;
576 case G_FPEXT:
577 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
578 &Mips::ValueMappings[Mips::SPRIdx]});
579 break;
580 case G_FPTRUNC:
581 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
582 &Mips::ValueMappings[Mips::DPRIdx]});
583 break;
584 case G_FPTOSI: {
585 assert((Op0Size == 32) && "Unsupported integer size");
586 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
587 OperandsMapping = getOperandsMapping(
588 {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
589 break;
591 case G_SITOFP:
592 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
593 "Unsupported integer size");
594 OperandsMapping = getOperandsMapping(
595 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
596 break;
597 case G_CONSTANT:
598 case G_FRAME_INDEX:
599 case G_GLOBAL_VALUE:
600 case G_JUMP_TABLE:
601 case G_BRCOND:
602 OperandsMapping =
603 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
604 break;
605 case G_BRJT:
606 OperandsMapping =
607 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
608 &Mips::ValueMappings[Mips::GPRIdx]});
609 break;
610 case G_ICMP:
611 OperandsMapping =
612 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
613 &Mips::ValueMappings[Mips::GPRIdx],
614 &Mips::ValueMappings[Mips::GPRIdx]});
615 break;
616 default:
617 return getInvalidInstructionMapping();
620 if (MappingID == CustomMappingID)
621 TI.clearTypeInfoData(&MI);
622 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
623 NumOperands);
626 using InstListTy = GISelWorkList<4>;
627 namespace {
628 class InstManager : public GISelChangeObserver {
629 InstListTy &InstList;
630 MachineIRBuilder &B;
632 public:
633 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
634 assert(!B.isObservingChanges());
635 B.setChangeObserver(*this);
638 ~InstManager() { B.stopObservingChanges(); }
640 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
641 void erasingInstr(MachineInstr &MI) override {}
642 void changingInstr(MachineInstr &MI) override {}
643 void changedInstr(MachineInstr &MI) override {}
645 } // end anonymous namespace
647 void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
648 MachineRegisterInfo &MRI) const {
649 Register Dest = MI.getOperand(0).getReg();
650 switch (MI.getOpcode()) {
651 case TargetOpcode::G_STORE:
652 // No def operands, skip this instruction.
653 break;
654 case TargetOpcode::G_CONSTANT:
655 case TargetOpcode::G_LOAD:
656 case TargetOpcode::G_SELECT:
657 case TargetOpcode::G_PHI:
658 case TargetOpcode::G_IMPLICIT_DEF: {
659 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
660 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
661 break;
663 case TargetOpcode::G_PTR_ADD: {
664 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
665 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
666 break;
668 default:
669 llvm_unreachable("Unexpected opcode.");
673 static void
674 combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
675 GUnmerge &MI, GISelChangeObserver &Observer) {
676 SmallVector<Register, 4> UpdatedDefs;
677 SmallVector<MachineInstr *, 2> DeadInstrs;
678 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
679 UpdatedDefs, Observer);
680 for (MachineInstr *DeadMI : DeadInstrs)
681 DeadMI->eraseFromParent();
684 void MipsRegisterBankInfo::applyMappingImpl(
685 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
686 MachineInstr &MI = OpdMapper.getMI();
687 Builder.setInstrAndDebugLoc(MI);
689 InstListTy NewInstrs;
690 MachineFunction *MF = MI.getMF();
691 MachineRegisterInfo &MRI = OpdMapper.getMRI();
692 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
694 InstManager NewInstrObserver(Builder, NewInstrs);
695 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
696 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
698 switch (MI.getOpcode()) {
699 case TargetOpcode::G_LOAD:
700 case TargetOpcode::G_STORE:
701 case TargetOpcode::G_PHI:
702 case TargetOpcode::G_SELECT:
703 case TargetOpcode::G_IMPLICIT_DEF: {
704 Helper.narrowScalar(MI, 0, LLT::scalar(32));
705 // Handle new instructions.
706 while (!NewInstrs.empty()) {
707 MachineInstr *NewMI = NewInstrs.pop_back_val();
708 // This is new G_UNMERGE that was created during narrowScalar and will
709 // not be considered for regbank selection. RegBankSelect for mips
710 // visits/makes corresponding G_MERGE first. Combine them here.
711 if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
712 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
713 // This G_MERGE will be combined away when its corresponding G_UNMERGE
714 // gets regBankSelected.
715 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
716 continue;
717 else
718 // Manually set register banks for def operands to 32 bit gprb.
719 setRegBank(*NewMI, MRI);
721 return;
723 case TargetOpcode::G_UNMERGE_VALUES:
724 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
725 NewInstrObserver);
726 return;
727 default:
728 break;
731 return applyDefaultMapping(OpdMapper);