LLVM 20.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
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:
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:
100 }
101}
102
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(&UseMI);
137 // Copy with many uses.
138 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
139 !NonCopyInstr->getOperand(0).getReg().isPhysical())
140 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
141 else
142 DefUses.push_back(skipCopiesOutgoing(&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(skipCopiesIncoming(DefMI));
152}
153
155MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
156 MachineInstr *MI) const {
157 const MachineFunction &MF = *MI->getParent()->getParent();
158 const MachineRegisterInfo &MRI = MF.getRegInfo();
160 while (Ret->getOpcode() == TargetOpcode::COPY &&
161 !Ret->getOperand(0).getReg().isPhysical() &&
162 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
163 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
164 }
165 return Ret;
166}
167
169MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
170 MachineInstr *MI) const {
171 const MachineFunction &MF = *MI->getParent()->getParent();
172 const MachineRegisterInfo &MRI = MF.getRegInfo();
174 while (Ret->getOpcode() == TargetOpcode::COPY &&
175 !Ret->getOperand(1).getReg().isPhysical())
176 Ret = MRI.getVRegDef(Ret->getOperand(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(MI->getOperand(0).getReg(), MRI);
189
190 if (MI->getOpcode() == TargetOpcode::G_STORE)
191 addUseDef(MI->getOperand(0).getReg(), MRI);
192
193 if (auto *PHI = dyn_cast<GPhi>(MI)) {
194 addDefUses(PHI->getReg(0), MRI);
195
196 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
197 addUseDef(PHI->getIncomingValue(I), MRI);
198 }
199
200 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
201 addDefUses(MI->getOperand(0).getReg(), MRI);
202
203 addUseDef(MI->getOperand(2).getReg(), MRI);
204 addUseDef(MI->getOperand(3).getReg(), MRI);
205 }
206
207 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
208 addDefUses(MI->getOperand(0).getReg(), MRI);
209
210 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
211 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
212
213 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
214 addDefUses(MI->getOperand(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
228 setTypes(MI, 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, DefUseContainer.getDefUses(), true, AmbiguousTy))
239 return true;
240
241 // Visit instructions that DEFINE MI's USE operands.
242 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), 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, 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(WaitingForTypeOfMI, 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(AdjMI->getOpcode())
271 setTypes(MI, 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, AdjMI, 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(AdjMI->getOpcode())) {
287 setTypes(MI, 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(AdjMI) ||
294 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
295 if (visit(AdjMI, MI, AmbiguousTy)) {
296 // InstType is successfully determined and is same as for AdjMI.
297 setTypes(MI, getRecordedTypeForInstr(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(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();
321 const RegisterBankInfo &RBI =
322 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
323 const RegisterBank *Bank =
324 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
325
326 if (Bank == &Mips::FPRBRegBank)
327 setTypes(MI, InstType::FloatingPoint);
328 else if (Bank == &Mips::GPRBRegBank)
329 setTypes(MI, 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, nullptr, 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
353 "MSA mapping not available on target without MSA.");
355}
356
358 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
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.
367getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
368 if (Size == 32)
370
371 MappingID = CustomMappingID;
373}
374
377
378 static TypeInfoForMF TI;
379
380 // Reset TI internal data when MF changes.
381 TI.cleanupIfNewFunction(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) {
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(Op.getReg());
404
405 if (RegTy.isScalar() &&
406 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
408
409 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
411 }
412 }
413
414 const LLT Op0Ty = MRI.getType(MI.getOperand(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(
454 break;
455 }
456
457 if (!Op0Ty.isPointer())
458 InstTy = TI.determineInstType(&MI);
459
460 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
461 isAmbiguous_64(InstTy, Op0Size)) {
462 OperandsMapping = getOperandsMapping(
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({getGprbOrCustomMapping(Op0Size, MappingID),
472 }
473
474 break;
475 }
476 case G_PHI: {
477 if (!Op0Ty.isPointer())
478 InstTy = TI.determineInstType(&MI);
479
480 // PHI is copylike and should have one regbank in mapping for def register.
481 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
482 OperandsMapping =
484 TI.clearTypeInfoData(&MI);
485 return getInstructionMapping(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);
499 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
500 isAmbiguous_64(InstTy, Op0Size)) {
501 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
502 OperandsMapping = getOperandsMapping(
503 {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");
511 getGprbOrCustomMapping(Op0Size, MappingID);
512 OperandsMapping = getOperandsMapping(
513 {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);
520
521 if (isFloatingPoint_32or64(InstTy, Op0Size))
522 OperandsMapping = getFprbMapping(Op0Size);
523 else {
524 assert((isInteger_32(InstTy, Op0Size) ||
525 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
526 "Unexpected Inst type");
527 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
528 }
529 } break;
530 case G_UNMERGE_VALUES: {
531 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
532 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
533 InstTy = TI.determineInstType(&MI);
534 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
535 isFloatingPoint_64(InstTy, Op3Size)) &&
536 "Unexpected Inst type");
540 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
541 MappingID = CustomMappingID;
542 break;
543 }
544 case G_MERGE_VALUES: {
545 InstTy = TI.determineInstType(&MI);
546 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
547 isFloatingPoint_64(InstTy, Op0Size)) &&
548 "Unexpected Inst type");
552 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, 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(Op0Size);
563 if (Op0Size == 128)
564 OperandsMapping = getMSAMapping(MF);
565 break;
566 case G_FCONSTANT:
567 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
568 break;
569 case G_FCMP: {
570 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
571 OperandsMapping =
573 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
574 break;
575 }
576 case G_FPEXT:
579 break;
580 case G_FPTRUNC:
583 break;
584 case G_FPTOSI: {
585 assert((Op0Size == 32) && "Unsupported integer size");
586 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
587 OperandsMapping = getOperandsMapping(
589 break;
590 }
591 case G_SITOFP:
592 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
593 "Unsupported integer size");
594 OperandsMapping = getOperandsMapping(
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 =
604 break;
605 case G_BRJT:
606 OperandsMapping =
609 break;
610 case G_ICMP:
611 OperandsMapping =
615 break;
616 default:
618 }
619
620 if (MappingID == CustomMappingID)
621 TI.clearTypeInfoData(&MI);
622 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
623 NumOperands);
624}
625
627namespace {
628class InstManager : public GISelChangeObserver {
629 InstListTy &InstList;
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(&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
648 MachineRegisterInfo &MRI) const {
649 Register Dest = MI.getOperand(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(Dest, getRegBank(Mips::GPRBRegBankID));
661 break;
662 }
663 case TargetOpcode::G_PTR_ADD: {
664 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
665 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
666 break;
667 }
668 default:
669 llvm_unreachable("Unexpected opcode.");
670 }
671}
672
673static void
675 GUnmerge &MI, GISelChangeObserver &Observer) {
676 SmallVector<Register, 4> UpdatedDefs;
678 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
679 UpdatedDefs, Observer);
680 for (MachineInstr *DeadMI : DeadInstrs)
681 DeadMI->eraseFromParent();
682}
683
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, 0, LLT::scalar(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>(NewMI))
712 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, 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(*NewMI, MRI);
720 }
721 return;
722 }
723 case TargetOpcode::G_UNMERGE_VALUES:
724 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
725 NewInstrObserver);
726 return;
727 default:
728 break;
729 }
730
731 return applyDefaultMapping(OpdMapper);
732}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static const unsigned CustomMappingID
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 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:569
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:579
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.
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
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:1697
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.