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