LLVM 19.0.0git
MipsRegisterBankInfo.cpp
Go to the documentation of this file.
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
14#include "MipsInstrInfo.h"
15#include "MipsTargetMachine.h"
20
21#define GET_TARGET_REGBANK_IMPL
22
23#include "MipsGenRegisterBank.inc"
24
25namespace llvm {
26namespace Mips {
33};
34
36 {0, 32, GPRBRegBank},
37 {0, 32, FPRBRegBank},
38 {0, 64, FPRBRegBank},
39 {0, 128, FPRBRegBank}
40};
41
44 GPRIdx = 1,
45 SPRIdx = 4,
46 DPRIdx = 7,
47 MSAIdx = 10
48};
49
51 // invalid
52 {nullptr, 0},
53 // up to 3 operands in GPRs
57 // up to 3 operands in FPRs - single precission
61 // up to 3 operands in FPRs - double precission
65 // up to 3 operands in FPRs - MSA
69};
70
71} // end namespace Mips
72} // end namespace llvm
73
74using namespace llvm;
75
77
78const RegisterBank &
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(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(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:
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:
129 }
130}
131
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(&UseMI);
166 // Copy with many uses.
167 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
168 !NonCopyInstr->getOperand(0).getReg().isPhysical())
169 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
170 else
171 DefUses.push_back(skipCopiesOutgoing(&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(skipCopiesIncoming(DefMI));
181}
182
184MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
185 MachineInstr *MI) const {
186 const MachineFunction &MF = *MI->getParent()->getParent();
187 const MachineRegisterInfo &MRI = MF.getRegInfo();
189 while (Ret->getOpcode() == TargetOpcode::COPY &&
190 !Ret->getOperand(0).getReg().isPhysical() &&
191 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
192 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
193 }
194 return Ret;
195}
196
198MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
199 MachineInstr *MI) const {
200 const MachineFunction &MF = *MI->getParent()->getParent();
201 const MachineRegisterInfo &MRI = MF.getRegInfo();
203 while (Ret->getOpcode() == TargetOpcode::COPY &&
204 !Ret->getOperand(1).getReg().isPhysical())
205 Ret = MRI.getVRegDef(Ret->getOperand(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(MI->getOperand(0).getReg(), MRI);
218
219 if (MI->getOpcode() == TargetOpcode::G_STORE)
220 addUseDef(MI->getOperand(0).getReg(), MRI);
221
222 if (auto *PHI = dyn_cast<GPhi>(MI)) {
223 addDefUses(PHI->getReg(0), MRI);
224
225 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
226 addUseDef(PHI->getIncomingValue(I), MRI);
227 }
228
229 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
230 addDefUses(MI->getOperand(0).getReg(), MRI);
231
232 addUseDef(MI->getOperand(2).getReg(), MRI);
233 addUseDef(MI->getOperand(3).getReg(), MRI);
234 }
235
236 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
237 addDefUses(MI->getOperand(0).getReg(), MRI);
238
239 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
240 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
241
242 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
243 addDefUses(MI->getOperand(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
257 setTypes(MI, 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, DefUseContainer.getDefUses(), true, AmbiguousTy))
268 return true;
269
270 // Visit instructions that DEFINE MI's USE operands.
271 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), 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, 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(WaitingForTypeOfMI, 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(AdjMI->getOpcode())
300 setTypes(MI, 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, AdjMI, 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(AdjMI->getOpcode())) {
316 setTypes(MI, 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(AdjMI) ||
323 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
324 if (visit(AdjMI, MI, AmbiguousTy)) {
325 // InstType is successfully determined and is same as for AdjMI.
326 setTypes(MI, getRecordedTypeForInstr(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(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();
350 const RegisterBankInfo &RBI =
351 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
352 const RegisterBank *Bank =
353 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
354
355 if (Bank == &Mips::FPRBRegBank)
356 setTypes(MI, InstType::FloatingPoint);
357 else if (Bank == &Mips::GPRBRegBank)
358 setTypes(MI, 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, nullptr, 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
382 "MSA mapping not available on target without MSA.");
384}
385
387 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
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.
396getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
397 if (Size == 32)
399
400 MappingID = CustomMappingID;
402}
403
406
407 static TypeInfoForMF TI;
408
409 // Reset TI internal data when MF changes.
410 TI.cleanupIfNewFunction(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) {
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(Op.getReg());
433
434 if (RegTy.isScalar() &&
435 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
437
438 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
440 }
441 }
442
443 const LLT Op0Ty = MRI.getType(MI.getOperand(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(
483 break;
484 }
485
486 if (!Op0Ty.isPointer())
487 InstTy = TI.determineInstType(&MI);
488
489 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
490 isAmbiguous_64(InstTy, Op0Size)) {
491 OperandsMapping = getOperandsMapping(
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({getGprbOrCustomMapping(Op0Size, MappingID),
501 }
502
503 break;
504 }
505 case G_PHI: {
506 if (!Op0Ty.isPointer())
507 InstTy = TI.determineInstType(&MI);
508
509 // PHI is copylike and should have one regbank in mapping for def register.
510 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
511 OperandsMapping =
513 TI.clearTypeInfoData(&MI);
514 return getInstructionMapping(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);
528 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
529 isAmbiguous_64(InstTy, Op0Size)) {
530 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
531 OperandsMapping = getOperandsMapping(
532 {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");
540 getGprbOrCustomMapping(Op0Size, MappingID);
541 OperandsMapping = getOperandsMapping(
542 {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);
549
550 if (isFloatingPoint_32or64(InstTy, Op0Size))
551 OperandsMapping = getFprbMapping(Op0Size);
552 else {
553 assert((isInteger_32(InstTy, Op0Size) ||
554 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
555 "Unexpected Inst type");
556 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
557 }
558 } break;
559 case G_UNMERGE_VALUES: {
560 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
561 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
562 InstTy = TI.determineInstType(&MI);
563 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
564 isFloatingPoint_64(InstTy, Op3Size)) &&
565 "Unexpected Inst type");
569 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
570 MappingID = CustomMappingID;
571 break;
572 }
573 case G_MERGE_VALUES: {
574 InstTy = TI.determineInstType(&MI);
575 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
576 isFloatingPoint_64(InstTy, Op0Size)) &&
577 "Unexpected Inst type");
581 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, 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(Op0Size);
592 if (Op0Size == 128)
593 OperandsMapping = getMSAMapping(MF);
594 break;
595 case G_FCONSTANT:
596 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
597 break;
598 case G_FCMP: {
599 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
600 OperandsMapping =
602 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
603 break;
604 }
605 case G_FPEXT:
608 break;
609 case G_FPTRUNC:
612 break;
613 case G_FPTOSI: {
614 assert((Op0Size == 32) && "Unsupported integer size");
615 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
616 OperandsMapping = getOperandsMapping(
618 break;
619 }
620 case G_SITOFP:
621 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
622 "Unsupported integer size");
623 OperandsMapping = getOperandsMapping(
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 =
633 break;
634 case G_BRJT:
635 OperandsMapping =
638 break;
639 case G_ICMP:
640 OperandsMapping =
644 break;
645 default:
647 }
648
649 if (MappingID == CustomMappingID)
650 TI.clearTypeInfoData(&MI);
651 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
652 NumOperands);
653}
654
656namespace {
657class InstManager : public GISelChangeObserver {
658 InstListTy &InstList;
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(&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
677 MachineRegisterInfo &MRI) const {
678 Register Dest = MI.getOperand(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(Dest, getRegBank(Mips::GPRBRegBankID));
690 break;
691 }
692 case TargetOpcode::G_PTR_ADD: {
693 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
694 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
695 break;
696 }
697 default:
698 llvm_unreachable("Unexpected opcode.");
699 }
700}
701
702static void
704 GUnmerge &MI, GISelChangeObserver &Observer) {
705 SmallVector<Register, 4> UpdatedDefs;
707 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
708 UpdatedDefs, Observer);
709 for (MachineInstr *DeadMI : DeadInstrs)
710 DeadMI->eraseFromParent();
711}
712
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, 0, LLT::scalar(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>(NewMI))
741 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, 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(*NewMI, MRI);
749 }
750 return;
751 }
752 case TargetOpcode::G_UNMERGE_VALUES:
753 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
754 NewInstrObserver);
755 return;
756 default:
757 break;
758 }
759
760 return applyDefaultMapping(OpdMapper);
761}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Rewrite undef for PHI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
uint64_t Size
This contains common code to allow clients to notify changes to machine instr.
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
static const MipsRegisterBankInfo::ValueMapping * getGprbOrCustomMapping(unsigned Size, unsigned &MappingID)
static bool isFloatingPointOpcodeUse(unsigned Opc)
static bool isFloatingPointOpcodeDef(unsigned Opc)
static const MipsRegisterBankInfo::ValueMapping * getMSAMapping(const MachineFunction &MF)
static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI)
static bool isAmbiguous(unsigned Opc)
static const unsigned CustomMappingID
static const MipsRegisterBankInfo::ValueMapping * getFprbMapping(unsigned Size)
static void combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner, GUnmerge &MI, GISelChangeObserver &Observer)
This file declares the targeting of the RegisterBankInfo class for Mips.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class represents an Operation in the Expression.
Abstract class that contains various methods for clients to notify about changes.
void insert(MachineInstr *I)
Add the specified instruction to the worklist if it isn't already in it.
Definition: GISelWorkList.h:74
MachineInstr * pop_back_val()
bool empty() const
Definition: GISelWorkList.h:38
Represents a G_UNMERGE_VALUES.
constexpr bool isScalar() const
Definition: LowLevelType.h:146
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr bool isVector() const
Definition: LowLevelType.h:148
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:193
constexpr bool isPointer() const
Definition: LowLevelType.h:149
bool tryCombineUnmergeValues(GUnmerge &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
LegalizeResult narrowScalar(MachineInstr &MI, unsigned TypeIdx, LLT NarrowTy)
Legalize an instruction by reducing the width of the underlying scalar type.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:558
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:568
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void applyMappingImpl(MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const override
Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or G_UNMERGE and erase instruc...
MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
void setRegBank(MachineInstr &MI, MachineRegisterInfo &MRI) const
RegBankSelect determined that s64 operand is better to be split into two s32 operands in gprb.
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT) const override
Get a register bank that covers RC.
bool systemSupportsUnalignedAccess() const
Does the system support unaligned memory access.
bool hasMSA() const
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
MachineRegisterInfo & getMRI() const
The MachineRegisterInfo we used to realize the mapping.
Holds all the information related to register banks.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
Definition: RegisterBank.h:28
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:95
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
unsigned getID() const
Return the register class ID number.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const RegisterBankInfo * getRegBankInfo() const
If the information for the register banks is available, return it.
virtual const LegalizerInfo * getLegalizerInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const RegisterBankInfo::ValueMapping ValueMappings[]
const RegisterBankInfo::PartialMapping PartMappings[]
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Definition: Utils.cpp:1669
Helper struct that represents how a value is partially mapped into a register.
Helper struct that represents how a value is mapped through different register banks.