[ARM] VQADD instructions
[llvm-complete.git] / lib / Target / Mips / MipsRegisterBankInfo.cpp
blobf8ce80b044cc3586156cdd35890557c8ac45b960
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 "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
16 #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #define GET_TARGET_REGBANK_IMPL
22 #include "MipsGenRegisterBank.inc"
24 namespace llvm {
25 namespace Mips {
26 enum PartialMappingIdx {
27 PMI_GPR,
28 PMI_SPR,
29 PMI_DPR,
30 PMI_Min = PMI_GPR,
33 RegisterBankInfo::PartialMapping PartMappings[]{
34 {0, 32, GPRBRegBank},
35 {0, 32, FPRBRegBank},
36 {0, 64, FPRBRegBank}
39 enum ValueMappingIdx {
40 InvalidIdx = 0,
41 GPRIdx = 1,
42 SPRIdx = 4,
43 DPRIdx = 7
46 RegisterBankInfo::ValueMapping ValueMappings[] = {
47 // invalid
48 {nullptr, 0},
49 // up to 3 operands in GPRs
50 {&PartMappings[PMI_GPR - PMI_Min], 1},
51 {&PartMappings[PMI_GPR - PMI_Min], 1},
52 {&PartMappings[PMI_GPR - PMI_Min], 1},
53 // up to 3 ops operands FPRs - single precission
54 {&PartMappings[PMI_SPR - PMI_Min], 1},
55 {&PartMappings[PMI_SPR - PMI_Min], 1},
56 {&PartMappings[PMI_SPR - PMI_Min], 1},
57 // up to 3 ops operands FPRs - double precission
58 {&PartMappings[PMI_DPR - PMI_Min], 1},
59 {&PartMappings[PMI_DPR - PMI_Min], 1},
60 {&PartMappings[PMI_DPR - PMI_Min], 1}
63 } // end namespace Mips
64 } // end namespace llvm
66 using namespace llvm;
68 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
69 : MipsGenRegisterBankInfo() {}
71 const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
72 const TargetRegisterClass &RC) const {
73 using namespace Mips;
75 switch (RC.getID()) {
76 case Mips::GPR32RegClassID:
77 case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
78 case Mips::GPRMM16MovePPairFirstRegClassID:
79 case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
80 case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
81 case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
82 case Mips::SP32RegClassID:
83 case Mips::GP32RegClassID:
84 return getRegBank(Mips::GPRBRegBankID);
85 case Mips::FGRCCRegClassID:
86 case Mips::FGR32RegClassID:
87 case Mips::FGR64RegClassID:
88 case Mips::AFGR64RegClassID:
89 return getRegBank(Mips::FPRBRegBankID);
90 default:
91 llvm_unreachable("Register class not supported");
95 // Instructions where all register operands are floating point.
96 static bool isFloatingPointOpcode(unsigned Opc) {
97 switch (Opc) {
98 case TargetOpcode::G_FCONSTANT:
99 case TargetOpcode::G_FADD:
100 case TargetOpcode::G_FSUB:
101 case TargetOpcode::G_FMUL:
102 case TargetOpcode::G_FDIV:
103 case TargetOpcode::G_FABS:
104 case TargetOpcode::G_FSQRT:
105 case TargetOpcode::G_FCEIL:
106 case TargetOpcode::G_FFLOOR:
107 case TargetOpcode::G_FPEXT:
108 case TargetOpcode::G_FPTRUNC:
109 return true;
110 default:
111 return false;
115 // Instructions where use operands are floating point registers.
116 // Def operands are general purpose.
117 static bool isFloatingPointOpcodeUse(unsigned Opc) {
118 switch (Opc) {
119 case TargetOpcode::G_FPTOSI:
120 case TargetOpcode::G_FPTOUI:
121 case TargetOpcode::G_FCMP:
122 case Mips::MFC1:
123 case Mips::ExtractElementF64:
124 case Mips::ExtractElementF64_64:
125 return true;
126 default:
127 return isFloatingPointOpcode(Opc);
131 // Instructions where def operands are floating point registers.
132 // Use operands are general purpose.
133 static bool isFloatingPointOpcodeDef(unsigned Opc) {
134 switch (Opc) {
135 case TargetOpcode::G_SITOFP:
136 case TargetOpcode::G_UITOFP:
137 case Mips::MTC1:
138 case Mips::BuildPairF64:
139 case Mips::BuildPairF64_64:
140 return true;
141 default:
142 return isFloatingPointOpcode(Opc);
146 static bool isAmbiguous(unsigned Opc) {
147 switch (Opc) {
148 case TargetOpcode::G_LOAD:
149 case TargetOpcode::G_STORE:
150 case TargetOpcode::G_PHI:
151 case TargetOpcode::G_SELECT:
152 case TargetOpcode::G_IMPLICIT_DEF:
153 return true;
154 default:
155 return false;
159 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
160 Register Reg, const MachineRegisterInfo &MRI) {
161 assert(!MRI.getType(Reg).isPointer() &&
162 "Pointers are gprb, they should not be considered as ambiguous.\n");
163 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
164 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
165 // Copy with many uses.
166 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
167 !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
168 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
169 else
170 DefUses.push_back(skipCopiesOutgoing(&UseMI));
174 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
175 Register Reg, const MachineRegisterInfo &MRI) {
176 assert(!MRI.getType(Reg).isPointer() &&
177 "Pointers are gprb, they should not be considered as ambiguous.\n");
178 MachineInstr *DefMI = MRI.getVRegDef(Reg);
179 UseDefs.push_back(skipCopiesIncoming(DefMI));
182 MachineInstr *
183 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
184 MachineInstr *MI) const {
185 const MachineFunction &MF = *MI->getParent()->getParent();
186 const MachineRegisterInfo &MRI = MF.getRegInfo();
187 MachineInstr *Ret = MI;
188 while (Ret->getOpcode() == TargetOpcode::COPY &&
189 !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
190 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
191 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
193 return Ret;
196 MachineInstr *
197 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
198 MachineInstr *MI) const {
199 const MachineFunction &MF = *MI->getParent()->getParent();
200 const MachineRegisterInfo &MRI = MF.getRegInfo();
201 MachineInstr *Ret = MI;
202 while (Ret->getOpcode() == TargetOpcode::COPY &&
203 !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
204 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
205 return Ret;
208 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
209 const MachineInstr *MI) {
210 assert(isAmbiguous(MI->getOpcode()) &&
211 "Not implemented for non Ambiguous opcode.\n");
213 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
215 if (MI->getOpcode() == TargetOpcode::G_LOAD)
216 addDefUses(MI->getOperand(0).getReg(), MRI);
218 if (MI->getOpcode() == TargetOpcode::G_STORE)
219 addUseDef(MI->getOperand(0).getReg(), MRI);
221 if (MI->getOpcode() == TargetOpcode::G_PHI) {
222 addDefUses(MI->getOperand(0).getReg(), MRI);
224 for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
225 addUseDef(MI->getOperand(i).getReg(), MRI);
228 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
229 addDefUses(MI->getOperand(0).getReg(), MRI);
231 addUseDef(MI->getOperand(2).getReg(), MRI);
232 addUseDef(MI->getOperand(3).getReg(), MRI);
235 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
236 addDefUses(MI->getOperand(0).getReg(), MRI);
239 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
240 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) {
241 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
242 if (wasVisited(MI))
243 return true; // InstType has already been determined for MI.
245 startVisit(MI);
246 AmbiguousRegDefUseContainer DefUseContainer(MI);
248 // Visit instructions where MI's DEF operands are USED.
249 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true))
250 return true;
252 // Visit instructions that DEFINE MI's USE operands.
253 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false))
254 return true;
256 // All MI's adjacent instructions, are ambiguous.
257 if (!WaitingForTypeOfMI) {
258 // This is chain of ambiguous instructions.
259 setTypes(MI, InstType::Ambiguous);
260 return true;
262 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
263 // instructions or has no other adjacent instructions. Anyway InstType could
264 // not be determined. There could be unexplored path from some of
265 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
266 // mapping available.
267 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
268 // this way when WaitingForTypeOfMI figures out its InstType same InstType
269 // will be assigned to all instructions in this branch.
270 addToWaitingQueue(WaitingForTypeOfMI, MI);
271 return false;
274 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
275 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
276 bool isDefUse) {
277 while (!AdjacentInstrs.empty()) {
278 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
280 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
281 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
282 setTypes(MI, InstType::FloatingPoint);
283 return true;
286 // Determine InstType from register bank of phys register that is
287 // 'isDefUse ? def : use' of this copy.
288 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
289 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
290 return true;
293 // Defaults to integer instruction. Includes G_MERGE_VALUES and
294 // G_UNMERGE_VALUES.
295 if (!isAmbiguous(AdjMI->getOpcode())) {
296 setTypes(MI, InstType::Integer);
297 return true;
300 // When AdjMI was visited first, MI has to continue to explore remaining
301 // adjacent instructions and determine InstType without visiting AdjMI.
302 if (!wasVisited(AdjMI) ||
303 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
304 if (visit(AdjMI, MI)) {
305 // InstType is successfully determined and is same as for AdjMI.
306 setTypes(MI, getRecordedTypeForInstr(AdjMI));
307 return true;
311 return false;
314 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
315 InstType InstTy) {
316 changeRecordedTypeForInstr(MI, InstTy);
317 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
318 setTypes(WaitingInstr, InstTy);
322 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
323 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
324 assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
325 "Copies of non physical registers should not be considered here.\n");
327 const MachineFunction &MF = *CopyInst->getMF();
328 const MachineRegisterInfo &MRI = MF.getRegInfo();
329 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
330 const RegisterBankInfo &RBI =
331 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
332 const RegisterBank *Bank =
333 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
335 if (Bank == &Mips::FPRBRegBank)
336 setTypes(MI, InstType::FloatingPoint);
337 else if (Bank == &Mips::GPRBRegBank)
338 setTypes(MI, InstType::Integer);
339 else
340 llvm_unreachable("Unsupported register bank.\n");
343 MipsRegisterBankInfo::InstType
344 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
345 visit(MI, nullptr);
346 return getRecordedTypeForInstr(MI);
349 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
350 llvm::StringRef FunctionName) {
351 if (MFName != FunctionName) {
352 MFName = FunctionName;
353 WaitingQueues.clear();
354 Types.clear();
358 const RegisterBankInfo::InstructionMapping &
359 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
361 static TypeInfoForMF TI;
363 // Reset TI internal data when MF changes.
364 TI.cleanupIfNewFunction(MI.getMF()->getName());
366 unsigned Opc = MI.getOpcode();
367 const MachineFunction &MF = *MI.getParent()->getParent();
368 const MachineRegisterInfo &MRI = MF.getRegInfo();
370 if (MI.getOpcode() != TargetOpcode::G_PHI) {
371 const RegisterBankInfo::InstructionMapping &Mapping =
372 getInstrMappingImpl(MI);
373 if (Mapping.isValid())
374 return Mapping;
377 using namespace TargetOpcode;
379 unsigned NumOperands = MI.getNumOperands();
380 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
381 unsigned MappingID = DefaultMappingID;
382 const unsigned CustomMappingID = 1;
384 switch (Opc) {
385 case G_TRUNC:
386 case G_ADD:
387 case G_SUB:
388 case G_MUL:
389 case G_UMULH:
390 case G_ZEXTLOAD:
391 case G_SEXTLOAD:
392 case G_GEP:
393 case G_INTTOPTR:
394 case G_PTRTOINT:
395 case G_AND:
396 case G_OR:
397 case G_XOR:
398 case G_SHL:
399 case G_ASHR:
400 case G_LSHR:
401 case G_SDIV:
402 case G_UDIV:
403 case G_SREM:
404 case G_UREM:
405 case G_BRINDIRECT:
406 case G_VASTART:
407 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
408 break;
409 case G_LOAD: {
410 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
411 InstType InstTy = InstType::Integer;
412 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
413 InstTy = TI.determineInstType(&MI);
416 if (InstTy == InstType::FloatingPoint ||
417 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
418 OperandsMapping =
419 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
420 : &Mips::ValueMappings[Mips::DPRIdx],
421 &Mips::ValueMappings[Mips::GPRIdx]});
422 break;
423 } else { // gprb
424 OperandsMapping =
425 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
426 : &Mips::ValueMappings[Mips::DPRIdx],
427 &Mips::ValueMappings[Mips::GPRIdx]});
428 if (Size == 64)
429 MappingID = CustomMappingID;
432 break;
434 case G_STORE: {
435 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
436 InstType InstTy = InstType::Integer;
437 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
438 InstTy = TI.determineInstType(&MI);
441 if (InstTy == InstType::FloatingPoint ||
442 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
443 OperandsMapping =
444 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
445 : &Mips::ValueMappings[Mips::DPRIdx],
446 &Mips::ValueMappings[Mips::GPRIdx]});
447 break;
448 } else { // gprb
449 OperandsMapping =
450 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
451 : &Mips::ValueMappings[Mips::DPRIdx],
452 &Mips::ValueMappings[Mips::GPRIdx]});
453 if (Size == 64)
454 MappingID = CustomMappingID;
456 break;
458 case G_PHI: {
459 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
460 InstType InstTy = InstType::Integer;
461 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
462 InstTy = TI.determineInstType(&MI);
465 // PHI is copylike and should have one regbank in mapping for def register.
466 if (InstTy == InstType::Integer && Size == 64) { // fprb
467 OperandsMapping =
468 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
469 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
470 /*NumOperands=*/1);
472 // Use default handling for PHI, i.e. set reg bank of def operand to match
473 // register banks of use operands.
474 const RegisterBankInfo::InstructionMapping &Mapping =
475 getInstrMappingImpl(MI);
476 return Mapping;
478 case G_SELECT: {
479 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
480 InstType InstTy = InstType::Integer;
481 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
482 InstTy = TI.determineInstType(&MI);
485 if (InstTy == InstType::FloatingPoint ||
486 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb
487 const RegisterBankInfo::ValueMapping *Bank =
488 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
489 : &Mips::ValueMappings[Mips::DPRIdx];
490 OperandsMapping = getOperandsMapping(
491 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
492 break;
493 } else { // gprb
494 const RegisterBankInfo::ValueMapping *Bank =
495 Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
496 : &Mips::ValueMappings[Mips::DPRIdx];
497 OperandsMapping = getOperandsMapping(
498 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
499 if (Size == 64)
500 MappingID = CustomMappingID;
502 break;
504 case G_IMPLICIT_DEF: {
505 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
506 InstType InstTy = InstType::Integer;
507 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
508 InstTy = TI.determineInstType(&MI);
511 if (InstTy == InstType::FloatingPoint) { // fprb
512 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
513 : &Mips::ValueMappings[Mips::DPRIdx];
514 } else { // gprb
515 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::GPRIdx]
516 : &Mips::ValueMappings[Mips::DPRIdx];
517 if (Size == 64)
518 MappingID = CustomMappingID;
520 break;
522 case G_UNMERGE_VALUES: {
523 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
524 &Mips::ValueMappings[Mips::GPRIdx],
525 &Mips::ValueMappings[Mips::DPRIdx]});
526 MappingID = CustomMappingID;
527 break;
529 case G_MERGE_VALUES: {
530 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
531 &Mips::ValueMappings[Mips::GPRIdx],
532 &Mips::ValueMappings[Mips::GPRIdx]});
533 MappingID = CustomMappingID;
534 break;
536 case G_FADD:
537 case G_FSUB:
538 case G_FMUL:
539 case G_FDIV:
540 case G_FABS:
541 case G_FSQRT:{
542 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
543 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
544 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
545 : &Mips::ValueMappings[Mips::DPRIdx];
546 break;
548 case G_FCONSTANT: {
549 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
550 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
551 const RegisterBankInfo::ValueMapping *FPRValueMapping =
552 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
553 : &Mips::ValueMappings[Mips::DPRIdx];
554 OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
555 break;
557 case G_FCMP: {
558 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
559 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
560 const RegisterBankInfo::ValueMapping *FPRValueMapping =
561 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
562 : &Mips::ValueMappings[Mips::DPRIdx];
563 OperandsMapping =
564 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
565 FPRValueMapping, FPRValueMapping});
566 break;
568 case G_FPEXT:
569 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
570 &Mips::ValueMappings[Mips::SPRIdx]});
571 break;
572 case G_FPTRUNC:
573 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
574 &Mips::ValueMappings[Mips::DPRIdx]});
575 break;
576 case G_FPTOSI: {
577 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
578 assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
579 "Unsupported integer size");
580 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
581 OperandsMapping = getOperandsMapping({
582 &Mips::ValueMappings[Mips::GPRIdx],
583 SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
584 : &Mips::ValueMappings[Mips::DPRIdx],
586 break;
588 case G_SITOFP: {
589 unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
590 unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
591 (void)SizeInt;
592 assert((SizeInt == 32) && "Unsupported integer size");
593 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
594 OperandsMapping =
595 getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
596 : &Mips::ValueMappings[Mips::DPRIdx],
597 &Mips::ValueMappings[Mips::GPRIdx]});
598 break;
600 case G_CONSTANT:
601 case G_FRAME_INDEX:
602 case G_GLOBAL_VALUE:
603 case G_JUMP_TABLE:
604 case G_BRCOND:
605 OperandsMapping =
606 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
607 break;
608 case G_BRJT:
609 OperandsMapping =
610 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
611 &Mips::ValueMappings[Mips::GPRIdx]});
612 break;
613 case G_ICMP:
614 OperandsMapping =
615 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
616 &Mips::ValueMappings[Mips::GPRIdx],
617 &Mips::ValueMappings[Mips::GPRIdx]});
618 break;
619 default:
620 return getInvalidInstructionMapping();
623 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
624 NumOperands);
627 using InstListTy = GISelWorkList<4>;
628 namespace {
629 class InstManager : public GISelChangeObserver {
630 InstListTy &InstList;
632 public:
633 InstManager(InstListTy &Insts) : InstList(Insts) {}
635 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
636 void erasingInstr(MachineInstr &MI) override {}
637 void changingInstr(MachineInstr &MI) override {}
638 void changedInstr(MachineInstr &MI) override {}
640 } // end anonymous namespace
642 /// Here we have to narrowScalar s64 operands to s32, combine away
643 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
644 /// We manually assign 32 bit gprb to register operands of all new instructions
645 /// that got created in the process since they will not end up in RegBankSelect
646 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
647 void MipsRegisterBankInfo::applyMappingImpl(
648 const OperandsMapper &OpdMapper) const {
649 MachineInstr &MI = OpdMapper.getMI();
650 InstListTy NewInstrs;
651 MachineIRBuilder B(MI);
652 MachineFunction *MF = MI.getMF();
653 MachineRegisterInfo &MRI = OpdMapper.getMRI();
655 InstManager NewInstrObserver(NewInstrs);
656 GISelObserverWrapper WrapperObserver(&NewInstrObserver);
657 LegalizerHelper Helper(*MF, WrapperObserver, B);
658 LegalizationArtifactCombiner ArtCombiner(
659 B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
661 switch (MI.getOpcode()) {
662 case TargetOpcode::G_LOAD:
663 case TargetOpcode::G_STORE:
664 case TargetOpcode::G_PHI:
665 case TargetOpcode::G_SELECT:
666 case TargetOpcode::G_IMPLICIT_DEF: {
667 Helper.narrowScalar(MI, 0, LLT::scalar(32));
668 // Handle new instructions.
669 while (!NewInstrs.empty()) {
670 MachineInstr *NewMI = NewInstrs.pop_back_val();
671 // This is new G_UNMERGE that was created during narrowScalar and will
672 // not be considered for regbank selection. RegBankSelect for mips
673 // visits/makes corresponding G_MERGE first. Combine them here.
674 if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
675 SmallVector<MachineInstr *, 2> DeadInstrs;
676 ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
677 for (MachineInstr *DeadMI : DeadInstrs)
678 DeadMI->eraseFromParent();
680 // This G_MERGE will be combined away when its corresponding G_UNMERGE
681 // gets regBankSelected.
682 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
683 continue;
684 else
685 // Manually set register banks for all register operands to 32 bit gprb.
686 for (auto Op : NewMI->operands()) {
687 if (Op.isReg()) {
688 assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
689 "Only 32 bit gprb is handled here.\n");
690 MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
694 return;
696 case TargetOpcode::G_UNMERGE_VALUES: {
697 SmallVector<MachineInstr *, 2> DeadInstrs;
698 ArtCombiner.tryCombineMerges(MI, DeadInstrs);
699 for (MachineInstr *DeadMI : DeadInstrs)
700 DeadMI->eraseFromParent();
701 return;
703 default:
704 break;
707 return applyDefaultMapping(OpdMapper);