[MIPS GlobalISel] Register bank select for G_STORE. Select i64 store
[llvm-complete.git] / lib / Target / Mips / MipsRegisterBankInfo.cpp
blobcd8937d40658f25db6511a0202af4824352c36d9
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 //===----------------------------------------------------------------------===//
13 #include "MipsRegisterBankInfo.h"
14 #include "MipsInstrInfo.h"
15 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
16 #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #define GET_TARGET_REGBANK_IMPL
22 #include "MipsGenRegisterBank.inc"
24 namespace llvm {
25 namespace Mips {
26 enum PartialMappingIdx {
27 PMI_GPR,
28 PMI_SPR,
29 PMI_DPR,
30 PMI_Min = PMI_GPR,
33 RegisterBankInfo::PartialMapping PartMappings[]{
34 {0, 32, GPRBRegBank},
35 {0, 32, FPRBRegBank},
36 {0, 64, FPRBRegBank}
39 enum ValueMappingIdx {
40 InvalidIdx = 0,
41 GPRIdx = 1,
42 SPRIdx = 4,
43 DPRIdx = 7
46 RegisterBankInfo::ValueMapping ValueMappings[] = {
47 // invalid
48 {nullptr, 0},
49 // up to 3 operands in GPRs
50 {&PartMappings[PMI_GPR - PMI_Min], 1},
51 {&PartMappings[PMI_GPR - PMI_Min], 1},
52 {&PartMappings[PMI_GPR - PMI_Min], 1},
53 // up to 3 ops operands FPRs - single precission
54 {&PartMappings[PMI_SPR - PMI_Min], 1},
55 {&PartMappings[PMI_SPR - PMI_Min], 1},
56 {&PartMappings[PMI_SPR - PMI_Min], 1},
57 // up to 3 ops operands FPRs - double precission
58 {&PartMappings[PMI_DPR - PMI_Min], 1},
59 {&PartMappings[PMI_DPR - PMI_Min], 1},
60 {&PartMappings[PMI_DPR - PMI_Min], 1}
63 } // end namespace Mips
64 } // end namespace llvm
66 using namespace llvm;
68 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI)
69 : MipsGenRegisterBankInfo() {}
71 const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass(
72 const TargetRegisterClass &RC) const {
73 using namespace Mips;
75 switch (RC.getID()) {
76 case Mips::GPR32RegClassID:
77 case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
78 case Mips::GPRMM16MovePPairFirstRegClassID:
79 case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
80 case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
81 case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
82 case Mips::SP32RegClassID:
83 case Mips::GP32RegClassID:
84 return getRegBank(Mips::GPRBRegBankID);
85 case Mips::FGRCCRegClassID:
86 case Mips::FGR32RegClassID:
87 case Mips::FGR64RegClassID:
88 case Mips::AFGR64RegClassID:
89 return getRegBank(Mips::FPRBRegBankID);
90 default:
91 llvm_unreachable("Register class not supported");
95 // Instructions where all register operands are floating point.
96 static bool isFloatingPointOpcode(unsigned Opc) {
97 switch (Opc) {
98 case TargetOpcode::G_FCONSTANT:
99 case TargetOpcode::G_FADD:
100 case TargetOpcode::G_FSUB:
101 case TargetOpcode::G_FMUL:
102 case TargetOpcode::G_FDIV:
103 case TargetOpcode::G_FABS:
104 case TargetOpcode::G_FSQRT:
105 case TargetOpcode::G_FCEIL:
106 case TargetOpcode::G_FFLOOR:
107 case TargetOpcode::G_FPEXT:
108 case TargetOpcode::G_FPTRUNC:
109 return true;
110 default:
111 return false;
115 // Instructions where def operands are floating point registers.
116 // Use operands are general purpose.
117 static bool isFloatingPointOpcodeDef(unsigned Opc) {
118 switch (Opc) {
119 case TargetOpcode::G_SITOFP:
120 case TargetOpcode::G_UITOFP:
121 case Mips::MTC1:
122 case Mips::BuildPairF64:
123 case Mips::BuildPairF64_64:
124 return true;
125 default:
126 return isFloatingPointOpcode(Opc);
130 static bool isAmbiguous(unsigned Opc) {
131 switch (Opc) {
132 case TargetOpcode::G_LOAD:
133 case TargetOpcode::G_STORE:
134 case TargetOpcode::G_PHI:
135 case TargetOpcode::G_SELECT:
136 return true;
137 default:
138 return false;
142 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
143 Register Reg, const MachineRegisterInfo &MRI) {
144 assert(!MRI.getType(Reg).isPointer() &&
145 "Pointers are gprb, they should not be considered as ambiguous.\n");
146 MachineInstr *DefMI = MRI.getVRegDef(Reg);
147 if (DefMI->getOpcode() == TargetOpcode::COPY &&
148 !TargetRegisterInfo::isPhysicalRegister(DefMI->getOperand(1).getReg()))
149 // Copies from non-physical registers are not supported.
150 return;
152 UseDefs.push_back(DefMI);
155 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
156 const MachineInstr *MI) {
157 assert(isAmbiguous(MI->getOpcode()) &&
158 "Not implemented for non Ambiguous opcode.\n");
160 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
162 if (MI->getOpcode() == TargetOpcode::G_STORE)
163 addUseDef(MI->getOperand(0).getReg(), MRI);
166 bool MipsRegisterBankInfo::TypeInfoForMF::visit(const MachineInstr *MI) {
167 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
169 startVisit(MI);
170 AmbiguousRegDefUseContainer DefUseContainer(MI);
172 // Visit instructions that DEFINE MI's USE operands.
173 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs()))
174 return true;
176 return false;
179 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
180 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs) {
181 while (!AdjacentInstrs.empty()) {
182 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
184 if (isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
185 setTypes(MI, InstType::FloatingPoint);
186 return true;
189 // Determine InstType from register bank of phys register that is
190 // use of this copy.
191 if (AdjMI->getOpcode() == TargetOpcode::COPY) {
192 setTypesAccordingToPhysicalRegister(MI, AdjMI, 1);
193 return true;
196 if (isAmbiguous(AdjMI->getOpcode())) {
197 // Chains of ambiguous instructions are not supported.
198 return false;
201 // Defaults to integer instruction. Includes G_MERGE_VALUES and
202 // G_UNMERGE_VALUES.
203 setTypes(MI, InstType::Integer);
204 return true;
206 return false;
209 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
210 InstType InstTy) {
211 changeRecordedTypeForInstr(MI, InstTy);
214 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
215 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
216 assert((TargetRegisterInfo::isPhysicalRegister(
217 CopyInst->getOperand(Op).getReg())) &&
218 "Copies of non physical registers should not be considered here.\n");
220 const MachineFunction &MF = *CopyInst->getMF();
221 const MachineRegisterInfo &MRI = MF.getRegInfo();
222 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
223 const RegisterBankInfo &RBI =
224 *CopyInst->getMF()->getSubtarget().getRegBankInfo();
225 const RegisterBank *Bank =
226 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
228 if (Bank == &Mips::FPRBRegBank)
229 setTypes(MI, InstType::FloatingPoint);
230 else if (Bank == &Mips::GPRBRegBank)
231 setTypes(MI, InstType::Integer);
232 else
233 llvm_unreachable("Unsupported register bank.\n");
236 MipsRegisterBankInfo::InstType
237 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
238 visit(MI);
239 return getRecordedTypeForInstr(MI);
242 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
243 llvm::StringRef FunctionName) {
244 if (MFName != FunctionName) {
245 MFName = FunctionName;
246 Types.clear();
250 const RegisterBankInfo::InstructionMapping &
251 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
253 static TypeInfoForMF TI;
255 // Reset TI internal data when MF changes.
256 TI.cleanupIfNewFunction(MI.getMF()->getName());
258 unsigned Opc = MI.getOpcode();
259 const MachineFunction &MF = *MI.getParent()->getParent();
260 const MachineRegisterInfo &MRI = MF.getRegInfo();
262 const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI);
263 if (Mapping.isValid())
264 return Mapping;
266 using namespace TargetOpcode;
268 unsigned NumOperands = MI.getNumOperands();
269 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
270 unsigned MappingID = DefaultMappingID;
271 const unsigned CustomMappingID = 1;
273 switch (Opc) {
274 case G_TRUNC:
275 case G_ADD:
276 case G_SUB:
277 case G_MUL:
278 case G_UMULH:
279 case G_LOAD:
280 case G_ZEXTLOAD:
281 case G_SEXTLOAD:
282 case G_GEP:
283 case G_AND:
284 case G_OR:
285 case G_XOR:
286 case G_SHL:
287 case G_ASHR:
288 case G_LSHR:
289 case G_SDIV:
290 case G_UDIV:
291 case G_SREM:
292 case G_UREM:
293 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
294 break;
295 case G_STORE: {
296 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
297 InstType InstTy = InstType::Integer;
298 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
299 InstTy = TI.determineInstType(&MI);
302 if (InstTy == InstType::FloatingPoint) { // fprb
303 OperandsMapping =
304 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
305 : &Mips::ValueMappings[Mips::DPRIdx],
306 &Mips::ValueMappings[Mips::GPRIdx]});
307 break;
308 } else { // gprb
309 OperandsMapping =
310 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
311 : &Mips::ValueMappings[Mips::DPRIdx],
312 &Mips::ValueMappings[Mips::GPRIdx]});
313 if (Size == 64)
314 MappingID = CustomMappingID;
316 break;
318 case G_MERGE_VALUES: {
319 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
320 &Mips::ValueMappings[Mips::GPRIdx],
321 &Mips::ValueMappings[Mips::GPRIdx]});
322 MappingID = CustomMappingID;
323 break;
325 case G_FADD:
326 case G_FSUB:
327 case G_FMUL:
328 case G_FDIV:
329 case G_FABS:
330 case G_FSQRT:{
331 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
332 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
333 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
334 : &Mips::ValueMappings[Mips::DPRIdx];
335 break;
337 case G_FCONSTANT: {
338 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
339 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
340 const RegisterBankInfo::ValueMapping *FPRValueMapping =
341 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
342 : &Mips::ValueMappings[Mips::DPRIdx];
343 OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr});
344 break;
346 case G_FCMP: {
347 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
348 assert((Size == 32 || Size == 64) && "Unsupported floating point size");
349 const RegisterBankInfo::ValueMapping *FPRValueMapping =
350 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
351 : &Mips::ValueMappings[Mips::DPRIdx];
352 OperandsMapping =
353 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
354 FPRValueMapping, FPRValueMapping});
355 break;
357 case G_FPEXT:
358 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
359 &Mips::ValueMappings[Mips::SPRIdx]});
360 break;
361 case G_FPTRUNC:
362 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
363 &Mips::ValueMappings[Mips::DPRIdx]});
364 break;
365 case G_FPTOSI: {
366 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
367 assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) &&
368 "Unsupported integer size");
369 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
370 OperandsMapping = getOperandsMapping({
371 &Mips::ValueMappings[Mips::GPRIdx],
372 SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
373 : &Mips::ValueMappings[Mips::DPRIdx],
375 break;
377 case G_SITOFP: {
378 unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
379 unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
380 (void)SizeInt;
381 assert((SizeInt == 32) && "Unsupported integer size");
382 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size");
383 OperandsMapping =
384 getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
385 : &Mips::ValueMappings[Mips::DPRIdx],
386 &Mips::ValueMappings[Mips::GPRIdx]});
387 break;
389 case G_CONSTANT:
390 case G_FRAME_INDEX:
391 case G_GLOBAL_VALUE:
392 case G_BRCOND:
393 OperandsMapping =
394 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
395 break;
396 case G_ICMP:
397 OperandsMapping =
398 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
399 &Mips::ValueMappings[Mips::GPRIdx],
400 &Mips::ValueMappings[Mips::GPRIdx]});
401 break;
402 case G_SELECT:
403 OperandsMapping =
404 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
405 &Mips::ValueMappings[Mips::GPRIdx],
406 &Mips::ValueMappings[Mips::GPRIdx],
407 &Mips::ValueMappings[Mips::GPRIdx]});
408 break;
409 default:
410 return getInvalidInstructionMapping();
413 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
414 NumOperands);
417 using InstListTy = GISelWorkList<4>;
418 namespace {
419 class InstManager : public GISelChangeObserver {
420 InstListTy &InstList;
422 public:
423 InstManager(InstListTy &Insts) : InstList(Insts) {}
425 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
426 void erasingInstr(MachineInstr &MI) override {}
427 void changingInstr(MachineInstr &MI) override {}
428 void changedInstr(MachineInstr &MI) override {}
430 } // end anonymous namespace
432 /// Here we have to narrowScalar s64 operands to s32, combine away
433 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
434 /// We manually assign 32 bit gprb to register operands of all new instructions
435 /// that got created in the process since they will not end up in RegBankSelect
436 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
437 void MipsRegisterBankInfo::applyMappingImpl(
438 const OperandsMapper &OpdMapper) const {
439 MachineInstr &MI = OpdMapper.getMI();
440 InstListTy NewInstrs;
441 MachineIRBuilder B(MI);
442 MachineFunction *MF = MI.getMF();
443 MachineRegisterInfo &MRI = OpdMapper.getMRI();
445 InstManager NewInstrObserver(NewInstrs);
446 GISelObserverWrapper WrapperObserver(&NewInstrObserver);
447 LegalizerHelper Helper(*MF, WrapperObserver, B);
448 LegalizationArtifactCombiner ArtCombiner(
449 B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
451 switch (MI.getOpcode()) {
452 case TargetOpcode::G_STORE: {
453 Helper.narrowScalar(MI, 0, LLT::scalar(32));
454 // Handle new instructions.
455 while (!NewInstrs.empty()) {
456 MachineInstr *NewMI = NewInstrs.pop_back_val();
457 // This is new G_UNMERGE that was created during narrowScalar and will
458 // not be considered for regbank selection. RegBankSelect for mips
459 // visits/makes corresponding G_MERGE first. Combine them here.
460 if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
461 SmallVector<MachineInstr *, 2> DeadInstrs;
462 ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
463 for (MachineInstr *DeadMI : DeadInstrs)
464 DeadMI->eraseFromParent();
465 } else
466 // Manually set register banks for all register operands to 32 bit gprb.
467 for (auto Op : NewMI->operands()) {
468 if (Op.isReg()) {
469 assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
470 "Only 32 bit gprb is handled here.\n");
471 MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
475 return;
477 default:
478 break;
481 return applyDefaultMapping(OpdMapper);