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
78// Instructions where use operands are floating point registers.
79// Def operands are general purpose.
80static 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);
88 }
89}
90
91// Instructions where def operands are floating point registers.
92// Use operands are general purpose.
93static 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);
100 }
101}
102
103static 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;
112 }
113 return false;
114}
115
116static 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;
128 }
129}
130
131void 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(MI: &UseMI);
137 // Copy with many uses.
138 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
139 !NonCopyInstr->getOperand(i: 0).getReg().isPhysical())
140 addDefUses(Reg: NonCopyInstr->getOperand(i: 0).getReg(), MRI);
141 else
142 DefUses.push_back(Elt: skipCopiesOutgoing(MI: &UseMI));
143 }
144}
145
146void 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(Elt: skipCopiesIncoming(MI: DefMI));
152}
153
154MachineInstr *
155MipsRegisterBankInfo::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(i: 0).getReg().isPhysical() &&
162 MRI.hasOneUse(RegNo: Ret->getOperand(i: 0).getReg())) {
163 Ret = &(*MRI.use_instr_begin(RegNo: Ret->getOperand(i: 0).getReg()));
164 }
165 return Ret;
166}
167
168MachineInstr *
169MipsRegisterBankInfo::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(i: 1).getReg().isPhysical())
176 Ret = MRI.getVRegDef(Reg: Ret->getOperand(i: 1).getReg());
177 return Ret;
178}
179
180MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
181 const MachineInstr *MI) {
182 assert(isAmbiguous(MI->getOpcode()) &&
183 "Not implemented for non Ambiguous opcode.\n");
184
185 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
186
187 if (MI->getOpcode() == TargetOpcode::G_LOAD)
188 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
189
190 if (MI->getOpcode() == TargetOpcode::G_STORE)
191 addUseDef(Reg: MI->getOperand(i: 0).getReg(), MRI);
192
193 if (auto *PHI = dyn_cast<GPhi>(Val: MI)) {
194 addDefUses(Reg: PHI->getReg(Idx: 0), MRI);
195
196 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
197 addUseDef(Reg: PHI->getIncomingValue(I), MRI);
198 }
199
200 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
201 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
202
203 addUseDef(Reg: MI->getOperand(i: 2).getReg(), MRI);
204 addUseDef(Reg: MI->getOperand(i: 3).getReg(), MRI);
205 }
206
207 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
208 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
209
210 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
211 addUseDef(Reg: MI->getOperand(i: MI->getNumOperands() - 1).getReg(), MRI);
212
213 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
214 addDefUses(Reg: MI->getOperand(i: 0).getReg(), MRI);
215}
216
217bool 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.
223
224 startVisit(MI);
225 AmbiguousRegDefUseContainer DefUseContainer(MI);
226
227 if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
228 setTypes(MI, ITy: Integer);
229 return true;
230 }
231
232 if (AmbiguousTy == InstType::Ambiguous &&
233 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
234 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
235 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
236
237 // Visit instructions where MI's DEF operands are USED.
238 if (visitAdjacentInstrs(MI, AdjacentInstrs&: DefUseContainer.getDefUses(), isDefUse: true, AmbiguousTy))
239 return true;
240
241 // Visit instructions that DEFINE MI's USE operands.
242 if (visitAdjacentInstrs(MI, AdjacentInstrs&: DefUseContainer.getUseDefs(), isDefUse: false, AmbiguousTy))
243 return true;
244
245 // All MI's adjacent instructions, are ambiguous.
246 if (!WaitingForTypeOfMI) {
247 // This is chain of ambiguous instructions.
248 setTypes(MI, ITy: AmbiguousTy);
249 return true;
250 }
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(MI: WaitingForTypeOfMI, WaitingForMI: MI);
260 return false;
261}
262
263bool 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();
268
269 if (isDefUse ? isFloatingPointOpcodeUse(Opc: AdjMI->getOpcode())
270 : isFloatingPointOpcodeDef(Opc: AdjMI->getOpcode())) {
271 setTypes(MI, ITy: InstType::FloatingPoint);
272 return true;
273 }
274
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, CopyInst: AdjMI, Op: isDefUse ? 0 : 1);
279 return true;
280 }
281
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(Opc: AdjMI->getOpcode())) {
287 setTypes(MI, ITy: InstType::Integer);
288 return true;
289 }
290
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(MI: AdjMI) ||
294 getRecordedTypeForInstr(MI: AdjMI) != InstType::NotDetermined) {
295 if (visit(MI: AdjMI, WaitingForTypeOfMI: MI, AmbiguousTy)) {
296 // InstType is successfully determined and is same as for AdjMI.
297 setTypes(MI, ITy: getRecordedTypeForInstr(MI: AdjMI));
298 return true;
299 }
300 }
301 }
302 return false;
303}
304
305void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
306 InstType InstTy) {
307 changeRecordedTypeForInstr(MI, InstTy);
308 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
309 setTypes(MI: WaitingInstr, InstTy);
310 }
311}
312
313void 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");
317
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(Reg: CopyInst->getOperand(i: Op).getReg(), MRI, TRI);
325
326 if (Bank == &Mips::FPRBRegBank)
327 setTypes(MI, InstTy: InstType::FloatingPoint);
328 else if (Bank == &Mips::GPRBRegBank)
329 setTypes(MI, InstTy: InstType::Integer);
330 else
331 llvm_unreachable("Unsupported register bank.\n");
332}
333
334MipsRegisterBankInfo::InstType
335MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
336 InstType DefaultAmbiguousType = InstType::Ambiguous;
337 visit(MI, WaitingForTypeOfMI: nullptr, AmbiguousTy&: DefaultAmbiguousType);
338 return getRecordedTypeForInstr(MI);
339}
340
341void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
342 llvm::StringRef FunctionName) {
343 if (MFName != FunctionName) {
344 MFName = std::string(FunctionName);
345 WaitingQueues.clear();
346 Types.clear();
347 }
348}
349
350static const MipsRegisterBankInfo::ValueMapping *
351getMSAMapping(const MachineFunction &MF) {
352 assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
353 "MSA mapping not available on target without MSA.");
354 return &Mips::ValueMappings[Mips::MSAIdx];
355}
356
357static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
358 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
359 : &Mips::ValueMappings[Mips::DPRIdx];
360}
361
362static const unsigned CustomMappingID = 1;
363
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.
366static const MipsRegisterBankInfo::ValueMapping *
367getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
368 if (Size == 32)
369 return &Mips::ValueMappings[Mips::GPRIdx];
370
371 MappingID = CustomMappingID;
372 return &Mips::ValueMappings[Mips::DPRIdx];
373}
374
375const RegisterBankInfo::InstructionMapping &
376MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
377
378 static TypeInfoForMF TI;
379
380 // Reset TI internal data when MF changes.
381 TI.cleanupIfNewFunction(FunctionName: MI.getMF()->getName());
382
383 unsigned Opc = MI.getOpcode();
384 const MachineFunction &MF = *MI.getParent()->getParent();
385 const MachineRegisterInfo &MRI = MF.getRegInfo();
386
387 if (MI.getOpcode() != TargetOpcode::G_PHI) {
388 const RegisterBankInfo::InstructionMapping &Mapping =
389 getInstrMappingImpl(MI);
390 if (Mapping.isValid())
391 return Mapping;
392 }
393
394 using namespace TargetOpcode;
395
396 unsigned NumOperands = MI.getNumOperands();
397 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
398 unsigned MappingID = DefaultMappingID;
399
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(Reg: Op.getReg());
404
405 if (RegTy.isScalar() &&
406 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
407 return getInvalidInstructionMapping();
408
409 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
410 return getInvalidInstructionMapping();
411 }
412 }
413
414 const LLT Op0Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
415 unsigned Op0Size = Op0Ty.getSizeInBits();
416 InstType InstTy = InstType::Integer;
417
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 OpdsMapping: {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
454 break;
455 }
456
457 if (!Op0Ty.isPointer())
458 InstTy = TI.determineInstType(MI: &MI);
459
460 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size) ||
461 isAmbiguous_64(InstTy, OpSize: Op0Size)) {
462 OperandsMapping = getOperandsMapping(
463 OpdsMapping: {getFprbMapping(Size: 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(OpdsMapping: {getGprbOrCustomMapping(Size: Op0Size, MappingID),
471 &Mips::ValueMappings[Mips::GPRIdx]});
472 }
473
474 break;
475 }
476 case G_PHI: {
477 if (!Op0Ty.isPointer())
478 InstTy = TI.determineInstType(MI: &MI);
479
480 // PHI is copylike and should have one regbank in mapping for def register.
481 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op0Size)) {
482 OperandsMapping =
483 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx]});
484 TI.clearTypeInfoData(MI: &MI);
485 return getInstructionMapping(ID: CustomMappingID, /*Cost=*/1, OperandsMapping,
486 /*NumOperands=*/1);
487 }
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);
495 }
496 case G_SELECT: {
497 if (!Op0Ty.isPointer())
498 InstTy = TI.determineInstType(MI: &MI);
499 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size) ||
500 isAmbiguous_64(InstTy, OpSize: Op0Size)) {
501 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Size: Op0Size);
502 OperandsMapping = getOperandsMapping(
503 OpdsMapping: {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(Size: Op0Size, MappingID);
512 OperandsMapping = getOperandsMapping(
513 OpdsMapping: {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
514 }
515 break;
516 }
517 case G_IMPLICIT_DEF: {
518 if (!Op0Ty.isPointer())
519 InstTy = TI.determineInstType(MI: &MI);
520
521 if (isFloatingPoint_32or64(InstTy, OpSize: Op0Size))
522 OperandsMapping = getFprbMapping(Size: Op0Size);
523 else {
524 assert((isInteger_32(InstTy, Op0Size) ||
525 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
526 "Unexpected Inst type");
527 OperandsMapping = getGprbOrCustomMapping(Size: Op0Size, MappingID);
528 }
529 } break;
530 case G_UNMERGE_VALUES: {
531 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
532 unsigned Op3Size = MRI.getType(Reg: MI.getOperand(i: 2).getReg()).getSizeInBits();
533 InstTy = TI.determineInstType(MI: &MI);
534 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
535 isFloatingPoint_64(InstTy, Op3Size)) &&
536 "Unexpected Inst type");
537 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx],
538 &Mips::ValueMappings[Mips::GPRIdx],
539 &Mips::ValueMappings[Mips::DPRIdx]});
540 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op3Size))
541 MappingID = CustomMappingID;
542 break;
543 }
544 case G_MERGE_VALUES: {
545 InstTy = TI.determineInstType(MI: &MI);
546 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
547 isFloatingPoint_64(InstTy, Op0Size)) &&
548 "Unexpected Inst type");
549 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx],
550 &Mips::ValueMappings[Mips::GPRIdx],
551 &Mips::ValueMappings[Mips::GPRIdx]});
552 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, OpSize: Op0Size))
553 MappingID = CustomMappingID;
554 break;
555 }
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(Size: Op0Size);
563 if (Op0Size == 128)
564 OperandsMapping = getMSAMapping(MF);
565 break;
566 case G_FCONSTANT:
567 OperandsMapping = getOperandsMapping(OpdsMapping: {getFprbMapping(Size: Op0Size), nullptr});
568 break;
569 case G_FCMP: {
570 unsigned Op2Size = MRI.getType(Reg: MI.getOperand(i: 2).getReg()).getSizeInBits();
571 OperandsMapping =
572 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
573 getFprbMapping(Size: Op2Size), getFprbMapping(Size: Op2Size)});
574 break;
575 }
576 case G_FPEXT:
577 OperandsMapping = getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::DPRIdx],
578 &Mips::ValueMappings[Mips::SPRIdx]});
579 break;
580 case G_FPTRUNC:
581 OperandsMapping = getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 1).getReg()).getSizeInBits();
587 OperandsMapping = getOperandsMapping(
588 OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(Size: SizeFP)});
589 break;
590 }
591 case G_SITOFP:
592 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
593 "Unsupported integer size");
594 OperandsMapping = getOperandsMapping(
595 OpdsMapping: {getFprbMapping(Size: 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(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr});
604 break;
605 case G_BRJT:
606 OperandsMapping =
607 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
608 &Mips::ValueMappings[Mips::GPRIdx]});
609 break;
610 case G_ICMP:
611 OperandsMapping =
612 getOperandsMapping(OpdsMapping: {&Mips::ValueMappings[Mips::GPRIdx], nullptr,
613 &Mips::ValueMappings[Mips::GPRIdx],
614 &Mips::ValueMappings[Mips::GPRIdx]});
615 break;
616 default:
617 return getInvalidInstructionMapping();
618 }
619
620 if (MappingID == CustomMappingID)
621 TI.clearTypeInfoData(MI: &MI);
622 return getInstructionMapping(ID: MappingID, /*Cost=*/1, OperandsMapping,
623 NumOperands);
624}
625
626using InstListTy = GISelWorkList<4>;
627namespace {
628class InstManager : public GISelChangeObserver {
629 InstListTy &InstList;
630 MachineIRBuilder &B;
631
632public:
633 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
634 assert(!B.isObservingChanges());
635 B.setChangeObserver(*this);
636 }
637
638 ~InstManager() { B.stopObservingChanges(); }
639
640 void createdInstr(MachineInstr &MI) override { InstList.insert(I: &MI); }
641 void erasingInstr(MachineInstr &MI) override {}
642 void changingInstr(MachineInstr &MI) override {}
643 void changedInstr(MachineInstr &MI) override {}
644};
645} // end anonymous namespace
646
647void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
648 MachineRegisterInfo &MRI) const {
649 Register Dest = MI.getOperand(i: 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(Reg: Dest, RegBank: getRegBank(ID: Mips::GPRBRegBankID));
661 break;
662 }
663 case TargetOpcode::G_PTR_ADD: {
664 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
665 MRI.setRegBank(Reg: Dest, RegBank: getRegBank(ID: Mips::GPRBRegBankID));
666 break;
667 }
668 default:
669 llvm_unreachable("Unexpected opcode.");
670 }
671}
672
673static void
674combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
675 GUnmerge &MI, GISelChangeObserver &Observer) {
676 SmallVector<Register, 4> UpdatedDefs;
677 SmallVector<MachineInstr *, 2> DeadInstrs;
678 ArtCombiner.tryCombineUnmergeValues(MI, DeadInsts&: DeadInstrs,
679 UpdatedDefs, Observer);
680 for (MachineInstr *DeadMI : DeadInstrs)
681 DeadMI->eraseFromParent();
682}
683
684void MipsRegisterBankInfo::applyMappingImpl(
685 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
686 MachineInstr &MI = OpdMapper.getMI();
687 Builder.setInstrAndDebugLoc(MI);
688
689 InstListTy NewInstrs;
690 MachineFunction *MF = MI.getMF();
691 MachineRegisterInfo &MRI = OpdMapper.getMRI();
692 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
693
694 InstManager NewInstrObserver(Builder, NewInstrs);
695 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
696 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
697
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, TypeIdx: 0, NarrowTy: LLT::scalar(SizeInBits: 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>(Val: NewMI))
712 combineAwayG_UNMERGE_VALUES(ArtCombiner, MI&: *Unmerge, Observer&: 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(MI&: *NewMI, MRI);
720 }
721 return;
722 }
723 case TargetOpcode::G_UNMERGE_VALUES:
724 combineAwayG_UNMERGE_VALUES(ArtCombiner, MI&: cast<GUnmerge>(Val&: MI),
725 Observer&: NewInstrObserver);
726 return;
727 default:
728 break;
729 }
730
731 return applyDefaultMapping(OpdMapper);
732}
733