1//===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the RegisterBankInfo class for Mips.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#include "MipsRegisterBankInfo.h"
14#include "MipsInstrInfo.h"
15#include "MipsTargetMachine.h"
16#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
18#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20
21#define GET_TARGET_REGBANK_IMPL
22
23#include "MipsGenRegisterBank.inc"
24
25namespace llvm {
26namespace Mips {
27enum PartialMappingIdx {
28 PMI_GPR,
29 PMI_SPR,
30 PMI_DPR,
31 PMI_MSA,
32 PMI_Min = PMI_GPR,
33};
34
35const RegisterBankInfo::PartialMapping PartMappings[]{
36 {0, 32, GPRBRegBank},
37 {0, 32, FPRBRegBank},
38 {0, 64, FPRBRegBank},
39 {0, 128, FPRBRegBank}
40};
41
42enum ValueMappingIdx {
43 InvalidIdx = 0,
44 GPRIdx = 1,
45 SPRIdx = 4,
46 DPRIdx = 7,
47 MSAIdx = 10
48};
49
50const 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}
69};
70
71} // end namespace Mips
72} // end namespace llvm
73
74using namespace llvm;
75
76MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {}
77
78const RegisterBank &
79MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
80 LLT) const {
81 using namespace Mips;
82
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(ID: 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(ID: Mips::FPRBRegBankID);
102 default:
103 llvm_unreachable("Register class not supported");
104 }
105}
106
107// Instructions where use operands are floating point registers.
108// Def operands are general purpose.
109static bool isFloatingPointOpcodeUse(unsigned Opc) {
110 switch (Opc) {
111 case TargetOpcode::G_FPTOSI:
112 case TargetOpcode::G_FPTOUI:
113 case TargetOpcode::G_FCMP:
114 return true;
115 default:
116 return isPreISelGenericFloatingPointOpcode(Opc);
117 }
118}
119
120// Instructions where def operands are floating point registers.
121// Use operands are general purpose.
122static bool isFloatingPointOpcodeDef(unsigned Opc) {
123 switch (Opc) {
124 case TargetOpcode::G_SITOFP:
125 case TargetOpcode::G_UITOFP:
126 return true;
127 default:
128 return isPreISelGenericFloatingPointOpcode(Opc);
129 }
130}
131
132static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
133 if (MI->getOpcode() == TargetOpcode::G_LOAD ||
134 MI->getOpcode() == TargetOpcode::G_STORE) {
135 auto MMO = *MI->memoperands_begin();
136 const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
137 if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
138 (!MMO->getSize().hasValue() ||
139 MMO->getAlign() < MMO->getSize().getValue())))
140 return true;
141 }
142 return false;
143}
144
145static bool isAmbiguous(unsigned Opc) {
146 switch (Opc) {
147 case TargetOpcode::G_LOAD:
148 case TargetOpcode::G_STORE:
149 case TargetOpcode::G_PHI:
150 case TargetOpcode::G_SELECT:
151 case TargetOpcode::G_IMPLICIT_DEF:
152 case TargetOpcode::G_UNMERGE_VALUES:
153 case TargetOpcode::G_MERGE_VALUES:
154 return true;
155 default:
156 return false;
157 }
158}
159
160void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
161 Register Reg, const MachineRegisterInfo &MRI) {
162 assert(!MRI.getType(Reg).isPointer() &&
163 "Pointers are gprb, they should not be considered as ambiguous.\n");
164 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
165 MachineInstr *NonCopyInstr = skipCopiesOutgoing(MI: &UseMI);
166 // Copy with many uses.
167 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
168 !NonCopyInstr->getOperand(i: 0).getReg().isPhysical())
169 addDefUses(Reg: NonCopyInstr->getOperand(i: 0).getReg(), MRI);
170 else
171 DefUses.push_back(Elt: skipCopiesOutgoing(MI: &UseMI));
172 }
173}
174
175void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
176 Register Reg, const MachineRegisterInfo &MRI) {
177 assert(!MRI.getType(Reg).isPointer() &&
178 "Pointers are gprb, they should not be considered as ambiguous.\n");
179 MachineInstr *DefMI = MRI.getVRegDef(Reg);
180 UseDefs.push_back(Elt: skipCopiesIncoming(MI: DefMI));
181}
182
183MachineInstr *
184MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
185 MachineInstr *MI) const {
186 const MachineFunction &MF = *MI->getParent()->getParent();
187 const MachineRegisterInfo &MRI = MF.getRegInfo();
188 MachineInstr *Ret = MI;
189 while (Ret->getOpcode() == TargetOpcode::COPY &&
190 !Ret->getOperand(i: 0).getReg().isPhysical() &&
191 MRI.hasOneUse(RegNo: Ret->getOperand(i: 0).getReg())) {
192 Ret = &(*MRI.use_instr_begin(RegNo: Ret->getOperand(i: 0).getReg()));
193 }
194 return Ret;
195}
196
197MachineInstr *
198MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
199 MachineInstr *MI) const {
200 const MachineFunction &MF = *MI->getParent()->getParent();
201 const MachineRegisterInfo &MRI = MF.getRegInfo();
202 MachineInstr *Ret = MI;
203 while (Ret->getOpcode() == TargetOpcode::COPY &&
204 !Ret->getOperand(i: 1).getReg().isPhysical())
205 Ret = MRI.getVRegDef(Reg: Ret->getOperand(i: 1).getReg());
206 return Ret;
207}
208
209MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
210 const MachineInstr *MI) {
211 assert(isAmbiguous(MI->getOpcode()) &&
212 "Not implemented for non Ambiguous opcode.\n");
213
214 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
215
216 if (MI->getOpcode() == TargetOpcode::G_LOAD)
217 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
218
219 if (MI->getOpcode() == TargetOpcode::G_STORE)
220 addUseDef(Reg: MI->getOperand(i: 0).getReg(), MRI);
221
222 if (auto *PHI = dyn_cast<GPhi>(Val: MI)) {
223 addDefUses(Reg: PHI->getReg(Idx: 0), MRI);
224
225 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
226 addUseDef(Reg: PHI->getIncomingValue(I), MRI);
227 }
228
229 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
230 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
231
232 addUseDef(Reg: MI->getOperand(i: 2).getReg(), MRI);
233 addUseDef(Reg: MI->getOperand(i: 3).getReg(), MRI);
234 }
235
236 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
237 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
238
239 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
240 addUseDef(Reg: MI->getOperand(i: MI->getNumOperands() - 1).getReg(), MRI);
241
242 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
243 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
244}
245
246bool MipsRegisterBankInfo::TypeInfoForMF::visit(
247 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
248 InstType &AmbiguousTy) {
249 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
250 if (wasVisited(MI))
251 return true; // InstType has already been determined for MI.
252
253 startVisit(MI);
254 AmbiguousRegDefUseContainer DefUseContainer(MI);
255
256 if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
257 setTypes(MI, ITy: Integer);
258 return true;
259 }
260
261 if (AmbiguousTy == InstType::Ambiguous &&
262 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
263 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
264 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
265
266 // Visit instructions where MI's DEF operands are USED.
267 if (visitAdjacentInstrs(MI, AdjacentInstrs&: DefUseContainer.getDefUses(), isDefUse: true, AmbiguousTy))
268 return true;
269
270 // Visit instructions that DEFINE MI's USE operands.
271 if (visitAdjacentInstrs(MI, AdjacentInstrs&: DefUseContainer.getUseDefs(), isDefUse: false, AmbiguousTy))
272 return true;
273
274 // All MI's adjacent instructions, are ambiguous.
275 if (!WaitingForTypeOfMI) {
276 // This is chain of ambiguous instructions.
277 setTypes(MI, ITy: AmbiguousTy);
278 return true;
279 }
280 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
281 // instructions or has no other adjacent instructions. Anyway InstType could
282 // not be determined. There could be unexplored path from some of
283 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
284 // mapping available.
285 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
286 // this way when WaitingForTypeOfMI figures out its InstType same InstType
287 // will be assigned to all instructions in this branch.
288 addToWaitingQueue(MI: WaitingForTypeOfMI, WaitingForMI: MI);
289 return false;
290}
291
292bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
293 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
294 bool isDefUse, InstType &AmbiguousTy) {
295 while (!AdjacentInstrs.empty()) {
296 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
297
298 if (isDefUse ? isFloatingPointOpcodeUse(Opc: AdjMI->getOpcode())
299 : isFloatingPointOpcodeDef(Opc: AdjMI->getOpcode())) {
300 setTypes(MI, ITy: InstType::FloatingPoint);
301 return true;
302 }
303
304 // Determine InstType from register bank of phys register that is
305 // 'isDefUse ? def : use' of this copy.
306 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
307 setTypesAccordingToPhysicalRegister(MI, CopyInst: AdjMI, Op: isDefUse ? 0 : 1);
308 return true;
309 }
310
311 // Defaults to integer instruction. Small registers in G_MERGE (uses) and
312 // G_UNMERGE (defs) will always be gprb.
313 if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
314 (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
315 !isAmbiguous(Opc: AdjMI->getOpcode())) {
316 setTypes(MI, ITy: InstType::Integer);
317 return true;
318 }
319
320 // When AdjMI was visited first, MI has to continue to explore remaining
321 // adjacent instructions and determine InstType without visiting AdjMI.
322 if (!wasVisited(MI: AdjMI) ||
323 getRecordedTypeForInstr(MI: AdjMI) != InstType::NotDetermined) {
324 if (visit(MI: AdjMI, WaitingForTypeOfMI: MI, AmbiguousTy)) {
325 // InstType is successfully determined and is same as for AdjMI.
326 setTypes(MI, ITy: getRecordedTypeForInstr(MI: AdjMI));
327 return true;
328 }
329 }
330 }
331 return false;
332}
333
334void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
335 InstType InstTy) {
336 changeRecordedTypeForInstr(MI, InstTy);
337 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
338 setTypes(MI: WaitingInstr, InstTy);
339 }
340}
341
342void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
343 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
344 assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&
345 "Copies of non physical registers should not be considered here.\n");
346
347 const MachineFunction &MF = *CopyInst->getMF();
348 const MachineRegisterInfo &MRI = MF.getRegInfo();
349 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
350 const RegisterBankInfo &RBI =
351 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
352 const RegisterBank *Bank =
353 RBI.getRegBank(Reg: CopyInst->getOperand(i: Op).getReg(), MRI, TRI);
354
355 if (Bank == &Mips::FPRBRegBank)
356 setTypes(MI, InstTy: InstType::FloatingPoint);
357 else if (Bank == &Mips::GPRBRegBank)
358 setTypes(MI, InstTy: InstType::Integer);
359 else
360 llvm_unreachable("Unsupported register bank.\n");
361}
362
363MipsRegisterBankInfo::InstType
364MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
365 InstType DefaultAmbiguousType = InstType::Ambiguous;
366 visit(MI, WaitingForTypeOfMI: nullptr, AmbiguousTy&: DefaultAmbiguousType);
367 return getRecordedTypeForInstr(MI);
368}
369
370void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
371 llvm::StringRef FunctionName) {
372 if (MFName != FunctionName) {
373 MFName = std::string(FunctionName);
374 WaitingQueues.clear();
375 Types.clear();
376 }
377}
378
379static const MipsRegisterBankInfo::ValueMapping *
380getMSAMapping(const MachineFunction &MF) {
381 assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
382 "MSA mapping not available on target without MSA.");
383 return &Mips::ValueMappings[Mips::MSAIdx];
384}
385
386static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
387 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
388 : &Mips::ValueMappings[Mips::DPRIdx];
389}
390
391static const unsigned CustomMappingID = 1;
392
393// Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
394// will be split into two 32 bit registers in gprb.
395static const MipsRegisterBankInfo::ValueMapping *
396getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
397 if (Size == 32)
398 return &Mips::ValueMappings[Mips::GPRIdx];
399
400 MappingID = CustomMappingID;
401 return &Mips::ValueMappings[Mips::DPRIdx];
402}
403
404const RegisterBankInfo::InstructionMapping &
405MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
406
407 static TypeInfoForMF TI;
408
409 // Reset TI internal data when MF changes.
410 TI.cleanupIfNewFunction(FunctionName: MI.getMF()->getName());
411
412 unsigned Opc = MI.getOpcode();
413 const MachineFunction &MF = *MI.getParent()->getParent();
414 const MachineRegisterInfo &MRI = MF.getRegInfo();
415
416 if (MI.getOpcode() != TargetOpcode::G_PHI) {
417 const RegisterBankInfo::InstructionMapping &Mapping =
418 getInstrMappingImpl(MI);
419 if (Mapping.isValid())
420 return Mapping;
421 }
422
423 using namespace TargetOpcode;
424
425 unsigned NumOperands = MI.getNumOperands();
426 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
427 unsigned MappingID = DefaultMappingID;
428
429 // Check if LLT sizes match sizes of available register banks.
430 for (const MachineOperand &Op : MI.operands()) {
431 if (Op.isReg()) {
432 LLT RegTy = MRI.getType(Reg: Op.getReg());
433
434 if (RegTy.isScalar() &&
435 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
436 return getInvalidInstructionMapping();
437
438 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
439 return getInvalidInstructionMapping();
440 }
441 }
442
443 const LLT Op0Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
444 unsigned Op0Size = Op0Ty.getSizeInBits();
445 InstType InstTy = InstType::Integer;
446
447 switch (Opc) {
448 case G_TRUNC:
449 case G_UMULH:
450 case G_ZEXTLOAD:
451 case G_SEXTLOAD:
452 case G_PTR_ADD:
453 case G_INTTOPTR:
454 case G_PTRTOINT:
455 case G_AND:
456 case G_OR:
457 case G_XOR:
458 case G_SHL:
459 case G_ASHR:
460 case G_LSHR:
461 case G_BRINDIRECT:
462 case G_VASTART:
463 case G_BSWAP:
464 case G_CTLZ:
465 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
466 break;
467 case G_ADD:
468 case G_SUB:
469 case G_MUL:
470 case G_SDIV:
471 case G_SREM:
472 case G_UDIV:
473 case G_UREM:
474 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
475 if (Op0Size == 128)
476 OperandsMapping = getMSAMapping(MF);
477 break;
478 case G_STORE:
479 case G_LOAD: {
480 if (Op0Size == 128) {
481 OperandsMapping = getOperandsMapping(
482 OpdsMapping: {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
483 break;
484 }
485
486 if (!Op0Ty.isPointer())
487 InstTy = TI.determineInstType(MI: &MI);
488
489 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size) ||
490 isAmbiguous_64(InstTy, OpSize: Op0Size)) {
491 OperandsMapping = getOperandsMapping(
492 OpdsMapping: {getFprbMapping(Size: Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
493 } else {
494 assert((isInteger_32(InstTy, Op0Size) ||
495 isAmbiguous_32(InstTy, Op0Size) ||
496 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
497 "Unexpected Inst type");
498 OperandsMapping =
499 getOperandsMapping(OpdsMapping: {getGprbOrCustomMapping(Size: Op0Size, MappingID),
500 &Mips::ValueMappings[Mips::GPRIdx]});
501 }
502
503 break;
504 }
505 case G_PHI: {
506 if (!Op0Ty.isPointer())
507 InstTy = TI.determineInstType(MI: &MI);
508
509 // PHI is copylike and should have one regbank in mapping for def register.
510 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op0Size)) {
511 OperandsMapping =
512 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx]});
513 TI.clearTypeInfoData(MI: &MI);
514 return getInstructionMapping(ID: CustomMappingID, /*Cost=*/1, OperandsMapping,
515 /*NumOperands=*/1);
516 }
517 assert((isInteger_32(InstTy, Op0Size) ||
518 isFloatingPoint_32or64(InstTy, Op0Size) ||
519 isAmbiguous_32or64(InstTy, Op0Size)) &&
520 "Unexpected Inst type");
521 // Use default handling for PHI, i.e. set reg bank of def operand to match
522 // register banks of use operands.
523 return getInstrMappingImpl(MI);
524 }
525 case G_SELECT: {
526 if (!Op0Ty.isPointer())
527 InstTy = TI.determineInstType(MI: &MI);
528 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size) ||
529 isAmbiguous_64(InstTy, OpSize: Op0Size)) {
530 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Size: Op0Size);
531 OperandsMapping = getOperandsMapping(
532 OpdsMapping: {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
533 break;
534 } else {
535 assert((isInteger_32(InstTy, Op0Size) ||
536 isAmbiguous_32(InstTy, Op0Size) ||
537 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
538 "Unexpected Inst type");
539 const RegisterBankInfo::ValueMapping *Bank =
540 getGprbOrCustomMapping(Size: Op0Size, MappingID);
541 OperandsMapping = getOperandsMapping(
542 OpdsMapping: {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
543 }
544 break;
545 }
546 case G_IMPLICIT_DEF: {
547 if (!Op0Ty.isPointer())
548 InstTy = TI.determineInstType(MI: &MI);
549
550 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size))
551 OperandsMapping = getFprbMapping(Size: Op0Size);
552 else {
553 assert((isInteger_32(InstTy, Op0Size) ||
554 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
555 "Unexpected Inst type");
556 OperandsMapping = getGprbOrCustomMapping(Size: Op0Size, MappingID);
557 }
558 } break;
559 case G_UNMERGE_VALUES: {
560 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
561 unsigned Op3Size = MRI.getType(Reg: MI.getOperand(i: 2).getReg()).getSizeInBits();
562 InstTy = TI.determineInstType(MI: &MI);
563 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
564 isFloatingPoint_64(InstTy, Op3Size)) &&
565 "Unexpected Inst type");
566 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx],
567 &Mips::ValueMappings[Mips::GPRIdx],
568 &Mips::ValueMappings[Mips::DPRIdx]});
569 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op3Size))
570 MappingID = CustomMappingID;
571 break;
572 }
573 case G_MERGE_VALUES: {
574 InstTy = TI.determineInstType(MI: &MI);
575 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
576 isFloatingPoint_64(InstTy, Op0Size)) &&
577 "Unexpected Inst type");
578 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx],
579 &Mips::ValueMappings[Mips::GPRIdx],
580 &Mips::ValueMappings[Mips::GPRIdx]});
581 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op0Size))
582 MappingID = CustomMappingID;
583 break;
584 }
585 case G_FADD:
586 case G_FSUB:
587 case G_FMUL:
588 case G_FDIV:
589 case G_FABS:
590 case G_FSQRT:
591 OperandsMapping = getFprbMapping(Size: Op0Size);
592 if (Op0Size == 128)
593 OperandsMapping = getMSAMapping(MF);
594 break;
595 case G_FCONSTANT:
596 OperandsMapping = getOperandsMapping(OpdsMapping: {getFprbMapping(Size: Op0Size), nullptr});
597 break;
598 case G_FCMP: {
599 unsigned Op2Size = MRI.getType(Reg: MI.getOperand(i: 2).getReg()).getSizeInBits();
600 OperandsMapping =
601 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
602 getFprbMapping(Size: Op2Size), getFprbMapping(Size: Op2Size)});
603 break;
604 }
605 case G_FPEXT:
606 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx],
607 &Mips::ValueMappings[Mips::SPRIdx]});
608 break;
609 case G_FPTRUNC:
610 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::SPRIdx],
611 &Mips::ValueMappings[Mips::DPRIdx]});
612 break;
613 case G_FPTOSI: {
614 assert((Op0Size == 32) && "Unsupported integer size");
615 unsigned SizeFP = MRI.getType(Reg: MI.getOperand(i: 1).getReg()).getSizeInBits();
616 OperandsMapping = getOperandsMapping(
617 OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(Size: SizeFP)});
618 break;
619 }
620 case G_SITOFP:
621 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
622 "Unsupported integer size");
623 OperandsMapping = getOperandsMapping(
624 OpdsMapping: {getFprbMapping(Size: Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
625 break;
626 case G_CONSTANT:
627 case G_FRAME_INDEX:
628 case G_GLOBAL_VALUE:
629 case G_JUMP_TABLE:
630 case G_BRCOND:
631 OperandsMapping =
632 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr});
633 break;
634 case G_BRJT:
635 OperandsMapping =
636 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
637 &Mips::ValueMappings[Mips::GPRIdx]});
638 break;
639 case G_ICMP:
640 OperandsMapping =
641 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
642 &Mips::ValueMappings[Mips::GPRIdx],
643 &Mips::ValueMappings[Mips::GPRIdx]});
644 break;
645 default:
646 return getInvalidInstructionMapping();
647 }
648
649 if (MappingID == CustomMappingID)
650 TI.clearTypeInfoData(MI: &MI);
651 return getInstructionMapping(ID: MappingID, /*Cost=*/1, OperandsMapping,
652 NumOperands);
653}
654
655using InstListTy = GISelWorkList<4>;
656namespace {
657class InstManager : public GISelChangeObserver {
658 InstListTy &InstList;
659 MachineIRBuilder &B;
660
661public:
662 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
663 assert(!B.isObservingChanges());
664 B.setChangeObserver(*this);
665 }
666
667 ~InstManager() { B.stopObservingChanges(); }
668
669 void createdInstr(MachineInstr &MI) override { InstList.insert(I: &MI); }
670 void erasingInstr(MachineInstr &MI) override {}
671 void changingInstr(MachineInstr &MI) override {}
672 void changedInstr(MachineInstr &MI) override {}
673};
674} // end anonymous namespace
675
676void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
677 MachineRegisterInfo &MRI) const {
678 Register Dest = MI.getOperand(i: 0).getReg();
679 switch (MI.getOpcode()) {
680 case TargetOpcode::G_STORE:
681 // No def operands, skip this instruction.
682 break;
683 case TargetOpcode::G_CONSTANT:
684 case TargetOpcode::G_LOAD:
685 case TargetOpcode::G_SELECT:
686 case TargetOpcode::G_PHI:
687 case TargetOpcode::G_IMPLICIT_DEF: {
688 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
689 MRI.setRegBank(Reg: Dest, RegBank: getRegBank(ID: Mips::GPRBRegBankID));
690 break;
691 }
692 case TargetOpcode::G_PTR_ADD: {
693 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
694 MRI.setRegBank(Reg: Dest, RegBank: getRegBank(ID: Mips::GPRBRegBankID));
695 break;
696 }
697 default:
698 llvm_unreachable("Unexpected opcode.");
699 }
700}
701
702static void
703combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
704 GUnmerge &MI, GISelChangeObserver &Observer) {
705 SmallVector<Register, 4> UpdatedDefs;
706 SmallVector<MachineInstr *, 2> DeadInstrs;
707 ArtCombiner.tryCombineUnmergeValues(MI, DeadInsts&: DeadInstrs,
708 UpdatedDefs, Observer);
709 for (MachineInstr *DeadMI : DeadInstrs)
710 DeadMI->eraseFromParent();
711}
712
713void MipsRegisterBankInfo::applyMappingImpl(
714 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
715 MachineInstr &MI = OpdMapper.getMI();
716 Builder.setInstrAndDebugLoc(MI);
717
718 InstListTy NewInstrs;
719 MachineFunction *MF = MI.getMF();
720 MachineRegisterInfo &MRI = OpdMapper.getMRI();
721 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
722
723 InstManager NewInstrObserver(Builder, NewInstrs);
724 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
725 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
726
727 switch (MI.getOpcode()) {
728 case TargetOpcode::G_LOAD:
729 case TargetOpcode::G_STORE:
730 case TargetOpcode::G_PHI:
731 case TargetOpcode::G_SELECT:
732 case TargetOpcode::G_IMPLICIT_DEF: {
733 Helper.narrowScalar(MI, TypeIdx: 0, NarrowTy: LLT::scalar(SizeInBits: 32));
734 // Handle new instructions.
735 while (!NewInstrs.empty()) {
736 MachineInstr *NewMI = NewInstrs.pop_back_val();
737 // This is new G_UNMERGE that was created during narrowScalar and will
738 // not be considered for regbank selection. RegBankSelect for mips
739 // visits/makes corresponding G_MERGE first. Combine them here.
740 if (auto *Unmerge = dyn_cast<GUnmerge>(Val: NewMI))
741 combineAwayG_UNMERGE_VALUES(ArtCombiner, MI&: *Unmerge, Observer&: NewInstrObserver);
742 // This G_MERGE will be combined away when its corresponding G_UNMERGE
743 // gets regBankSelected.
744 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
745 continue;
746 else
747 // Manually set register banks for def operands to 32 bit gprb.
748 setRegBank(MI&: *NewMI, MRI);
749 }
750 return;
751 }
752 case TargetOpcode::G_UNMERGE_VALUES:
753 combineAwayG_UNMERGE_VALUES(ArtCombiner, MI&: cast<GUnmerge>(Val&: MI),
754 Observer&: NewInstrObserver);
755 return;
756 default:
757 break;
758 }
759
760 return applyDefaultMapping(OpdMapper);
761}
762