LLVM 17.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;
678
679public:
680 InstManager(InstListTy &Insts) : InstList(Insts) {}
681
682 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
683 void erasingInstr(MachineInstr &MI) override {}
684 void changingInstr(MachineInstr &MI) override {}
685 void changedInstr(MachineInstr &MI) override {}
686};
687} // end anonymous namespace
688
690 MachineRegisterInfo &MRI) const {
691 Register Dest = MI.getOperand(0).getReg();
692 switch (MI.getOpcode()) {
693 case TargetOpcode::G_STORE:
694 // No def operands, skip this instruction.
695 break;
696 case TargetOpcode::G_CONSTANT:
697 case TargetOpcode::G_LOAD:
698 case TargetOpcode::G_SELECT:
699 case TargetOpcode::G_PHI:
700 case TargetOpcode::G_IMPLICIT_DEF: {
701 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
702 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
703 break;
704 }
705 case TargetOpcode::G_PTR_ADD: {
706 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
707 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
708 break;
709 }
710 default:
711 llvm_unreachable("Unexpected opcode.");
712 }
713}
714
715static void
717 GUnmerge &MI, GISelChangeObserver &Observer) {
718 SmallVector<Register, 4> UpdatedDefs;
720 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
721 UpdatedDefs, Observer);
722 for (MachineInstr *DeadMI : DeadInstrs)
723 DeadMI->eraseFromParent();
724}
725
727 const OperandsMapper &OpdMapper) const {
728 MachineInstr &MI = OpdMapper.getMI();
729 InstListTy NewInstrs;
730 MachineFunction *MF = MI.getMF();
731 MachineRegisterInfo &MRI = OpdMapper.getMRI();
732 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
733
734 InstManager NewInstrObserver(NewInstrs);
735 MachineIRBuilder B(MI, NewInstrObserver);
736 LegalizerHelper Helper(*MF, NewInstrObserver, B);
737 LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
738
739 switch (MI.getOpcode()) {
740 case TargetOpcode::G_LOAD:
741 case TargetOpcode::G_STORE:
742 case TargetOpcode::G_PHI:
743 case TargetOpcode::G_SELECT:
744 case TargetOpcode::G_IMPLICIT_DEF: {
745 Helper.narrowScalar(MI, 0, LLT::scalar(32));
746 // Handle new instructions.
747 while (!NewInstrs.empty()) {
748 MachineInstr *NewMI = NewInstrs.pop_back_val();
749 // This is new G_UNMERGE that was created during narrowScalar and will
750 // not be considered for regbank selection. RegBankSelect for mips
751 // visits/makes corresponding G_MERGE first. Combine them here.
752 if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
753 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
754 // This G_MERGE will be combined away when its corresponding G_UNMERGE
755 // gets regBankSelected.
756 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
757 continue;
758 else
759 // Manually set register banks for def operands to 32 bit gprb.
760 setRegBank(*NewMI, MRI);
761 }
762 return;
763 }
764 case TargetOpcode::G_UNMERGE_VALUES:
765 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
766 NewInstrObserver);
767 return;
768 default:
769 break;
770 }
771
772 return applyDefaultMapping(OpdMapper);
773}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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())
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
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)
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:516
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:526
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,...
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.
void applyMappingImpl(const OperandsMapper &OpdMapper) const override
Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or G_UNMERGE and erase instruc...
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.
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
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:97
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.