Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / lib / Target / Mips / MipsRegisterBankInfo.cpp
blobeeefafbaf6332062d17b5914573b3f6da8e46b6c
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) {}
78 const RegisterBank &
79 MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
80 LLT) 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 return true;
135 default:
136 return isFloatingPointOpcode(Opc);
140 // Instructions where def operands are floating point registers.
141 // Use operands are general purpose.
142 static bool isFloatingPointOpcodeDef(unsigned Opc) {
143 switch (Opc) {
144 case TargetOpcode::G_SITOFP:
145 case TargetOpcode::G_UITOFP:
146 return true;
147 default:
148 return isFloatingPointOpcode(Opc);
152 static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
153 if (MI->getOpcode() == TargetOpcode::G_LOAD ||
154 MI->getOpcode() == TargetOpcode::G_STORE) {
155 auto MMO = *MI->memoperands_begin();
156 const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
157 if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
158 MMO->getAlign() < MMO->getSize()))
159 return true;
161 return false;
164 static bool isAmbiguous(unsigned Opc) {
165 switch (Opc) {
166 case TargetOpcode::G_LOAD:
167 case TargetOpcode::G_STORE:
168 case TargetOpcode::G_PHI:
169 case TargetOpcode::G_SELECT:
170 case TargetOpcode::G_IMPLICIT_DEF:
171 case TargetOpcode::G_UNMERGE_VALUES:
172 case TargetOpcode::G_MERGE_VALUES:
173 return true;
174 default:
175 return false;
179 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
180 Register Reg, const MachineRegisterInfo &MRI) {
181 assert(!MRI.getType(Reg).isPointer() &&
182 "Pointers are gprb, they should not be considered as ambiguous.\n");
183 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
184 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
185 // Copy with many uses.
186 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
187 !NonCopyInstr->getOperand(0).getReg().isPhysical())
188 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
189 else
190 DefUses.push_back(skipCopiesOutgoing(&UseMI));
194 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
195 Register Reg, const MachineRegisterInfo &MRI) {
196 assert(!MRI.getType(Reg).isPointer() &&
197 "Pointers are gprb, they should not be considered as ambiguous.\n");
198 MachineInstr *DefMI = MRI.getVRegDef(Reg);
199 UseDefs.push_back(skipCopiesIncoming(DefMI));
202 MachineInstr *
203 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
204 MachineInstr *MI) const {
205 const MachineFunction &MF = *MI->getParent()->getParent();
206 const MachineRegisterInfo &MRI = MF.getRegInfo();
207 MachineInstr *Ret = MI;
208 while (Ret->getOpcode() == TargetOpcode::COPY &&
209 !Ret->getOperand(0).getReg().isPhysical() &&
210 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
211 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
213 return Ret;
216 MachineInstr *
217 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
218 MachineInstr *MI) const {
219 const MachineFunction &MF = *MI->getParent()->getParent();
220 const MachineRegisterInfo &MRI = MF.getRegInfo();
221 MachineInstr *Ret = MI;
222 while (Ret->getOpcode() == TargetOpcode::COPY &&
223 !Ret->getOperand(1).getReg().isPhysical())
224 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
225 return Ret;
228 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
229 const MachineInstr *MI) {
230 assert(isAmbiguous(MI->getOpcode()) &&
231 "Not implemented for non Ambiguous opcode.\n");
233 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
235 if (MI->getOpcode() == TargetOpcode::G_LOAD)
236 addDefUses(MI->getOperand(0).getReg(), MRI);
238 if (MI->getOpcode() == TargetOpcode::G_STORE)
239 addUseDef(MI->getOperand(0).getReg(), MRI);
241 if (MI->getOpcode() == TargetOpcode::G_PHI) {
242 addDefUses(MI->getOperand(0).getReg(), MRI);
244 for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
245 addUseDef(MI->getOperand(i).getReg(), MRI);
248 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
249 addDefUses(MI->getOperand(0).getReg(), MRI);
251 addUseDef(MI->getOperand(2).getReg(), MRI);
252 addUseDef(MI->getOperand(3).getReg(), MRI);
255 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
256 addDefUses(MI->getOperand(0).getReg(), MRI);
258 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
259 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
261 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
262 addDefUses(MI->getOperand(0).getReg(), MRI);
265 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
266 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
267 InstType &AmbiguousTy) {
268 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
269 if (wasVisited(MI))
270 return true; // InstType has already been determined for MI.
272 startVisit(MI);
273 AmbiguousRegDefUseContainer DefUseContainer(MI);
275 if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
276 setTypes(MI, Integer);
277 return true;
280 if (AmbiguousTy == InstType::Ambiguous &&
281 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
282 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
283 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
285 // Visit instructions where MI's DEF operands are USED.
286 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
287 return true;
289 // Visit instructions that DEFINE MI's USE operands.
290 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
291 return true;
293 // All MI's adjacent instructions, are ambiguous.
294 if (!WaitingForTypeOfMI) {
295 // This is chain of ambiguous instructions.
296 setTypes(MI, AmbiguousTy);
297 return true;
299 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
300 // instructions or has no other adjacent instructions. Anyway InstType could
301 // not be determined. There could be unexplored path from some of
302 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
303 // mapping available.
304 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
305 // this way when WaitingForTypeOfMI figures out its InstType same InstType
306 // will be assigned to all instructions in this branch.
307 addToWaitingQueue(WaitingForTypeOfMI, MI);
308 return false;
311 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
312 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
313 bool isDefUse, InstType &AmbiguousTy) {
314 while (!AdjacentInstrs.empty()) {
315 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
317 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
318 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
319 setTypes(MI, InstType::FloatingPoint);
320 return true;
323 // Determine InstType from register bank of phys register that is
324 // 'isDefUse ? def : use' of this copy.
325 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
326 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
327 return true;
330 // Defaults to integer instruction. Small registers in G_MERGE (uses) and
331 // G_UNMERGE (defs) will always be gprb.
332 if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
333 (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
334 !isAmbiguous(AdjMI->getOpcode())) {
335 setTypes(MI, InstType::Integer);
336 return true;
339 // When AdjMI was visited first, MI has to continue to explore remaining
340 // adjacent instructions and determine InstType without visiting AdjMI.
341 if (!wasVisited(AdjMI) ||
342 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
343 if (visit(AdjMI, MI, AmbiguousTy)) {
344 // InstType is successfully determined and is same as for AdjMI.
345 setTypes(MI, getRecordedTypeForInstr(AdjMI));
346 return true;
350 return false;
353 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
354 InstType InstTy) {
355 changeRecordedTypeForInstr(MI, InstTy);
356 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
357 setTypes(WaitingInstr, InstTy);
361 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
362 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
363 assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&
364 "Copies of non physical registers should not be considered here.\n");
366 const MachineFunction &MF = *CopyInst->getMF();
367 const MachineRegisterInfo &MRI = MF.getRegInfo();
368 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
369 const RegisterBankInfo &RBI =
370 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
371 const RegisterBank *Bank =
372 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
374 if (Bank == &Mips::FPRBRegBank)
375 setTypes(MI, InstType::FloatingPoint);
376 else if (Bank == &Mips::GPRBRegBank)
377 setTypes(MI, InstType::Integer);
378 else
379 llvm_unreachable("Unsupported register bank.\n");
382 MipsRegisterBankInfo::InstType
383 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
384 InstType DefaultAmbiguousType = InstType::Ambiguous;
385 visit(MI, nullptr, DefaultAmbiguousType);
386 return getRecordedTypeForInstr(MI);
389 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
390 llvm::StringRef FunctionName) {
391 if (MFName != FunctionName) {
392 MFName = std::string(FunctionName);
393 WaitingQueues.clear();
394 Types.clear();
398 static const MipsRegisterBankInfo::ValueMapping *
399 getMSAMapping(const MachineFunction &MF) {
400 assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
401 "MSA mapping not available on target without MSA.");
402 return &Mips::ValueMappings[Mips::MSAIdx];
405 static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
406 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
407 : &Mips::ValueMappings[Mips::DPRIdx];
410 static const unsigned CustomMappingID = 1;
412 // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
413 // will be split into two 32 bit registers in gprb.
414 static const MipsRegisterBankInfo::ValueMapping *
415 getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
416 if (Size == 32)
417 return &Mips::ValueMappings[Mips::GPRIdx];
419 MappingID = CustomMappingID;
420 return &Mips::ValueMappings[Mips::DPRIdx];
423 const RegisterBankInfo::InstructionMapping &
424 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
426 static TypeInfoForMF TI;
428 // Reset TI internal data when MF changes.
429 TI.cleanupIfNewFunction(MI.getMF()->getName());
431 unsigned Opc = MI.getOpcode();
432 const MachineFunction &MF = *MI.getParent()->getParent();
433 const MachineRegisterInfo &MRI = MF.getRegInfo();
435 if (MI.getOpcode() != TargetOpcode::G_PHI) {
436 const RegisterBankInfo::InstructionMapping &Mapping =
437 getInstrMappingImpl(MI);
438 if (Mapping.isValid())
439 return Mapping;
442 using namespace TargetOpcode;
444 unsigned NumOperands = MI.getNumOperands();
445 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
446 unsigned MappingID = DefaultMappingID;
448 // Check if LLT sizes match sizes of available register banks.
449 for (const MachineOperand &Op : MI.operands()) {
450 if (Op.isReg()) {
451 LLT RegTy = MRI.getType(Op.getReg());
453 if (RegTy.isScalar() &&
454 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
455 return getInvalidInstructionMapping();
457 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
458 return getInvalidInstructionMapping();
462 const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
463 unsigned Op0Size = Op0Ty.getSizeInBits();
464 InstType InstTy = InstType::Integer;
466 switch (Opc) {
467 case G_TRUNC:
468 case G_UMULH:
469 case G_ZEXTLOAD:
470 case G_SEXTLOAD:
471 case G_PTR_ADD:
472 case G_INTTOPTR:
473 case G_PTRTOINT:
474 case G_AND:
475 case G_OR:
476 case G_XOR:
477 case G_SHL:
478 case G_ASHR:
479 case G_LSHR:
480 case G_BRINDIRECT:
481 case G_VASTART:
482 case G_BSWAP:
483 case G_CTLZ:
484 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
485 break;
486 case G_ADD:
487 case G_SUB:
488 case G_MUL:
489 case G_SDIV:
490 case G_SREM:
491 case G_UDIV:
492 case G_UREM:
493 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
494 if (Op0Size == 128)
495 OperandsMapping = getMSAMapping(MF);
496 break;
497 case G_STORE:
498 case G_LOAD: {
499 if (Op0Size == 128) {
500 OperandsMapping = getOperandsMapping(
501 {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
502 break;
505 if (!Op0Ty.isPointer())
506 InstTy = TI.determineInstType(&MI);
508 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
509 isAmbiguous_64(InstTy, Op0Size)) {
510 OperandsMapping = getOperandsMapping(
511 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
512 } else {
513 assert((isInteger_32(InstTy, Op0Size) ||
514 isAmbiguous_32(InstTy, Op0Size) ||
515 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
516 "Unexpected Inst type");
517 OperandsMapping =
518 getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
519 &Mips::ValueMappings[Mips::GPRIdx]});
522 break;
524 case G_PHI: {
525 if (!Op0Ty.isPointer())
526 InstTy = TI.determineInstType(&MI);
528 // PHI is copylike and should have one regbank in mapping for def register.
529 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
530 OperandsMapping =
531 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
532 TI.clearTypeInfoData(&MI);
533 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
534 /*NumOperands=*/1);
536 assert((isInteger_32(InstTy, Op0Size) ||
537 isFloatingPoint_32or64(InstTy, Op0Size) ||
538 isAmbiguous_32or64(InstTy, Op0Size)) &&
539 "Unexpected Inst type");
540 // Use default handling for PHI, i.e. set reg bank of def operand to match
541 // register banks of use operands.
542 return getInstrMappingImpl(MI);
544 case G_SELECT: {
545 if (!Op0Ty.isPointer())
546 InstTy = TI.determineInstType(&MI);
547 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
548 isAmbiguous_64(InstTy, Op0Size)) {
549 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
550 OperandsMapping = getOperandsMapping(
551 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
552 break;
553 } else {
554 assert((isInteger_32(InstTy, Op0Size) ||
555 isAmbiguous_32(InstTy, Op0Size) ||
556 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
557 "Unexpected Inst type");
558 const RegisterBankInfo::ValueMapping *Bank =
559 getGprbOrCustomMapping(Op0Size, MappingID);
560 OperandsMapping = getOperandsMapping(
561 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
563 break;
565 case G_IMPLICIT_DEF: {
566 if (!Op0Ty.isPointer())
567 InstTy = TI.determineInstType(&MI);
569 if (isFloatingPoint_32or64(InstTy, Op0Size))
570 OperandsMapping = getFprbMapping(Op0Size);
571 else {
572 assert((isInteger_32(InstTy, Op0Size) ||
573 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
574 "Unexpected Inst type");
575 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
577 } break;
578 case G_UNMERGE_VALUES: {
579 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
580 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
581 InstTy = TI.determineInstType(&MI);
582 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
583 isFloatingPoint_64(InstTy, Op3Size)) &&
584 "Unexpected Inst type");
585 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
586 &Mips::ValueMappings[Mips::GPRIdx],
587 &Mips::ValueMappings[Mips::DPRIdx]});
588 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
589 MappingID = CustomMappingID;
590 break;
592 case G_MERGE_VALUES: {
593 InstTy = TI.determineInstType(&MI);
594 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
595 isFloatingPoint_64(InstTy, Op0Size)) &&
596 "Unexpected Inst type");
597 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
598 &Mips::ValueMappings[Mips::GPRIdx],
599 &Mips::ValueMappings[Mips::GPRIdx]});
600 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
601 MappingID = CustomMappingID;
602 break;
604 case G_FADD:
605 case G_FSUB:
606 case G_FMUL:
607 case G_FDIV:
608 case G_FABS:
609 case G_FSQRT:
610 OperandsMapping = getFprbMapping(Op0Size);
611 if (Op0Size == 128)
612 OperandsMapping = getMSAMapping(MF);
613 break;
614 case G_FCONSTANT:
615 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
616 break;
617 case G_FCMP: {
618 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
619 OperandsMapping =
620 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
621 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
622 break;
624 case G_FPEXT:
625 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
626 &Mips::ValueMappings[Mips::SPRIdx]});
627 break;
628 case G_FPTRUNC:
629 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
630 &Mips::ValueMappings[Mips::DPRIdx]});
631 break;
632 case G_FPTOSI: {
633 assert((Op0Size == 32) && "Unsupported integer size");
634 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
635 OperandsMapping = getOperandsMapping(
636 {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
637 break;
639 case G_SITOFP:
640 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
641 "Unsupported integer size");
642 OperandsMapping = getOperandsMapping(
643 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
644 break;
645 case G_CONSTANT:
646 case G_FRAME_INDEX:
647 case G_GLOBAL_VALUE:
648 case G_JUMP_TABLE:
649 case G_BRCOND:
650 OperandsMapping =
651 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
652 break;
653 case G_BRJT:
654 OperandsMapping =
655 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
656 &Mips::ValueMappings[Mips::GPRIdx]});
657 break;
658 case G_ICMP:
659 OperandsMapping =
660 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
661 &Mips::ValueMappings[Mips::GPRIdx],
662 &Mips::ValueMappings[Mips::GPRIdx]});
663 break;
664 default:
665 return getInvalidInstructionMapping();
668 if (MappingID == CustomMappingID)
669 TI.clearTypeInfoData(&MI);
670 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
671 NumOperands);
674 using InstListTy = GISelWorkList<4>;
675 namespace {
676 class InstManager : public GISelChangeObserver {
677 InstListTy &InstList;
678 MachineIRBuilder &B;
680 public:
681 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
682 assert(!B.isObservingChanges());
683 B.setChangeObserver(*this);
686 ~InstManager() { B.stopObservingChanges(); }
688 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
689 void erasingInstr(MachineInstr &MI) override {}
690 void changingInstr(MachineInstr &MI) override {}
691 void changedInstr(MachineInstr &MI) override {}
693 } // end anonymous namespace
695 void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
696 MachineRegisterInfo &MRI) const {
697 Register Dest = MI.getOperand(0).getReg();
698 switch (MI.getOpcode()) {
699 case TargetOpcode::G_STORE:
700 // No def operands, skip this instruction.
701 break;
702 case TargetOpcode::G_CONSTANT:
703 case TargetOpcode::G_LOAD:
704 case TargetOpcode::G_SELECT:
705 case TargetOpcode::G_PHI:
706 case TargetOpcode::G_IMPLICIT_DEF: {
707 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
708 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
709 break;
711 case TargetOpcode::G_PTR_ADD: {
712 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
713 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
714 break;
716 default:
717 llvm_unreachable("Unexpected opcode.");
721 static void
722 combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
723 GUnmerge &MI, GISelChangeObserver &Observer) {
724 SmallVector<Register, 4> UpdatedDefs;
725 SmallVector<MachineInstr *, 2> DeadInstrs;
726 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
727 UpdatedDefs, Observer);
728 for (MachineInstr *DeadMI : DeadInstrs)
729 DeadMI->eraseFromParent();
732 void MipsRegisterBankInfo::applyMappingImpl(
733 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
734 MachineInstr &MI = OpdMapper.getMI();
735 Builder.setInstrAndDebugLoc(MI);
737 InstListTy NewInstrs;
738 MachineFunction *MF = MI.getMF();
739 MachineRegisterInfo &MRI = OpdMapper.getMRI();
740 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
742 InstManager NewInstrObserver(Builder, NewInstrs);
743 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
744 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
746 switch (MI.getOpcode()) {
747 case TargetOpcode::G_LOAD:
748 case TargetOpcode::G_STORE:
749 case TargetOpcode::G_PHI:
750 case TargetOpcode::G_SELECT:
751 case TargetOpcode::G_IMPLICIT_DEF: {
752 Helper.narrowScalar(MI, 0, LLT::scalar(32));
753 // Handle new instructions.
754 while (!NewInstrs.empty()) {
755 MachineInstr *NewMI = NewInstrs.pop_back_val();
756 // This is new G_UNMERGE that was created during narrowScalar and will
757 // not be considered for regbank selection. RegBankSelect for mips
758 // visits/makes corresponding G_MERGE first. Combine them here.
759 if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
760 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
761 // This G_MERGE will be combined away when its corresponding G_UNMERGE
762 // gets regBankSelected.
763 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
764 continue;
765 else
766 // Manually set register banks for def operands to 32 bit gprb.
767 setRegBank(*NewMI, MRI);
769 return;
771 case TargetOpcode::G_UNMERGE_VALUES:
772 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
773 NewInstrObserver);
774 return;
775 default:
776 break;
779 return applyDefaultMapping(OpdMapper);