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