LLVM 18.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 all register operands are floating point.
108static bool isFloatingPointOpcode(unsigned Opc) {
109 switch (Opc) {
110 case TargetOpcode::G_FCONSTANT:
111 case TargetOpcode::G_FADD:
112 case TargetOpcode::G_FSUB:
113 case TargetOpcode::G_FMUL:
114 case TargetOpcode::G_FDIV:
115 case TargetOpcode::G_FABS:
116 case TargetOpcode::G_FSQRT:
117 case TargetOpcode::G_FCEIL:
118 case TargetOpcode::G_FFLOOR:
119 case TargetOpcode::G_FPEXT:
120 case TargetOpcode::G_FPTRUNC:
121 return true;
122 default:
123 return false;
124 }
125}
126
127// Instructions where use operands are floating point registers.
128// Def operands are general purpose.
129static bool isFloatingPointOpcodeUse(unsigned Opc) {
130 switch (Opc) {
131 case TargetOpcode::G_FPTOSI:
132 case TargetOpcode::G_FPTOUI:
133 case TargetOpcode::G_FCMP:
134 return true;
135 default:
136 return isFloatingPointOpcode(Opc);
137 }
138}
139
140// Instructions where def operands are floating point registers.
141// Use operands are general purpose.
142static bool isFloatingPointOpcodeDef(unsigned Opc) {
143 switch (Opc) {
144 case TargetOpcode::G_SITOFP:
145 case TargetOpcode::G_UITOFP:
146 return true;
147 default:
148 return isFloatingPointOpcode(Opc);
149 }
150}
151
153 if (MI->getOpcode() == TargetOpcode::G_LOAD ||
154 MI->getOpcode() == TargetOpcode::G_STORE) {
155 auto MMO = *MI->memoperands_begin();
156 const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
157 if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
158 MMO->getAlign() < MMO->getSize()))
159 return true;
160 }
161 return false;
162}
163
164static bool isAmbiguous(unsigned Opc) {
165 switch (Opc) {
166 case TargetOpcode::G_LOAD:
167 case TargetOpcode::G_STORE:
168 case TargetOpcode::G_PHI:
169 case TargetOpcode::G_SELECT:
170 case TargetOpcode::G_IMPLICIT_DEF:
171 case TargetOpcode::G_UNMERGE_VALUES:
172 case TargetOpcode::G_MERGE_VALUES:
173 return true;
174 default:
175 return false;
176 }
177}
178
179void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
180 Register Reg, const MachineRegisterInfo &MRI) {
181 assert(!MRI.getType(Reg).isPointer() &&
182 "Pointers are gprb, they should not be considered as ambiguous.\n");
183 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
184 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
185 // Copy with many uses.
186 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
187 !NonCopyInstr->getOperand(0).getReg().isPhysical())
188 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
189 else
190 DefUses.push_back(skipCopiesOutgoing(&UseMI));
191 }
192}
193
194void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
195 Register Reg, const MachineRegisterInfo &MRI) {
196 assert(!MRI.getType(Reg).isPointer() &&
197 "Pointers are gprb, they should not be considered as ambiguous.\n");
198 MachineInstr *DefMI = MRI.getVRegDef(Reg);
199 UseDefs.push_back(skipCopiesIncoming(DefMI));
200}
201
203MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
204 MachineInstr *MI) const {
205 const MachineFunction &MF = *MI->getParent()->getParent();
206 const MachineRegisterInfo &MRI = MF.getRegInfo();
208 while (Ret->getOpcode() == TargetOpcode::COPY &&
209 !Ret->getOperand(0).getReg().isPhysical() &&
210 MRI.hasOneUse(Ret->getOperand(0).getReg())) {
211 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
212 }
213 return Ret;
214}
215
217MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
218 MachineInstr *MI) const {
219 const MachineFunction &MF = *MI->getParent()->getParent();
220 const MachineRegisterInfo &MRI = MF.getRegInfo();
222 while (Ret->getOpcode() == TargetOpcode::COPY &&
223 !Ret->getOperand(1).getReg().isPhysical())
224 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
225 return Ret;
226}
227
228MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
229 const MachineInstr *MI) {
230 assert(isAmbiguous(MI->getOpcode()) &&
231 "Not implemented for non Ambiguous opcode.\n");
232
233 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
234
235 if (MI->getOpcode() == TargetOpcode::G_LOAD)
236 addDefUses(MI->getOperand(0).getReg(), MRI);
237
238 if (MI->getOpcode() == TargetOpcode::G_STORE)
239 addUseDef(MI->getOperand(0).getReg(), MRI);
240
241 if (MI->getOpcode() == TargetOpcode::G_PHI) {
242 addDefUses(MI->getOperand(0).getReg(), MRI);
243
244 for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
245 addUseDef(MI->getOperand(i).getReg(), MRI);
246 }
247
248 if (MI->getOpcode() == TargetOpcode::G_SELECT) {
249 addDefUses(MI->getOperand(0).getReg(), MRI);
250
251 addUseDef(MI->getOperand(2).getReg(), MRI);
252 addUseDef(MI->getOperand(3).getReg(), MRI);
253 }
254
255 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
256 addDefUses(MI->getOperand(0).getReg(), MRI);
257
258 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
259 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
260
261 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
262 addDefUses(MI->getOperand(0).getReg(), MRI);
263}
264
265bool MipsRegisterBankInfo::TypeInfoForMF::visit(
266 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
267 InstType &AmbiguousTy) {
268 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
269 if (wasVisited(MI))
270 return true; // InstType has already been determined for MI.
271
272 startVisit(MI);
273 AmbiguousRegDefUseContainer DefUseContainer(MI);
274
276 setTypes(MI, Integer);
277 return true;
278 }
279
280 if (AmbiguousTy == InstType::Ambiguous &&
281 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
282 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
283 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
284
285 // Visit instructions where MI's DEF operands are USED.
286 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
287 return true;
288
289 // Visit instructions that DEFINE MI's USE operands.
290 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
291 return true;
292
293 // All MI's adjacent instructions, are ambiguous.
294 if (!WaitingForTypeOfMI) {
295 // This is chain of ambiguous instructions.
296 setTypes(MI, AmbiguousTy);
297 return true;
298 }
299 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
300 // instructions or has no other adjacent instructions. Anyway InstType could
301 // not be determined. There could be unexplored path from some of
302 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
303 // mapping available.
304 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
305 // this way when WaitingForTypeOfMI figures out its InstType same InstType
306 // will be assigned to all instructions in this branch.
307 addToWaitingQueue(WaitingForTypeOfMI, MI);
308 return false;
309}
310
311bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
312 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
313 bool isDefUse, InstType &AmbiguousTy) {
314 while (!AdjacentInstrs.empty()) {
315 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
316
317 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
319 setTypes(MI, InstType::FloatingPoint);
320 return true;
321 }
322
323 // Determine InstType from register bank of phys register that is
324 // 'isDefUse ? def : use' of this copy.
325 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
326 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
327 return true;
328 }
329
330 // Defaults to integer instruction. Small registers in G_MERGE (uses) and
331 // G_UNMERGE (defs) will always be gprb.
332 if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
333 (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
334 !isAmbiguous(AdjMI->getOpcode())) {
335 setTypes(MI, InstType::Integer);
336 return true;
337 }
338
339 // When AdjMI was visited first, MI has to continue to explore remaining
340 // adjacent instructions and determine InstType without visiting AdjMI.
341 if (!wasVisited(AdjMI) ||
342 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
343 if (visit(AdjMI, MI, AmbiguousTy)) {
344 // InstType is successfully determined and is same as for AdjMI.
345 setTypes(MI, getRecordedTypeForInstr(AdjMI));
346 return true;
347 }
348 }
349 }
350 return false;
351}
352
353void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
354 InstType InstTy) {
355 changeRecordedTypeForInstr(MI, InstTy);
356 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
357 setTypes(WaitingInstr, InstTy);
358 }
359}
360
361void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
362 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
363 assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&
364 "Copies of non physical registers should not be considered here.\n");
365
366 const MachineFunction &MF = *CopyInst->getMF();
367 const MachineRegisterInfo &MRI = MF.getRegInfo();
369 const RegisterBankInfo &RBI =
370 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
371 const RegisterBank *Bank =
372 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
373
374 if (Bank == &Mips::FPRBRegBank)
375 setTypes(MI, InstType::FloatingPoint);
376 else if (Bank == &Mips::GPRBRegBank)
377 setTypes(MI, InstType::Integer);
378 else
379 llvm_unreachable("Unsupported register bank.\n");
380}
381
382MipsRegisterBankInfo::InstType
383MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
384 InstType DefaultAmbiguousType = InstType::Ambiguous;
385 visit(MI, nullptr, DefaultAmbiguousType);
386 return getRecordedTypeForInstr(MI);
387}
388
389void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
390 llvm::StringRef FunctionName) {
391 if (MFName != FunctionName) {
392 MFName = std::string(FunctionName);
393 WaitingQueues.clear();
394 Types.clear();
395 }
396}
397
401 "MSA mapping not available on target without MSA.");
403}
404
406 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
408}
409
410static const unsigned CustomMappingID = 1;
411
412// Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
413// will be split into two 32 bit registers in gprb.
415getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
416 if (Size == 32)
418
419 MappingID = CustomMappingID;
421}
422
425
426 static TypeInfoForMF TI;
427
428 // Reset TI internal data when MF changes.
429 TI.cleanupIfNewFunction(MI.getMF()->getName());
430
431 unsigned Opc = MI.getOpcode();
432 const MachineFunction &MF = *MI.getParent()->getParent();
433 const MachineRegisterInfo &MRI = MF.getRegInfo();
434
435 if (MI.getOpcode() != TargetOpcode::G_PHI) {
438 if (Mapping.isValid())
439 return Mapping;
440 }
441
442 using namespace TargetOpcode;
443
444 unsigned NumOperands = MI.getNumOperands();
445 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
446 unsigned MappingID = DefaultMappingID;
447
448 // Check if LLT sizes match sizes of available register banks.
449 for (const MachineOperand &Op : MI.operands()) {
450 if (Op.isReg()) {
451 LLT RegTy = MRI.getType(Op.getReg());
452
453 if (RegTy.isScalar() &&
454 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
456
457 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
459 }
460 }
461
462 const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
463 unsigned Op0Size = Op0Ty.getSizeInBits();
464 InstType InstTy = InstType::Integer;
465
466 switch (Opc) {
467 case G_TRUNC:
468 case G_UMULH:
469 case G_ZEXTLOAD:
470 case G_SEXTLOAD:
471 case G_PTR_ADD:
472 case G_INTTOPTR:
473 case G_PTRTOINT:
474 case G_AND:
475 case G_OR:
476 case G_XOR:
477 case G_SHL:
478 case G_ASHR:
479 case G_LSHR:
480 case G_BRINDIRECT:
481 case G_VASTART:
482 case G_BSWAP:
483 case G_CTLZ:
484 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
485 break;
486 case G_ADD:
487 case G_SUB:
488 case G_MUL:
489 case G_SDIV:
490 case G_SREM:
491 case G_UDIV:
492 case G_UREM:
493 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
494 if (Op0Size == 128)
495 OperandsMapping = getMSAMapping(MF);
496 break;
497 case G_STORE:
498 case G_LOAD: {
499 if (Op0Size == 128) {
500 OperandsMapping = getOperandsMapping(
502 break;
503 }
504
505 if (!Op0Ty.isPointer())
506 InstTy = TI.determineInstType(&MI);
507
508 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
509 isAmbiguous_64(InstTy, Op0Size)) {
510 OperandsMapping = getOperandsMapping(
512 } else {
513 assert((isInteger_32(InstTy, Op0Size) ||
514 isAmbiguous_32(InstTy, Op0Size) ||
515 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
516 "Unexpected Inst type");
517 OperandsMapping =
518 getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
520 }
521
522 break;
523 }
524 case G_PHI: {
525 if (!Op0Ty.isPointer())
526 InstTy = TI.determineInstType(&MI);
527
528 // PHI is copylike and should have one regbank in mapping for def register.
529 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
530 OperandsMapping =
532 TI.clearTypeInfoData(&MI);
533 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
534 /*NumOperands=*/1);
535 }
536 assert((isInteger_32(InstTy, Op0Size) ||
537 isFloatingPoint_32or64(InstTy, Op0Size) ||
538 isAmbiguous_32or64(InstTy, Op0Size)) &&
539 "Unexpected Inst type");
540 // Use default handling for PHI, i.e. set reg bank of def operand to match
541 // register banks of use operands.
542 return getInstrMappingImpl(MI);
543 }
544 case G_SELECT: {
545 if (!Op0Ty.isPointer())
546 InstTy = TI.determineInstType(&MI);
547 if (isFloatingPoint_32or64(InstTy, Op0Size) ||
548 isAmbiguous_64(InstTy, Op0Size)) {
549 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
550 OperandsMapping = getOperandsMapping(
551 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
552 break;
553 } else {
554 assert((isInteger_32(InstTy, Op0Size) ||
555 isAmbiguous_32(InstTy, Op0Size) ||
556 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
557 "Unexpected Inst type");
559 getGprbOrCustomMapping(Op0Size, MappingID);
560 OperandsMapping = getOperandsMapping(
561 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
562 }
563 break;
564 }
565 case G_IMPLICIT_DEF: {
566 if (!Op0Ty.isPointer())
567 InstTy = TI.determineInstType(&MI);
568
569 if (isFloatingPoint_32or64(InstTy, Op0Size))
570 OperandsMapping = getFprbMapping(Op0Size);
571 else {
572 assert((isInteger_32(InstTy, Op0Size) ||
573 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
574 "Unexpected Inst type");
575 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
576 }
577 } break;
578 case G_UNMERGE_VALUES: {
579 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
580 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
581 InstTy = TI.determineInstType(&MI);
582 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
583 isFloatingPoint_64(InstTy, Op3Size)) &&
584 "Unexpected Inst type");
588 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
589 MappingID = CustomMappingID;
590 break;
591 }
592 case G_MERGE_VALUES: {
593 InstTy = TI.determineInstType(&MI);
594 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
595 isFloatingPoint_64(InstTy, Op0Size)) &&
596 "Unexpected Inst type");
600 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
601 MappingID = CustomMappingID;
602 break;
603 }
604 case G_FADD:
605 case G_FSUB:
606 case G_FMUL:
607 case G_FDIV:
608 case G_FABS:
609 case G_FSQRT:
610 OperandsMapping = getFprbMapping(Op0Size);
611 if (Op0Size == 128)
612 OperandsMapping = getMSAMapping(MF);
613 break;
614 case G_FCONSTANT:
615 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
616 break;
617 case G_FCMP: {
618 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
619 OperandsMapping =
621 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
622 break;
623 }
624 case G_FPEXT:
627 break;
628 case G_FPTRUNC:
631 break;
632 case G_FPTOSI: {
633 assert((Op0Size == 32) && "Unsupported integer size");
634 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
635 OperandsMapping = getOperandsMapping(
637 break;
638 }
639 case G_SITOFP:
640 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
641 "Unsupported integer size");
642 OperandsMapping = getOperandsMapping(
644 break;
645 case G_CONSTANT:
646 case G_FRAME_INDEX:
647 case G_GLOBAL_VALUE:
648 case G_JUMP_TABLE:
649 case G_BRCOND:
650 OperandsMapping =
652 break;
653 case G_BRJT:
654 OperandsMapping =
657 break;
658 case G_ICMP:
659 OperandsMapping =
663 break;
664 default:
666 }
667
668 if (MappingID == CustomMappingID)
669 TI.clearTypeInfoData(&MI);
670 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
671 NumOperands);
672}
673
675namespace {
676class InstManager : public GISelChangeObserver {
677 InstListTy &InstList;
679
680public:
681 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
682 assert(!B.isObservingChanges());
683 B.setChangeObserver(*this);
684 }
685
686 ~InstManager() { B.stopObservingChanges(); }
687
688 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
689 void erasingInstr(MachineInstr &MI) override {}
690 void changingInstr(MachineInstr &MI) override {}
691 void changedInstr(MachineInstr &MI) override {}
692};
693} // end anonymous namespace
694
696 MachineRegisterInfo &MRI) const {
697 Register Dest = MI.getOperand(0).getReg();
698 switch (MI.getOpcode()) {
699 case TargetOpcode::G_STORE:
700 // No def operands, skip this instruction.
701 break;
702 case TargetOpcode::G_CONSTANT:
703 case TargetOpcode::G_LOAD:
704 case TargetOpcode::G_SELECT:
705 case TargetOpcode::G_PHI:
706 case TargetOpcode::G_IMPLICIT_DEF: {
707 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
708 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
709 break;
710 }
711 case TargetOpcode::G_PTR_ADD: {
712 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
713 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
714 break;
715 }
716 default:
717 llvm_unreachable("Unexpected opcode.");
718 }
719}
720
721static void
723 GUnmerge &MI, GISelChangeObserver &Observer) {
724 SmallVector<Register, 4> UpdatedDefs;
726 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
727 UpdatedDefs, Observer);
728 for (MachineInstr *DeadMI : DeadInstrs)
729 DeadMI->eraseFromParent();
730}
731
733 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
734 MachineInstr &MI = OpdMapper.getMI();
735 Builder.setInstrAndDebugLoc(MI);
736
737 InstListTy NewInstrs;
738 MachineFunction *MF = MI.getMF();
739 MachineRegisterInfo &MRI = OpdMapper.getMRI();
740 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
741
742 InstManager NewInstrObserver(Builder, NewInstrs);
743 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
744 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
745
746 switch (MI.getOpcode()) {
747 case TargetOpcode::G_LOAD:
748 case TargetOpcode::G_STORE:
749 case TargetOpcode::G_PHI:
750 case TargetOpcode::G_SELECT:
751 case TargetOpcode::G_IMPLICIT_DEF: {
752 Helper.narrowScalar(MI, 0, LLT::scalar(32));
753 // Handle new instructions.
754 while (!NewInstrs.empty()) {
755 MachineInstr *NewMI = NewInstrs.pop_back_val();
756 // This is new G_UNMERGE that was created during narrowScalar and will
757 // not be considered for regbank selection. RegBankSelect for mips
758 // visits/makes corresponding G_MERGE first. Combine them here.
759 if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
760 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
761 // This G_MERGE will be combined away when its corresponding G_UNMERGE
762 // gets regBankSelected.
763 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
764 continue;
765 else
766 // Manually set register banks for def operands to 32 bit gprb.
767 setRegBank(*NewMI, MRI);
768 }
769 return;
770 }
771 case TargetOpcode::G_UNMERGE_VALUES:
772 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
773 NewInstrObserver);
774 return;
775 default:
776 break;
777 }
778
779 return applyDefaultMapping(OpdMapper);
780}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assume Assume Builder
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
unsigned const TargetRegisterInfo * TRI
static const MipsRegisterBankInfo::ValueMapping * getGprbOrCustomMapping(unsigned Size, unsigned &MappingID)
static bool isFloatingPointOpcodeUse(unsigned Opc)
static bool isFloatingPointOpcode(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:139
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:145
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:175
constexpr bool isPointer() const
Definition: LowLevelType.h:141
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.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:543
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:553
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.
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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.
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:577
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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.
RegisterBankInfo::PartialMapping PartMappings[]
RegisterBankInfo::ValueMapping ValueMappings[]
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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.