1 //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the RegisterBankInfo class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #include "MipsRegisterBankInfo.h"
14 #include "MipsInstrInfo.h"
15 #include "MipsTargetMachine.h"
16 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17 #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
18 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #define GET_TARGET_REGBANK_IMPL
23 #include "MipsGenRegisterBank.inc"
27 enum PartialMappingIdx
{
35 const RegisterBankInfo::PartialMapping PartMappings
[]{
42 enum ValueMappingIdx
{
50 const RegisterBankInfo::ValueMapping ValueMappings
[] = {
53 // up to 3 operands in GPRs
54 {&PartMappings
[PMI_GPR
- PMI_Min
], 1},
55 {&PartMappings
[PMI_GPR
- PMI_Min
], 1},
56 {&PartMappings
[PMI_GPR
- PMI_Min
], 1},
57 // up to 3 operands in FPRs - single precission
58 {&PartMappings
[PMI_SPR
- PMI_Min
], 1},
59 {&PartMappings
[PMI_SPR
- PMI_Min
], 1},
60 {&PartMappings
[PMI_SPR
- PMI_Min
], 1},
61 // up to 3 operands in FPRs - double precission
62 {&PartMappings
[PMI_DPR
- PMI_Min
], 1},
63 {&PartMappings
[PMI_DPR
- PMI_Min
], 1},
64 {&PartMappings
[PMI_DPR
- PMI_Min
], 1},
65 // up to 3 operands in FPRs - MSA
66 {&PartMappings
[PMI_MSA
- PMI_Min
], 1},
67 {&PartMappings
[PMI_MSA
- PMI_Min
], 1},
68 {&PartMappings
[PMI_MSA
- PMI_Min
], 1}
71 } // end namespace Mips
72 } // end namespace llvm
76 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo
&TRI
) {}
79 MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass
&RC
,
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
);
103 llvm_unreachable("Register class not supported");
107 // Instructions where use operands are floating point registers.
108 // Def operands are general purpose.
109 static bool isFloatingPointOpcodeUse(unsigned Opc
) {
111 case TargetOpcode::G_FPTOSI
:
112 case TargetOpcode::G_FPTOUI
:
113 case TargetOpcode::G_FCMP
:
116 return isPreISelGenericFloatingPointOpcode(Opc
);
120 // Instructions where def operands are floating point registers.
121 // Use operands are general purpose.
122 static bool isFloatingPointOpcodeDef(unsigned Opc
) {
124 case TargetOpcode::G_SITOFP
:
125 case TargetOpcode::G_UITOFP
:
128 return isPreISelGenericFloatingPointOpcode(Opc
);
132 static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr
*MI
) {
133 if (MI
->getOpcode() == TargetOpcode::G_LOAD
||
134 MI
->getOpcode() == TargetOpcode::G_STORE
) {
135 auto MMO
= *MI
->memoperands_begin();
136 const MipsSubtarget
&STI
= MI
->getMF()->getSubtarget
<MipsSubtarget
>();
137 if (MMO
->getSize() == 4 && (!STI
.systemSupportsUnalignedAccess() &&
138 (!MMO
->getSize().hasValue() ||
139 MMO
->getAlign() < MMO
->getSize().getValue())))
145 static bool isAmbiguous(unsigned Opc
) {
147 case TargetOpcode::G_LOAD
:
148 case TargetOpcode::G_STORE
:
149 case TargetOpcode::G_PHI
:
150 case TargetOpcode::G_SELECT
:
151 case TargetOpcode::G_IMPLICIT_DEF
:
152 case TargetOpcode::G_UNMERGE_VALUES
:
153 case TargetOpcode::G_MERGE_VALUES
:
160 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
161 Register Reg
, const MachineRegisterInfo
&MRI
) {
162 assert(!MRI
.getType(Reg
).isPointer() &&
163 "Pointers are gprb, they should not be considered as ambiguous.\n");
164 for (MachineInstr
&UseMI
: MRI
.use_instructions(Reg
)) {
165 MachineInstr
*NonCopyInstr
= skipCopiesOutgoing(&UseMI
);
166 // Copy with many uses.
167 if (NonCopyInstr
->getOpcode() == TargetOpcode::COPY
&&
168 !NonCopyInstr
->getOperand(0).getReg().isPhysical())
169 addDefUses(NonCopyInstr
->getOperand(0).getReg(), MRI
);
171 DefUses
.push_back(skipCopiesOutgoing(&UseMI
));
175 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
176 Register Reg
, const MachineRegisterInfo
&MRI
) {
177 assert(!MRI
.getType(Reg
).isPointer() &&
178 "Pointers are gprb, they should not be considered as ambiguous.\n");
179 MachineInstr
*DefMI
= MRI
.getVRegDef(Reg
);
180 UseDefs
.push_back(skipCopiesIncoming(DefMI
));
184 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
185 MachineInstr
*MI
) const {
186 const MachineFunction
&MF
= *MI
->getParent()->getParent();
187 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
188 MachineInstr
*Ret
= MI
;
189 while (Ret
->getOpcode() == TargetOpcode::COPY
&&
190 !Ret
->getOperand(0).getReg().isPhysical() &&
191 MRI
.hasOneUse(Ret
->getOperand(0).getReg())) {
192 Ret
= &(*MRI
.use_instr_begin(Ret
->getOperand(0).getReg()));
198 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
199 MachineInstr
*MI
) const {
200 const MachineFunction
&MF
= *MI
->getParent()->getParent();
201 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
202 MachineInstr
*Ret
= MI
;
203 while (Ret
->getOpcode() == TargetOpcode::COPY
&&
204 !Ret
->getOperand(1).getReg().isPhysical())
205 Ret
= MRI
.getVRegDef(Ret
->getOperand(1).getReg());
209 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
210 const MachineInstr
*MI
) {
211 assert(isAmbiguous(MI
->getOpcode()) &&
212 "Not implemented for non Ambiguous opcode.\n");
214 const MachineRegisterInfo
&MRI
= MI
->getMF()->getRegInfo();
216 if (MI
->getOpcode() == TargetOpcode::G_LOAD
)
217 addDefUses(MI
->getOperand(0).getReg(), MRI
);
219 if (MI
->getOpcode() == TargetOpcode::G_STORE
)
220 addUseDef(MI
->getOperand(0).getReg(), MRI
);
222 if (auto *PHI
= dyn_cast
<GPhi
>(MI
)) {
223 addDefUses(PHI
->getReg(0), MRI
);
225 for (unsigned I
= 1; I
< PHI
->getNumIncomingValues(); ++I
)
226 addUseDef(PHI
->getIncomingValue(I
), MRI
);
229 if (MI
->getOpcode() == TargetOpcode::G_SELECT
) {
230 addDefUses(MI
->getOperand(0).getReg(), MRI
);
232 addUseDef(MI
->getOperand(2).getReg(), MRI
);
233 addUseDef(MI
->getOperand(3).getReg(), MRI
);
236 if (MI
->getOpcode() == TargetOpcode::G_IMPLICIT_DEF
)
237 addDefUses(MI
->getOperand(0).getReg(), MRI
);
239 if (MI
->getOpcode() == TargetOpcode::G_UNMERGE_VALUES
)
240 addUseDef(MI
->getOperand(MI
->getNumOperands() - 1).getReg(), MRI
);
242 if (MI
->getOpcode() == TargetOpcode::G_MERGE_VALUES
)
243 addDefUses(MI
->getOperand(0).getReg(), MRI
);
246 bool MipsRegisterBankInfo::TypeInfoForMF::visit(
247 const MachineInstr
*MI
, const MachineInstr
*WaitingForTypeOfMI
,
248 InstType
&AmbiguousTy
) {
249 assert(isAmbiguous(MI
->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
251 return true; // InstType has already been determined for MI.
254 AmbiguousRegDefUseContainer
DefUseContainer(MI
);
256 if (isGprbTwoInstrUnalignedLoadOrStore(MI
)) {
257 setTypes(MI
, Integer
);
261 if (AmbiguousTy
== InstType::Ambiguous
&&
262 (MI
->getOpcode() == TargetOpcode::G_MERGE_VALUES
||
263 MI
->getOpcode() == TargetOpcode::G_UNMERGE_VALUES
))
264 AmbiguousTy
= InstType::AmbiguousWithMergeOrUnmerge
;
266 // Visit instructions where MI's DEF operands are USED.
267 if (visitAdjacentInstrs(MI
, DefUseContainer
.getDefUses(), true, AmbiguousTy
))
270 // Visit instructions that DEFINE MI's USE operands.
271 if (visitAdjacentInstrs(MI
, DefUseContainer
.getUseDefs(), false, AmbiguousTy
))
274 // All MI's adjacent instructions, are ambiguous.
275 if (!WaitingForTypeOfMI
) {
276 // This is chain of ambiguous instructions.
277 setTypes(MI
, AmbiguousTy
);
280 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
281 // instructions or has no other adjacent instructions. Anyway InstType could
282 // not be determined. There could be unexplored path from some of
283 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
284 // mapping available.
285 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
286 // this way when WaitingForTypeOfMI figures out its InstType same InstType
287 // will be assigned to all instructions in this branch.
288 addToWaitingQueue(WaitingForTypeOfMI
, MI
);
292 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
293 const MachineInstr
*MI
, SmallVectorImpl
<MachineInstr
*> &AdjacentInstrs
,
294 bool isDefUse
, InstType
&AmbiguousTy
) {
295 while (!AdjacentInstrs
.empty()) {
296 MachineInstr
*AdjMI
= AdjacentInstrs
.pop_back_val();
298 if (isDefUse
? isFloatingPointOpcodeUse(AdjMI
->getOpcode())
299 : isFloatingPointOpcodeDef(AdjMI
->getOpcode())) {
300 setTypes(MI
, InstType::FloatingPoint
);
304 // Determine InstType from register bank of phys register that is
305 // 'isDefUse ? def : use' of this copy.
306 if (AdjMI
->getOpcode() == TargetOpcode::COPY
) {
307 setTypesAccordingToPhysicalRegister(MI
, AdjMI
, isDefUse
? 0 : 1);
311 // Defaults to integer instruction. Small registers in G_MERGE (uses) and
312 // G_UNMERGE (defs) will always be gprb.
313 if ((!isDefUse
&& AdjMI
->getOpcode() == TargetOpcode::G_UNMERGE_VALUES
) ||
314 (isDefUse
&& AdjMI
->getOpcode() == TargetOpcode::G_MERGE_VALUES
) ||
315 !isAmbiguous(AdjMI
->getOpcode())) {
316 setTypes(MI
, InstType::Integer
);
320 // When AdjMI was visited first, MI has to continue to explore remaining
321 // adjacent instructions and determine InstType without visiting AdjMI.
322 if (!wasVisited(AdjMI
) ||
323 getRecordedTypeForInstr(AdjMI
) != InstType::NotDetermined
) {
324 if (visit(AdjMI
, MI
, AmbiguousTy
)) {
325 // InstType is successfully determined and is same as for AdjMI.
326 setTypes(MI
, getRecordedTypeForInstr(AdjMI
));
334 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr
*MI
,
336 changeRecordedTypeForInstr(MI
, InstTy
);
337 for (const MachineInstr
*WaitingInstr
: getWaitingQueueFor(MI
)) {
338 setTypes(WaitingInstr
, InstTy
);
342 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
343 const MachineInstr
*MI
, const MachineInstr
*CopyInst
, unsigned Op
) {
344 assert((CopyInst
->getOperand(Op
).getReg().isPhysical()) &&
345 "Copies of non physical registers should not be considered here.\n");
347 const MachineFunction
&MF
= *CopyInst
->getMF();
348 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
349 const TargetRegisterInfo
&TRI
= *MF
.getSubtarget().getRegisterInfo();
350 const RegisterBankInfo
&RBI
=
351 *CopyInst
->getMF()->getSubtarget().getRegBankInfo();
352 const RegisterBank
*Bank
=
353 RBI
.getRegBank(CopyInst
->getOperand(Op
).getReg(), MRI
, TRI
);
355 if (Bank
== &Mips::FPRBRegBank
)
356 setTypes(MI
, InstType::FloatingPoint
);
357 else if (Bank
== &Mips::GPRBRegBank
)
358 setTypes(MI
, InstType::Integer
);
360 llvm_unreachable("Unsupported register bank.\n");
363 MipsRegisterBankInfo::InstType
364 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr
*MI
) {
365 InstType DefaultAmbiguousType
= InstType::Ambiguous
;
366 visit(MI
, nullptr, DefaultAmbiguousType
);
367 return getRecordedTypeForInstr(MI
);
370 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
371 llvm::StringRef FunctionName
) {
372 if (MFName
!= FunctionName
) {
373 MFName
= std::string(FunctionName
);
374 WaitingQueues
.clear();
379 static const MipsRegisterBankInfo::ValueMapping
*
380 getMSAMapping(const MachineFunction
&MF
) {
381 assert(MF
.getSubtarget
<MipsSubtarget
>().hasMSA() &&
382 "MSA mapping not available on target without MSA.");
383 return &Mips::ValueMappings
[Mips::MSAIdx
];
386 static const MipsRegisterBankInfo::ValueMapping
*getFprbMapping(unsigned Size
) {
387 return Size
== 32 ? &Mips::ValueMappings
[Mips::SPRIdx
]
388 : &Mips::ValueMappings
[Mips::DPRIdx
];
391 static const unsigned CustomMappingID
= 1;
393 // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
394 // will be split into two 32 bit registers in gprb.
395 static const MipsRegisterBankInfo::ValueMapping
*
396 getGprbOrCustomMapping(unsigned Size
, unsigned &MappingID
) {
398 return &Mips::ValueMappings
[Mips::GPRIdx
];
400 MappingID
= CustomMappingID
;
401 return &Mips::ValueMappings
[Mips::DPRIdx
];
404 const RegisterBankInfo::InstructionMapping
&
405 MipsRegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
407 static TypeInfoForMF TI
;
409 // Reset TI internal data when MF changes.
410 TI
.cleanupIfNewFunction(MI
.getMF()->getName());
412 unsigned Opc
= MI
.getOpcode();
413 const MachineFunction
&MF
= *MI
.getParent()->getParent();
414 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
416 if (MI
.getOpcode() != TargetOpcode::G_PHI
) {
417 const RegisterBankInfo::InstructionMapping
&Mapping
=
418 getInstrMappingImpl(MI
);
419 if (Mapping
.isValid())
423 using namespace TargetOpcode
;
425 unsigned NumOperands
= MI
.getNumOperands();
426 const ValueMapping
*OperandsMapping
= &Mips::ValueMappings
[Mips::GPRIdx
];
427 unsigned MappingID
= DefaultMappingID
;
429 // Check if LLT sizes match sizes of available register banks.
430 for (const MachineOperand
&Op
: MI
.operands()) {
432 LLT RegTy
= MRI
.getType(Op
.getReg());
434 if (RegTy
.isScalar() &&
435 (RegTy
.getSizeInBits() != 32 && RegTy
.getSizeInBits() != 64))
436 return getInvalidInstructionMapping();
438 if (RegTy
.isVector() && RegTy
.getSizeInBits() != 128)
439 return getInvalidInstructionMapping();
443 const LLT Op0Ty
= MRI
.getType(MI
.getOperand(0).getReg());
444 unsigned Op0Size
= Op0Ty
.getSizeInBits();
445 InstType InstTy
= InstType::Integer
;
465 OperandsMapping
= &Mips::ValueMappings
[Mips::GPRIdx
];
474 OperandsMapping
= &Mips::ValueMappings
[Mips::GPRIdx
];
476 OperandsMapping
= getMSAMapping(MF
);
480 if (Op0Size
== 128) {
481 OperandsMapping
= getOperandsMapping(
482 {getMSAMapping(MF
), &Mips::ValueMappings
[Mips::GPRIdx
]});
486 if (!Op0Ty
.isPointer())
487 InstTy
= TI
.determineInstType(&MI
);
489 if (isFloatingPoint_32or64(InstTy
, Op0Size
) ||
490 isAmbiguous_64(InstTy
, Op0Size
)) {
491 OperandsMapping
= getOperandsMapping(
492 {getFprbMapping(Op0Size
), &Mips::ValueMappings
[Mips::GPRIdx
]});
494 assert((isInteger_32(InstTy
, Op0Size
) ||
495 isAmbiguous_32(InstTy
, Op0Size
) ||
496 isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
)) &&
497 "Unexpected Inst type");
499 getOperandsMapping({getGprbOrCustomMapping(Op0Size
, MappingID
),
500 &Mips::ValueMappings
[Mips::GPRIdx
]});
506 if (!Op0Ty
.isPointer())
507 InstTy
= TI
.determineInstType(&MI
);
509 // PHI is copylike and should have one regbank in mapping for def register.
510 if (isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
)) {
512 getOperandsMapping({&Mips::ValueMappings
[Mips::DPRIdx
]});
513 TI
.clearTypeInfoData(&MI
);
514 return getInstructionMapping(CustomMappingID
, /*Cost=*/1, OperandsMapping
,
517 assert((isInteger_32(InstTy
, Op0Size
) ||
518 isFloatingPoint_32or64(InstTy
, Op0Size
) ||
519 isAmbiguous_32or64(InstTy
, Op0Size
)) &&
520 "Unexpected Inst type");
521 // Use default handling for PHI, i.e. set reg bank of def operand to match
522 // register banks of use operands.
523 return getInstrMappingImpl(MI
);
526 if (!Op0Ty
.isPointer())
527 InstTy
= TI
.determineInstType(&MI
);
528 if (isFloatingPoint_32or64(InstTy
, Op0Size
) ||
529 isAmbiguous_64(InstTy
, Op0Size
)) {
530 const RegisterBankInfo::ValueMapping
*Bank
= getFprbMapping(Op0Size
);
531 OperandsMapping
= getOperandsMapping(
532 {Bank
, &Mips::ValueMappings
[Mips::GPRIdx
], Bank
, Bank
});
535 assert((isInteger_32(InstTy
, Op0Size
) ||
536 isAmbiguous_32(InstTy
, Op0Size
) ||
537 isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
)) &&
538 "Unexpected Inst type");
539 const RegisterBankInfo::ValueMapping
*Bank
=
540 getGprbOrCustomMapping(Op0Size
, MappingID
);
541 OperandsMapping
= getOperandsMapping(
542 {Bank
, &Mips::ValueMappings
[Mips::GPRIdx
], Bank
, Bank
});
546 case G_IMPLICIT_DEF
: {
547 if (!Op0Ty
.isPointer())
548 InstTy
= TI
.determineInstType(&MI
);
550 if (isFloatingPoint_32or64(InstTy
, Op0Size
))
551 OperandsMapping
= getFprbMapping(Op0Size
);
553 assert((isInteger_32(InstTy
, Op0Size
) ||
554 isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
)) &&
555 "Unexpected Inst type");
556 OperandsMapping
= getGprbOrCustomMapping(Op0Size
, MappingID
);
559 case G_UNMERGE_VALUES
: {
560 assert(MI
.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
561 unsigned Op3Size
= MRI
.getType(MI
.getOperand(2).getReg()).getSizeInBits();
562 InstTy
= TI
.determineInstType(&MI
);
563 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op3Size
) ||
564 isFloatingPoint_64(InstTy
, Op3Size
)) &&
565 "Unexpected Inst type");
566 OperandsMapping
= getOperandsMapping({&Mips::ValueMappings
[Mips::GPRIdx
],
567 &Mips::ValueMappings
[Mips::GPRIdx
],
568 &Mips::ValueMappings
[Mips::DPRIdx
]});
569 if (isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op3Size
))
570 MappingID
= CustomMappingID
;
573 case G_MERGE_VALUES
: {
574 InstTy
= TI
.determineInstType(&MI
);
575 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
) ||
576 isFloatingPoint_64(InstTy
, Op0Size
)) &&
577 "Unexpected Inst type");
578 OperandsMapping
= getOperandsMapping({&Mips::ValueMappings
[Mips::DPRIdx
],
579 &Mips::ValueMappings
[Mips::GPRIdx
],
580 &Mips::ValueMappings
[Mips::GPRIdx
]});
581 if (isAmbiguousWithMergeOrUnmerge_64(InstTy
, Op0Size
))
582 MappingID
= CustomMappingID
;
591 OperandsMapping
= getFprbMapping(Op0Size
);
593 OperandsMapping
= getMSAMapping(MF
);
596 OperandsMapping
= getOperandsMapping({getFprbMapping(Op0Size
), nullptr});
599 unsigned Op2Size
= MRI
.getType(MI
.getOperand(2).getReg()).getSizeInBits();
601 getOperandsMapping({&Mips::ValueMappings
[Mips::GPRIdx
], nullptr,
602 getFprbMapping(Op2Size
), getFprbMapping(Op2Size
)});
606 OperandsMapping
= getOperandsMapping({&Mips::ValueMappings
[Mips::DPRIdx
],
607 &Mips::ValueMappings
[Mips::SPRIdx
]});
610 OperandsMapping
= getOperandsMapping({&Mips::ValueMappings
[Mips::SPRIdx
],
611 &Mips::ValueMappings
[Mips::DPRIdx
]});
614 assert((Op0Size
== 32) && "Unsupported integer size");
615 unsigned SizeFP
= MRI
.getType(MI
.getOperand(1).getReg()).getSizeInBits();
616 OperandsMapping
= getOperandsMapping(
617 {&Mips::ValueMappings
[Mips::GPRIdx
], getFprbMapping(SizeFP
)});
621 assert((MRI
.getType(MI
.getOperand(1).getReg()).getSizeInBits() == 32) &&
622 "Unsupported integer size");
623 OperandsMapping
= getOperandsMapping(
624 {getFprbMapping(Op0Size
), &Mips::ValueMappings
[Mips::GPRIdx
]});
632 getOperandsMapping({&Mips::ValueMappings
[Mips::GPRIdx
], nullptr});
636 getOperandsMapping({&Mips::ValueMappings
[Mips::GPRIdx
], nullptr,
637 &Mips::ValueMappings
[Mips::GPRIdx
]});
641 getOperandsMapping({&Mips::ValueMappings
[Mips::GPRIdx
], nullptr,
642 &Mips::ValueMappings
[Mips::GPRIdx
],
643 &Mips::ValueMappings
[Mips::GPRIdx
]});
646 return getInvalidInstructionMapping();
649 if (MappingID
== CustomMappingID
)
650 TI
.clearTypeInfoData(&MI
);
651 return getInstructionMapping(MappingID
, /*Cost=*/1, OperandsMapping
,
655 using InstListTy
= GISelWorkList
<4>;
657 class InstManager
: public GISelChangeObserver
{
658 InstListTy
&InstList
;
662 InstManager(MachineIRBuilder
&B
, InstListTy
&Insts
) : InstList(Insts
), B(B
) {
663 assert(!B
.isObservingChanges());
664 B
.setChangeObserver(*this);
667 ~InstManager() { B
.stopObservingChanges(); }
669 void createdInstr(MachineInstr
&MI
) override
{ InstList
.insert(&MI
); }
670 void erasingInstr(MachineInstr
&MI
) override
{}
671 void changingInstr(MachineInstr
&MI
) override
{}
672 void changedInstr(MachineInstr
&MI
) override
{}
674 } // end anonymous namespace
676 void MipsRegisterBankInfo::setRegBank(MachineInstr
&MI
,
677 MachineRegisterInfo
&MRI
) const {
678 Register Dest
= MI
.getOperand(0).getReg();
679 switch (MI
.getOpcode()) {
680 case TargetOpcode::G_STORE
:
681 // No def operands, skip this instruction.
683 case TargetOpcode::G_CONSTANT
:
684 case TargetOpcode::G_LOAD
:
685 case TargetOpcode::G_SELECT
:
686 case TargetOpcode::G_PHI
:
687 case TargetOpcode::G_IMPLICIT_DEF
: {
688 assert(MRI
.getType(Dest
) == LLT::scalar(32) && "Unexpected operand type.");
689 MRI
.setRegBank(Dest
, getRegBank(Mips::GPRBRegBankID
));
692 case TargetOpcode::G_PTR_ADD
: {
693 assert(MRI
.getType(Dest
).isPointer() && "Unexpected operand type.");
694 MRI
.setRegBank(Dest
, getRegBank(Mips::GPRBRegBankID
));
698 llvm_unreachable("Unexpected opcode.");
703 combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner
&ArtCombiner
,
704 GUnmerge
&MI
, GISelChangeObserver
&Observer
) {
705 SmallVector
<Register
, 4> UpdatedDefs
;
706 SmallVector
<MachineInstr
*, 2> DeadInstrs
;
707 ArtCombiner
.tryCombineUnmergeValues(MI
, DeadInstrs
,
708 UpdatedDefs
, Observer
);
709 for (MachineInstr
*DeadMI
: DeadInstrs
)
710 DeadMI
->eraseFromParent();
713 void MipsRegisterBankInfo::applyMappingImpl(
714 MachineIRBuilder
&Builder
, const OperandsMapper
&OpdMapper
) const {
715 MachineInstr
&MI
= OpdMapper
.getMI();
716 Builder
.setInstrAndDebugLoc(MI
);
718 InstListTy NewInstrs
;
719 MachineFunction
*MF
= MI
.getMF();
720 MachineRegisterInfo
&MRI
= OpdMapper
.getMRI();
721 const LegalizerInfo
&LegInfo
= *MF
->getSubtarget().getLegalizerInfo();
723 InstManager
NewInstrObserver(Builder
, NewInstrs
);
724 LegalizerHelper
Helper(*MF
, NewInstrObserver
, Builder
);
725 LegalizationArtifactCombiner
ArtCombiner(Builder
, MF
->getRegInfo(), LegInfo
);
727 switch (MI
.getOpcode()) {
728 case TargetOpcode::G_LOAD
:
729 case TargetOpcode::G_STORE
:
730 case TargetOpcode::G_PHI
:
731 case TargetOpcode::G_SELECT
:
732 case TargetOpcode::G_IMPLICIT_DEF
: {
733 Helper
.narrowScalar(MI
, 0, LLT::scalar(32));
734 // Handle new instructions.
735 while (!NewInstrs
.empty()) {
736 MachineInstr
*NewMI
= NewInstrs
.pop_back_val();
737 // This is new G_UNMERGE that was created during narrowScalar and will
738 // not be considered for regbank selection. RegBankSelect for mips
739 // visits/makes corresponding G_MERGE first. Combine them here.
740 if (auto *Unmerge
= dyn_cast
<GUnmerge
>(NewMI
))
741 combineAwayG_UNMERGE_VALUES(ArtCombiner
, *Unmerge
, NewInstrObserver
);
742 // This G_MERGE will be combined away when its corresponding G_UNMERGE
743 // gets regBankSelected.
744 else if (NewMI
->getOpcode() == TargetOpcode::G_MERGE_VALUES
)
747 // Manually set register banks for def operands to 32 bit gprb.
748 setRegBank(*NewMI
, MRI
);
752 case TargetOpcode::G_UNMERGE_VALUES
:
753 combineAwayG_UNMERGE_VALUES(ArtCombiner
, cast
<GUnmerge
>(MI
),
760 return applyDefaultMapping(OpdMapper
);