LLVM 22.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 {
35
37 {0, 64, GPRBRegBank},
38 {0, 32, FPRBRegBank},
39 {0, 64, FPRBRegBank},
40 {0, 128, FPRBRegBank}};
41
50
52 // invalid
53 {nullptr, 0},
54 // up to 3 operands in GPRs; 32 bit.
58 // up to 3 operands in GPRs; 64 bit.
62 // up to 3 operands in FPRs - single precission
66 // up to 3 operands in FPRs - double precission
70 // up to 3 operands in FPRs - MSA
74
75} // end namespace Mips
76} // end namespace llvm
77
78using namespace llvm;
79
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:
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:
104 }
105}
106
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(
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(&UseMI);
141 // Copy with many uses.
142 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
143 !NonCopyInstr->getOperand(0).getReg().isPhysical())
144 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
145 else
146 DefUses.push_back(skipCopiesOutgoing(&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(skipCopiesIncoming(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(0).getReg().isPhysical() &&
166 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
167 Ret = &(*MRI.use_instr_begin(Ret->getOperand(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(1).getReg().isPhysical())
180 Ret = MRI.getVRegDef(Ret->getOperand(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(MI->getOperand(0).getReg(), MRI);
193
194 if (MI->getOpcode() == TargetOpcode::G_STORE)
195 addUseDef(MI->getOperand(0).getReg(), MRI);
196
197 if (auto *PHI = dyn_cast<GPhi>(MI)) {
198 addDefUses(PHI->getReg(0), MRI);
199
200 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
201 addUseDef(PHI->getIncomingValue(I), MRI);
202 }
203
204 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
205 addDefUses(MI->getOperand(0).getReg(), MRI);
206
207 addUseDef(MI->getOperand(2).getReg(), MRI);
208 addUseDef(MI->getOperand(3).getReg(), MRI);
209 }
210
211 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
212 addDefUses(MI->getOperand(0).getReg(), MRI);
213
214 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
215 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
216
217 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
218 addDefUses(MI->getOperand(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
232 setTypes(MI, 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, DefUseContainer.getDefUses(), true, AmbiguousTy))
243 return true;
244
245 // Visit instructions that DEFINE MI's USE operands.
246 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), 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, 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(WaitingForTypeOfMI, 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(AdjMI->getOpcode())
275 setTypes(MI, 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, AdjMI, 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(AdjMI->getOpcode())) {
291 setTypes(MI, 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(AdjMI) ||
298 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
299 if (visit(AdjMI, MI, AmbiguousTy)) {
300 // InstType is successfully determined and is same as for AdjMI.
301 setTypes(MI, getRecordedTypeForInstr(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(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(CopyInst->getOperand(Op).getReg(), MRI, TRI);
329
330 if (Bank == &Mips::FPRBRegBank)
331 setTypes(MI, InstType::FloatingPoint);
332 else if (Bank == &Mips::GPRBRegBank)
333 setTypes(MI, 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, nullptr, 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 *
357 "MSA mapping not available on target without MSA.");
359}
360
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.
371getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
372 if (Size == 32)
374
375 MappingID = CustomMappingID;
377}
378
379const RegisterBankInfo::InstructionMapping &
381
382 static TypeInfoForMF TI;
383
384 // Reset TI internal data when MF changes.
385 TI.cleanupIfNewFunction(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) {
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(Mips::GPRBRegBankID);
403 assert((GPRSize == 32 || GPRSize == 64) && "Unexpected GPR size");
404 const ValueMapping *GPRValueMapping =
405 GPRSize == 32 ? &Mips::ValueMappings[Mips::GPR32Idx]
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(Op.getReg());
413
414 if (RegTy.isScalar() &&
415 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
417
418 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
420 }
421 }
422
423 const LLT Op0Ty = MRI.getType(MI.getOperand(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({getMSAMapping(MF), GPRValueMapping});
463 break;
464 }
465
466 if (!Op0Ty.isPointer())
467 InstTy = TI.determineInstType(&MI);
468
469 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
470 isAmbiguous_64(InstTy, Op0Size)) {
471 OperandsMapping =
472 getOperandsMapping({getFprbMapping(Op0Size), GPRValueMapping});
473 } else if (InstTy == InstType::Integer) {
474 OperandsMapping = getOperandsMapping({GPRValueMapping, GPRValueMapping});
475 } else {
476 assert((isAmbiguous_32(InstTy, Op0Size) ||
477 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
478 "Unexpected Inst type");
479 OperandsMapping = getOperandsMapping(
480 {getGprbOrCustomMapping(Op0Size, MappingID), GPRValueMapping});
481 }
482
483 break;
484 }
485 case G_PHI: {
486 if (!Op0Ty.isPointer())
487 InstTy = TI.determineInstType(&MI);
488
489 // PHI is copylike and should have one regbank in mapping for def register.
490 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
491 OperandsMapping =
493 TI.clearTypeInfoData(&MI);
494 return getInstructionMapping(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);
508
509 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
510 isAmbiguous_64(InstTy, Op0Size)) {
511 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
512 OperandsMapping = getOperandsMapping({Bank, GPRValueMapping, Bank, Bank});
513 break;
514 } else if (InstTy == InstType::Integer) {
515 OperandsMapping = getOperandsMapping(
516 {GPRValueMapping, GPRValueMapping, GPRValueMapping, GPRValueMapping});
517 } else {
518 assert((isAmbiguous_32(InstTy, Op0Size) ||
519 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
520 "Unexpected Inst type");
522 getGprbOrCustomMapping(Op0Size, MappingID);
523 OperandsMapping = getOperandsMapping({Bank, GPRValueMapping, Bank, Bank});
524 }
525 break;
526 }
527 case G_IMPLICIT_DEF: {
528 if (!Op0Ty.isPointer())
529 InstTy = TI.determineInstType(&MI);
530
531 if (isFloatingPoint_32or64(InstTy, Op0Size))
532 OperandsMapping = getFprbMapping(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(Op0Size, MappingID);
539 }
540 } break;
541 case G_UNMERGE_VALUES: {
542 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
543 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
544 InstTy = TI.determineInstType(&MI);
545 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
546 isFloatingPoint_64(InstTy, Op3Size)) &&
547 "Unexpected Inst type");
548 OperandsMapping = getOperandsMapping(
549 {GPRValueMapping, GPRValueMapping, &Mips::ValueMappings[Mips::DPRIdx]});
550 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
551 MappingID = CustomMappingID;
552 break;
553 }
554 case G_MERGE_VALUES: {
555 InstTy = TI.determineInstType(&MI);
556 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
557 isFloatingPoint_64(InstTy, Op0Size)) &&
558 "Unexpected Inst type");
559 OperandsMapping = getOperandsMapping(
560 {&Mips::ValueMappings[Mips::DPRIdx], GPRValueMapping, GPRValueMapping});
561 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, 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(Op0Size);
572 if (Op0Size == 128)
573 OperandsMapping = getMSAMapping(MF);
574 break;
575 case G_FCONSTANT:
576 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
577 break;
578 case G_FCMP: {
579 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
580 OperandsMapping =
581 getOperandsMapping({GPRValueMapping, nullptr, getFprbMapping(Op2Size),
582 getFprbMapping(Op2Size)});
583 break;
584 }
585 case G_FPEXT:
588 break;
589 case G_FPTRUNC:
592 break;
593 case G_FPTOSI: {
594 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
595 OperandsMapping =
596 getOperandsMapping({GPRValueMapping, getFprbMapping(SizeFP)});
597 break;
598 }
599 case G_SITOFP:
600 OperandsMapping =
601 getOperandsMapping({getFprbMapping(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({GPRValueMapping, nullptr});
609 break;
610 case G_BRJT:
611 OperandsMapping =
612 getOperandsMapping({GPRValueMapping, nullptr, GPRValueMapping});
613 break;
614 case G_ICMP:
615 OperandsMapping = getOperandsMapping(
616 {GPRValueMapping, nullptr, GPRValueMapping, GPRValueMapping});
617 break;
618 default:
620 }
621
622 if (MappingID == CustomMappingID)
623 TI.clearTypeInfoData(&MI);
624 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
625 NumOperands);
626}
627
629namespace {
630class InstManager : public GISelChangeObserver {
631 InstListTy &InstList;
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(&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
650 MachineRegisterInfo &MRI) const {
651 Register Dest = MI.getOperand(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(Dest, getRegBank(Mips::GPRBRegBankID));
663 break;
664 }
665 case TargetOpcode::G_PTR_ADD: {
666 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
667 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
668 break;
669 }
670 default:
671 llvm_unreachable("Unexpected opcode.");
672 }
673}
674
675static void
677 GUnmerge &MI, GISelChangeObserver &Observer) {
678 SmallVector<Register, 4> UpdatedDefs;
680 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
681 UpdatedDefs, Observer);
682 for (MachineInstr *DeadMI : DeadInstrs)
683 DeadMI->eraseFromParent();
684}
685
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, 0, LLT::scalar(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>(NewMI))
714 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, 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(*NewMI, MRI);
722 }
723 return;
724 }
725 case TargetOpcode::G_UNMERGE_VALUES:
727 NewInstrObserver);
728 return;
729 default:
730 break;
731 }
732
733 return applyDefaultMapping(OpdMapper);
734}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const unsigned CustomMappingID
Rewrite undef for PHI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This contains common code to allow clients to notify changes to machine instr.
IRTranslator LLVM IR MI
GISelWorkList< 256 > InstListTy
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
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.
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
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.
MachineInstr * pop_back_val()
Represents a G_UNMERGE_VALUES.
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
bool tryCombineUnmergeValues(GUnmerge &MI, SmallVectorImpl< MachineInstr * > &DeadInsts, SmallVectorImpl< Register > &UpdatedDefs, GISelChangeObserver &Observer)
LLVM_ABI 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.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const MachineOperand & getOperand(unsigned i) const
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.
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.
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.
unsigned getMaximumSize(unsigned RegBankID) const
Get the maximum size in bits that fits in the given register bank.
RegisterBankInfo(const RegisterBank **RegBanks, unsigned NumRegBanks, const unsigned *Sizes, unsigned HwMode)
Create a RegisterBankInfo that can accommodate up to NumRegBanks RegisterBank instances.
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.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const RegisterBankInfo * getRegBankInfo() const
If the information for the register banks is available, return it.
virtual const LegalizerInfo * getLegalizerInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const RegisterBankInfo::ValueMapping ValueMappings[]
const RegisterBankInfo::PartialMapping PartMappings[]
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Definition Utils.cpp:1750
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.