1fac93e28SPetar Jovanovic //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
2fac93e28SPetar Jovanovic //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fac93e28SPetar Jovanovic //
7fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
8fac93e28SPetar Jovanovic /// \file
9fac93e28SPetar Jovanovic /// This file implements the targeting of the RegisterBankInfo class for Mips.
10fac93e28SPetar Jovanovic /// \todo This should be generated by TableGen.
11fac93e28SPetar Jovanovic //===----------------------------------------------------------------------===//
12fac93e28SPetar Jovanovic
13fac93e28SPetar Jovanovic #include "MipsRegisterBankInfo.h"
14ec575f6eSPetar Avramovic #include "MipsInstrInfo.h"
15599591f3SPetar Avramovic #include "MipsTargetMachine.h"
16ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
17ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
18ec575f6eSPetar Avramovic #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
19fac93e28SPetar Jovanovic #include "llvm/CodeGen/MachineRegisterInfo.h"
20fac93e28SPetar Jovanovic
21366857a2SPetar Jovanovic #define GET_TARGET_REGBANK_IMPL
22fac93e28SPetar Jovanovic
23366857a2SPetar Jovanovic #include "MipsGenRegisterBank.inc"
24366857a2SPetar Jovanovic
25366857a2SPetar Jovanovic namespace llvm {
26366857a2SPetar Jovanovic namespace Mips {
27366857a2SPetar Jovanovic enum PartialMappingIdx {
28366857a2SPetar Jovanovic PMI_GPR,
291af05df3SPetar Avramovic PMI_SPR,
301af05df3SPetar Avramovic PMI_DPR,
31599591f3SPetar Avramovic PMI_MSA,
32366857a2SPetar Jovanovic PMI_Min = PMI_GPR,
33366857a2SPetar Jovanovic };
34366857a2SPetar Jovanovic
35366857a2SPetar Jovanovic RegisterBankInfo::PartialMapping PartMappings[]{
361af05df3SPetar Avramovic {0, 32, GPRBRegBank},
371af05df3SPetar Avramovic {0, 32, FPRBRegBank},
38599591f3SPetar Avramovic {0, 64, FPRBRegBank},
39599591f3SPetar Avramovic {0, 128, FPRBRegBank}
40366857a2SPetar Jovanovic };
41366857a2SPetar Jovanovic
421af05df3SPetar Avramovic enum ValueMappingIdx {
431af05df3SPetar Avramovic InvalidIdx = 0,
441af05df3SPetar Avramovic GPRIdx = 1,
451af05df3SPetar Avramovic SPRIdx = 4,
46599591f3SPetar Avramovic DPRIdx = 7,
47599591f3SPetar Avramovic MSAIdx = 10
481af05df3SPetar Avramovic };
49366857a2SPetar Jovanovic
50366857a2SPetar Jovanovic RegisterBankInfo::ValueMapping ValueMappings[] = {
51366857a2SPetar Jovanovic // invalid
52366857a2SPetar Jovanovic {nullptr, 0},
531af05df3SPetar Avramovic // up to 3 operands in GPRs
54366857a2SPetar Jovanovic {&PartMappings[PMI_GPR - PMI_Min], 1},
55366857a2SPetar Jovanovic {&PartMappings[PMI_GPR - PMI_Min], 1},
561af05df3SPetar Avramovic {&PartMappings[PMI_GPR - PMI_Min], 1},
57f7c213c9SPetar Avramovic // up to 3 operands in FPRs - single precission
581af05df3SPetar Avramovic {&PartMappings[PMI_SPR - PMI_Min], 1},
591af05df3SPetar Avramovic {&PartMappings[PMI_SPR - PMI_Min], 1},
601af05df3SPetar Avramovic {&PartMappings[PMI_SPR - PMI_Min], 1},
61f7c213c9SPetar Avramovic // up to 3 operands in FPRs - double precission
621af05df3SPetar Avramovic {&PartMappings[PMI_DPR - PMI_Min], 1},
631af05df3SPetar Avramovic {&PartMappings[PMI_DPR - PMI_Min], 1},
64599591f3SPetar Avramovic {&PartMappings[PMI_DPR - PMI_Min], 1},
65599591f3SPetar Avramovic // up to 3 operands in FPRs - MSA
66599591f3SPetar Avramovic {&PartMappings[PMI_MSA - PMI_Min], 1},
67599591f3SPetar Avramovic {&PartMappings[PMI_MSA - PMI_Min], 1},
68599591f3SPetar Avramovic {&PartMappings[PMI_MSA - PMI_Min], 1}
691af05df3SPetar Avramovic };
70366857a2SPetar Jovanovic
71366857a2SPetar Jovanovic } // end namespace Mips
72366857a2SPetar Jovanovic } // end namespace llvm
73366857a2SPetar Jovanovic
74366857a2SPetar Jovanovic using namespace llvm;
75fac93e28SPetar Jovanovic
MipsRegisterBankInfo(const TargetRegisterInfo & TRI)7662128719SKazu Hirata MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {}
77366857a2SPetar Jovanovic
7821309eafSMatt Arsenault const RegisterBank &
getRegBankFromRegClass(const TargetRegisterClass & RC,LLT) const7921309eafSMatt Arsenault MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
8021309eafSMatt Arsenault LLT) const {
81366857a2SPetar Jovanovic using namespace Mips;
82366857a2SPetar Jovanovic
83366857a2SPetar Jovanovic switch (RC.getID()) {
84366857a2SPetar Jovanovic case Mips::GPR32RegClassID:
85366857a2SPetar Jovanovic case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
86852dd83bSSimon Atanasyan case Mips::GPRMM16MovePPairFirstRegClassID:
87852dd83bSSimon Atanasyan case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
88366857a2SPetar Jovanovic case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
89852dd83bSSimon Atanasyan case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
90021e4c82SPetar Jovanovic case Mips::SP32RegClassID:
91efcd3c00SPetar Avramovic case Mips::GP32RegClassID:
92366857a2SPetar Jovanovic return getRegBank(Mips::GPRBRegBankID);
933dfa368dSPetar Avramovic case Mips::FGRCCRegClassID:
94afa3afa3SPetar Avramovic case Mips::FGR32RegClassID:
953dfa368dSPetar Avramovic case Mips::FGR64RegClassID:
963dfa368dSPetar Avramovic case Mips::AFGR64RegClassID:
97599591f3SPetar Avramovic case Mips::MSA128BRegClassID:
98599591f3SPetar Avramovic case Mips::MSA128HRegClassID:
99599591f3SPetar Avramovic case Mips::MSA128WRegClassID:
100599591f3SPetar Avramovic case Mips::MSA128DRegClassID:
1013dfa368dSPetar Avramovic return getRegBank(Mips::FPRBRegBankID);
102366857a2SPetar Jovanovic default:
103366857a2SPetar Jovanovic llvm_unreachable("Register class not supported");
104366857a2SPetar Jovanovic }
105366857a2SPetar Jovanovic }
106366857a2SPetar Jovanovic
107ec575f6eSPetar Avramovic // Instructions where all register operands are floating point.
isFloatingPointOpcode(unsigned Opc)108ec575f6eSPetar Avramovic static bool isFloatingPointOpcode(unsigned Opc) {
109ec575f6eSPetar Avramovic switch (Opc) {
110ec575f6eSPetar Avramovic case TargetOpcode::G_FCONSTANT:
111ec575f6eSPetar Avramovic case TargetOpcode::G_FADD:
112ec575f6eSPetar Avramovic case TargetOpcode::G_FSUB:
113ec575f6eSPetar Avramovic case TargetOpcode::G_FMUL:
114ec575f6eSPetar Avramovic case TargetOpcode::G_FDIV:
115ec575f6eSPetar Avramovic case TargetOpcode::G_FABS:
116ec575f6eSPetar Avramovic case TargetOpcode::G_FSQRT:
117ec575f6eSPetar Avramovic case TargetOpcode::G_FCEIL:
118ec575f6eSPetar Avramovic case TargetOpcode::G_FFLOOR:
119ec575f6eSPetar Avramovic case TargetOpcode::G_FPEXT:
120ec575f6eSPetar Avramovic case TargetOpcode::G_FPTRUNC:
121ec575f6eSPetar Avramovic return true;
122ec575f6eSPetar Avramovic default:
123ec575f6eSPetar Avramovic return false;
124ec575f6eSPetar Avramovic }
125ec575f6eSPetar Avramovic }
126ec575f6eSPetar Avramovic
127aa699b20SPetar Avramovic // Instructions where use operands are floating point registers.
128aa699b20SPetar Avramovic // Def operands are general purpose.
isFloatingPointOpcodeUse(unsigned Opc)129aa699b20SPetar Avramovic static bool isFloatingPointOpcodeUse(unsigned Opc) {
130aa699b20SPetar Avramovic switch (Opc) {
131aa699b20SPetar Avramovic case TargetOpcode::G_FPTOSI:
132aa699b20SPetar Avramovic case TargetOpcode::G_FPTOUI:
133aa699b20SPetar Avramovic case TargetOpcode::G_FCMP:
134aa699b20SPetar Avramovic return true;
135aa699b20SPetar Avramovic default:
136aa699b20SPetar Avramovic return isFloatingPointOpcode(Opc);
137aa699b20SPetar Avramovic }
138aa699b20SPetar Avramovic }
139aa699b20SPetar Avramovic
140ec575f6eSPetar Avramovic // Instructions where def operands are floating point registers.
141ec575f6eSPetar Avramovic // Use operands are general purpose.
isFloatingPointOpcodeDef(unsigned Opc)142ec575f6eSPetar Avramovic static bool isFloatingPointOpcodeDef(unsigned Opc) {
143ec575f6eSPetar Avramovic switch (Opc) {
144ec575f6eSPetar Avramovic case TargetOpcode::G_SITOFP:
145ec575f6eSPetar Avramovic case TargetOpcode::G_UITOFP:
146ec575f6eSPetar Avramovic return true;
147ec575f6eSPetar Avramovic default:
148ec575f6eSPetar Avramovic return isFloatingPointOpcode(Opc);
149ec575f6eSPetar Avramovic }
150ec575f6eSPetar Avramovic }
151ec575f6eSPetar Avramovic
isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr * MI)1525171d152SPetar Avramovic static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
1535171d152SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_LOAD ||
1545171d152SPetar Avramovic MI->getOpcode() == TargetOpcode::G_STORE) {
1555171d152SPetar Avramovic auto MMO = *MI->memoperands_begin();
156*ad73ce31SZongwei Lan const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
1575171d152SPetar Avramovic if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
15874eac903SGuillaume Chatelet MMO->getAlign() < MMO->getSize()))
1595171d152SPetar Avramovic return true;
1605171d152SPetar Avramovic }
1615171d152SPetar Avramovic return false;
1625171d152SPetar Avramovic }
1635171d152SPetar Avramovic
isAmbiguous(unsigned Opc)164ec575f6eSPetar Avramovic static bool isAmbiguous(unsigned Opc) {
165ec575f6eSPetar Avramovic switch (Opc) {
166ec575f6eSPetar Avramovic case TargetOpcode::G_LOAD:
167ec575f6eSPetar Avramovic case TargetOpcode::G_STORE:
168ec575f6eSPetar Avramovic case TargetOpcode::G_PHI:
169ec575f6eSPetar Avramovic case TargetOpcode::G_SELECT:
17075e43a60SPetar Avramovic case TargetOpcode::G_IMPLICIT_DEF:
17192c80529SPetar Avramovic case TargetOpcode::G_UNMERGE_VALUES:
17292c80529SPetar Avramovic case TargetOpcode::G_MERGE_VALUES:
173ec575f6eSPetar Avramovic return true;
174ec575f6eSPetar Avramovic default:
175ec575f6eSPetar Avramovic return false;
176ec575f6eSPetar Avramovic }
177ec575f6eSPetar Avramovic }
178ec575f6eSPetar Avramovic
addDefUses(Register Reg,const MachineRegisterInfo & MRI)179aa699b20SPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
180aa699b20SPetar Avramovic Register Reg, const MachineRegisterInfo &MRI) {
181aa699b20SPetar Avramovic assert(!MRI.getType(Reg).isPointer() &&
182aa699b20SPetar Avramovic "Pointers are gprb, they should not be considered as ambiguous.\n");
183aa699b20SPetar Avramovic for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
18496252407SPetar Avramovic MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
18596252407SPetar Avramovic // Copy with many uses.
18696252407SPetar Avramovic if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
1872bea69bfSDaniel Sanders !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg()))
18896252407SPetar Avramovic addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
18996252407SPetar Avramovic else
19096252407SPetar Avramovic DefUses.push_back(skipCopiesOutgoing(&UseMI));
191aa699b20SPetar Avramovic }
192aa699b20SPetar Avramovic }
193aa699b20SPetar Avramovic
addUseDef(Register Reg,const MachineRegisterInfo & MRI)194ec575f6eSPetar Avramovic void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
195ec575f6eSPetar Avramovic Register Reg, const MachineRegisterInfo &MRI) {
196ec575f6eSPetar Avramovic assert(!MRI.getType(Reg).isPointer() &&
197ec575f6eSPetar Avramovic "Pointers are gprb, they should not be considered as ambiguous.\n");
198ec575f6eSPetar Avramovic MachineInstr *DefMI = MRI.getVRegDef(Reg);
19996252407SPetar Avramovic UseDefs.push_back(skipCopiesIncoming(DefMI));
20096252407SPetar Avramovic }
201ec575f6eSPetar Avramovic
20296252407SPetar Avramovic MachineInstr *
skipCopiesOutgoing(MachineInstr * MI) const20396252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
20496252407SPetar Avramovic MachineInstr *MI) const {
20596252407SPetar Avramovic const MachineFunction &MF = *MI->getParent()->getParent();
20696252407SPetar Avramovic const MachineRegisterInfo &MRI = MF.getRegInfo();
20796252407SPetar Avramovic MachineInstr *Ret = MI;
20896252407SPetar Avramovic while (Ret->getOpcode() == TargetOpcode::COPY &&
2092bea69bfSDaniel Sanders !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) &&
21096252407SPetar Avramovic MRI.hasOneUse(Ret->getOperand(0).getReg())) {
21196252407SPetar Avramovic Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
21296252407SPetar Avramovic }
21396252407SPetar Avramovic return Ret;
21496252407SPetar Avramovic }
21596252407SPetar Avramovic
21696252407SPetar Avramovic MachineInstr *
skipCopiesIncoming(MachineInstr * MI) const21796252407SPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
21896252407SPetar Avramovic MachineInstr *MI) const {
21996252407SPetar Avramovic const MachineFunction &MF = *MI->getParent()->getParent();
22096252407SPetar Avramovic const MachineRegisterInfo &MRI = MF.getRegInfo();
22196252407SPetar Avramovic MachineInstr *Ret = MI;
22296252407SPetar Avramovic while (Ret->getOpcode() == TargetOpcode::COPY &&
2232bea69bfSDaniel Sanders !Register::isPhysicalRegister(Ret->getOperand(1).getReg()))
22496252407SPetar Avramovic Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
22596252407SPetar Avramovic return Ret;
226ec575f6eSPetar Avramovic }
227ec575f6eSPetar Avramovic
AmbiguousRegDefUseContainer(const MachineInstr * MI)228ec575f6eSPetar Avramovic MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
229ec575f6eSPetar Avramovic const MachineInstr *MI) {
230ec575f6eSPetar Avramovic assert(isAmbiguous(MI->getOpcode()) &&
231ec575f6eSPetar Avramovic "Not implemented for non Ambiguous opcode.\n");
232ec575f6eSPetar Avramovic
233ec575f6eSPetar Avramovic const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
234ec575f6eSPetar Avramovic
235aa699b20SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_LOAD)
236aa699b20SPetar Avramovic addDefUses(MI->getOperand(0).getReg(), MRI);
237aa699b20SPetar Avramovic
238ec575f6eSPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_STORE)
239ec575f6eSPetar Avramovic addUseDef(MI->getOperand(0).getReg(), MRI);
240dbb6d01dSPetar Avramovic
241be20e361SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_PHI) {
242be20e361SPetar Avramovic addDefUses(MI->getOperand(0).getReg(), MRI);
243be20e361SPetar Avramovic
244be20e361SPetar Avramovic for (unsigned i = 1; i < MI->getNumOperands(); i += 2)
245be20e361SPetar Avramovic addUseDef(MI->getOperand(i).getReg(), MRI);
246be20e361SPetar Avramovic }
247be20e361SPetar Avramovic
248dbb6d01dSPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_SELECT) {
249dbb6d01dSPetar Avramovic addDefUses(MI->getOperand(0).getReg(), MRI);
250dbb6d01dSPetar Avramovic
251dbb6d01dSPetar Avramovic addUseDef(MI->getOperand(2).getReg(), MRI);
252dbb6d01dSPetar Avramovic addUseDef(MI->getOperand(3).getReg(), MRI);
253dbb6d01dSPetar Avramovic }
25475e43a60SPetar Avramovic
25575e43a60SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
25675e43a60SPetar Avramovic addDefUses(MI->getOperand(0).getReg(), MRI);
25792c80529SPetar Avramovic
25892c80529SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
25992c80529SPetar Avramovic addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
26092c80529SPetar Avramovic
26192c80529SPetar Avramovic if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
26292c80529SPetar Avramovic addDefUses(MI->getOperand(0).getReg(), MRI);
263ec575f6eSPetar Avramovic }
264ec575f6eSPetar Avramovic
visit(const MachineInstr * MI,const MachineInstr * WaitingForTypeOfMI,InstType & AmbiguousTy)265e3bb0a72SPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visit(
26692c80529SPetar Avramovic const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
26792c80529SPetar Avramovic InstType &AmbiguousTy) {
268ec575f6eSPetar Avramovic assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
269e3bb0a72SPetar Avramovic if (wasVisited(MI))
270e3bb0a72SPetar Avramovic return true; // InstType has already been determined for MI.
271ec575f6eSPetar Avramovic
272ec575f6eSPetar Avramovic startVisit(MI);
273ec575f6eSPetar Avramovic AmbiguousRegDefUseContainer DefUseContainer(MI);
274ec575f6eSPetar Avramovic
2755171d152SPetar Avramovic if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
2765171d152SPetar Avramovic setTypes(MI, Integer);
2775171d152SPetar Avramovic return true;
2785171d152SPetar Avramovic }
2795171d152SPetar Avramovic
28092c80529SPetar Avramovic if (AmbiguousTy == InstType::Ambiguous &&
28192c80529SPetar Avramovic (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
28292c80529SPetar Avramovic MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
28392c80529SPetar Avramovic AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
28492c80529SPetar Avramovic
285aa699b20SPetar Avramovic // Visit instructions where MI's DEF operands are USED.
28692c80529SPetar Avramovic if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
287aa699b20SPetar Avramovic return true;
288aa699b20SPetar Avramovic
289ec575f6eSPetar Avramovic // Visit instructions that DEFINE MI's USE operands.
29092c80529SPetar Avramovic if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
291ec575f6eSPetar Avramovic return true;
292ec575f6eSPetar Avramovic
293e3bb0a72SPetar Avramovic // All MI's adjacent instructions, are ambiguous.
294e3bb0a72SPetar Avramovic if (!WaitingForTypeOfMI) {
295e3bb0a72SPetar Avramovic // This is chain of ambiguous instructions.
29692c80529SPetar Avramovic setTypes(MI, AmbiguousTy);
297e3bb0a72SPetar Avramovic return true;
298e3bb0a72SPetar Avramovic }
299e3bb0a72SPetar Avramovic // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
300e3bb0a72SPetar Avramovic // instructions or has no other adjacent instructions. Anyway InstType could
301e3bb0a72SPetar Avramovic // not be determined. There could be unexplored path from some of
302e3bb0a72SPetar Avramovic // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
303e3bb0a72SPetar Avramovic // mapping available.
304e3bb0a72SPetar Avramovic // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
305e3bb0a72SPetar Avramovic // this way when WaitingForTypeOfMI figures out its InstType same InstType
306e3bb0a72SPetar Avramovic // will be assigned to all instructions in this branch.
307e3bb0a72SPetar Avramovic addToWaitingQueue(WaitingForTypeOfMI, MI);
308ec575f6eSPetar Avramovic return false;
309ec575f6eSPetar Avramovic }
310ec575f6eSPetar Avramovic
visitAdjacentInstrs(const MachineInstr * MI,SmallVectorImpl<MachineInstr * > & AdjacentInstrs,bool isDefUse,InstType & AmbiguousTy)311ec575f6eSPetar Avramovic bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
312aa699b20SPetar Avramovic const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
31392c80529SPetar Avramovic bool isDefUse, InstType &AmbiguousTy) {
314ec575f6eSPetar Avramovic while (!AdjacentInstrs.empty()) {
315ec575f6eSPetar Avramovic MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
316ec575f6eSPetar Avramovic
317aa699b20SPetar Avramovic if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
318aa699b20SPetar Avramovic : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
319ec575f6eSPetar Avramovic setTypes(MI, InstType::FloatingPoint);
320ec575f6eSPetar Avramovic return true;
321ec575f6eSPetar Avramovic }
322ec575f6eSPetar Avramovic
323ec575f6eSPetar Avramovic // Determine InstType from register bank of phys register that is
324aa699b20SPetar Avramovic // 'isDefUse ? def : use' of this copy.
325ec575f6eSPetar Avramovic if (AdjMI->getOpcode() == TargetOpcode::COPY) {
326aa699b20SPetar Avramovic setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
327ec575f6eSPetar Avramovic return true;
328ec575f6eSPetar Avramovic }
329ec575f6eSPetar Avramovic
33092c80529SPetar Avramovic // Defaults to integer instruction. Small registers in G_MERGE (uses) and
33192c80529SPetar Avramovic // G_UNMERGE (defs) will always be gprb.
33292c80529SPetar Avramovic if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
33392c80529SPetar Avramovic (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
33492c80529SPetar Avramovic !isAmbiguous(AdjMI->getOpcode())) {
335ec575f6eSPetar Avramovic setTypes(MI, InstType::Integer);
336ec575f6eSPetar Avramovic return true;
337ec575f6eSPetar Avramovic }
338e3bb0a72SPetar Avramovic
339e3bb0a72SPetar Avramovic // When AdjMI was visited first, MI has to continue to explore remaining
340e3bb0a72SPetar Avramovic // adjacent instructions and determine InstType without visiting AdjMI.
341e3bb0a72SPetar Avramovic if (!wasVisited(AdjMI) ||
342e3bb0a72SPetar Avramovic getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
34392c80529SPetar Avramovic if (visit(AdjMI, MI, AmbiguousTy)) {
344e3bb0a72SPetar Avramovic // InstType is successfully determined and is same as for AdjMI.
345e3bb0a72SPetar Avramovic setTypes(MI, getRecordedTypeForInstr(AdjMI));
346e3bb0a72SPetar Avramovic return true;
347e3bb0a72SPetar Avramovic }
348e3bb0a72SPetar Avramovic }
349e3bb0a72SPetar Avramovic }
350ec575f6eSPetar Avramovic return false;
351ec575f6eSPetar Avramovic }
352ec575f6eSPetar Avramovic
setTypes(const MachineInstr * MI,InstType InstTy)353ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
354ec575f6eSPetar Avramovic InstType InstTy) {
355ec575f6eSPetar Avramovic changeRecordedTypeForInstr(MI, InstTy);
356e3bb0a72SPetar Avramovic for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
357e3bb0a72SPetar Avramovic setTypes(WaitingInstr, InstTy);
358e3bb0a72SPetar Avramovic }
359ec575f6eSPetar Avramovic }
360ec575f6eSPetar Avramovic
setTypesAccordingToPhysicalRegister(const MachineInstr * MI,const MachineInstr * CopyInst,unsigned Op)361ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
362ec575f6eSPetar Avramovic const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
3632bea69bfSDaniel Sanders assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) &&
364ec575f6eSPetar Avramovic "Copies of non physical registers should not be considered here.\n");
365ec575f6eSPetar Avramovic
366ec575f6eSPetar Avramovic const MachineFunction &MF = *CopyInst->getMF();
367ec575f6eSPetar Avramovic const MachineRegisterInfo &MRI = MF.getRegInfo();
368ec575f6eSPetar Avramovic const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
369ec575f6eSPetar Avramovic const RegisterBankInfo &RBI =
370ec575f6eSPetar Avramovic *CopyInst->getMF()->getSubtarget().getRegBankInfo();
371ec575f6eSPetar Avramovic const RegisterBank *Bank =
372ec575f6eSPetar Avramovic RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
373ec575f6eSPetar Avramovic
374ec575f6eSPetar Avramovic if (Bank == &Mips::FPRBRegBank)
375ec575f6eSPetar Avramovic setTypes(MI, InstType::FloatingPoint);
376ec575f6eSPetar Avramovic else if (Bank == &Mips::GPRBRegBank)
377ec575f6eSPetar Avramovic setTypes(MI, InstType::Integer);
378ec575f6eSPetar Avramovic else
379ec575f6eSPetar Avramovic llvm_unreachable("Unsupported register bank.\n");
380ec575f6eSPetar Avramovic }
381ec575f6eSPetar Avramovic
382ec575f6eSPetar Avramovic MipsRegisterBankInfo::InstType
determineInstType(const MachineInstr * MI)383ec575f6eSPetar Avramovic MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
38492c80529SPetar Avramovic InstType DefaultAmbiguousType = InstType::Ambiguous;
38592c80529SPetar Avramovic visit(MI, nullptr, DefaultAmbiguousType);
386ec575f6eSPetar Avramovic return getRecordedTypeForInstr(MI);
387ec575f6eSPetar Avramovic }
388ec575f6eSPetar Avramovic
cleanupIfNewFunction(llvm::StringRef FunctionName)389ec575f6eSPetar Avramovic void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
390ec575f6eSPetar Avramovic llvm::StringRef FunctionName) {
391ec575f6eSPetar Avramovic if (MFName != FunctionName) {
392adcd0268SBenjamin Kramer MFName = std::string(FunctionName);
393e3bb0a72SPetar Avramovic WaitingQueues.clear();
394ec575f6eSPetar Avramovic Types.clear();
395ec575f6eSPetar Avramovic }
396ec575f6eSPetar Avramovic }
397ec575f6eSPetar Avramovic
398599591f3SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
getMSAMapping(const MachineFunction & MF)399599591f3SPetar Avramovic getMSAMapping(const MachineFunction &MF) {
400*ad73ce31SZongwei Lan assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
401599591f3SPetar Avramovic "MSA mapping not available on target without MSA.");
402599591f3SPetar Avramovic return &Mips::ValueMappings[Mips::MSAIdx];
403599591f3SPetar Avramovic }
404599591f3SPetar Avramovic
getFprbMapping(unsigned Size)405f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
406f7c213c9SPetar Avramovic return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
407f7c213c9SPetar Avramovic : &Mips::ValueMappings[Mips::DPRIdx];
408f7c213c9SPetar Avramovic }
409f7c213c9SPetar Avramovic
410f7c213c9SPetar Avramovic static const unsigned CustomMappingID = 1;
411f7c213c9SPetar Avramovic
412f7c213c9SPetar Avramovic // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
413f7c213c9SPetar Avramovic // will be split into two 32 bit registers in gprb.
414f7c213c9SPetar Avramovic static const MipsRegisterBankInfo::ValueMapping *
getGprbOrCustomMapping(unsigned Size,unsigned & MappingID)415f7c213c9SPetar Avramovic getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
416f7c213c9SPetar Avramovic if (Size == 32)
417f7c213c9SPetar Avramovic return &Mips::ValueMappings[Mips::GPRIdx];
418f7c213c9SPetar Avramovic
419f7c213c9SPetar Avramovic MappingID = CustomMappingID;
420f7c213c9SPetar Avramovic return &Mips::ValueMappings[Mips::DPRIdx];
421f7c213c9SPetar Avramovic }
422f7c213c9SPetar Avramovic
423366857a2SPetar Jovanovic const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const424366857a2SPetar Jovanovic MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
425366857a2SPetar Jovanovic
426ec575f6eSPetar Avramovic static TypeInfoForMF TI;
427ec575f6eSPetar Avramovic
428ec575f6eSPetar Avramovic // Reset TI internal data when MF changes.
429ec575f6eSPetar Avramovic TI.cleanupIfNewFunction(MI.getMF()->getName());
430ec575f6eSPetar Avramovic
431366857a2SPetar Jovanovic unsigned Opc = MI.getOpcode();
4321af05df3SPetar Avramovic const MachineFunction &MF = *MI.getParent()->getParent();
4331af05df3SPetar Avramovic const MachineRegisterInfo &MRI = MF.getRegInfo();
434366857a2SPetar Jovanovic
435be20e361SPetar Avramovic if (MI.getOpcode() != TargetOpcode::G_PHI) {
436be20e361SPetar Avramovic const RegisterBankInfo::InstructionMapping &Mapping =
437be20e361SPetar Avramovic getInstrMappingImpl(MI);
438366857a2SPetar Jovanovic if (Mapping.isValid())
439366857a2SPetar Jovanovic return Mapping;
440be20e361SPetar Avramovic }
441366857a2SPetar Jovanovic
442366857a2SPetar Jovanovic using namespace TargetOpcode;
443366857a2SPetar Jovanovic
444366857a2SPetar Jovanovic unsigned NumOperands = MI.getNumOperands();
445366857a2SPetar Jovanovic const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
446ec575f6eSPetar Avramovic unsigned MappingID = DefaultMappingID;
447f7c213c9SPetar Avramovic
448f7c213c9SPetar Avramovic // Check if LLT sizes match sizes of available register banks.
449f7c213c9SPetar Avramovic for (const MachineOperand &Op : MI.operands()) {
450f7c213c9SPetar Avramovic if (Op.isReg()) {
451f7c213c9SPetar Avramovic LLT RegTy = MRI.getType(Op.getReg());
452f7c213c9SPetar Avramovic
453f7c213c9SPetar Avramovic if (RegTy.isScalar() &&
454f7c213c9SPetar Avramovic (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
455f7c213c9SPetar Avramovic return getInvalidInstructionMapping();
456599591f3SPetar Avramovic
457599591f3SPetar Avramovic if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
458599591f3SPetar Avramovic return getInvalidInstructionMapping();
459f7c213c9SPetar Avramovic }
460f7c213c9SPetar Avramovic }
461f7c213c9SPetar Avramovic
462f7c213c9SPetar Avramovic const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
463f7c213c9SPetar Avramovic unsigned Op0Size = Op0Ty.getSizeInBits();
464f7c213c9SPetar Avramovic InstType InstTy = InstType::Integer;
465366857a2SPetar Jovanovic
466366857a2SPetar Jovanovic switch (Opc) {
4677cecadb9SPetar Avramovic case G_TRUNC:
468a48285a1SPetar Avramovic case G_UMULH:
46979df8596SPetar Avramovic case G_ZEXTLOAD:
47079df8596SPetar Avramovic case G_SEXTLOAD:
471e74c5b96SDaniel Sanders case G_PTR_ADD:
472b1fc6f61SPetar Avramovic case G_INTTOPTR:
473b1fc6f61SPetar Avramovic case G_PTRTOINT:
4743b953c37SPetar Jovanovic case G_AND:
4753b953c37SPetar Jovanovic case G_OR:
4763b953c37SPetar Jovanovic case G_XOR:
4773b953c37SPetar Jovanovic case G_SHL:
4783b953c37SPetar Jovanovic case G_ASHR:
4793b953c37SPetar Jovanovic case G_LSHR:
480ff6ac1ebSPetar Avramovic case G_BRINDIRECT:
481c063b0b0SPetar Avramovic case G_VASTART:
48294a24e7aSPetar Avramovic case G_BSWAP:
4832b66d32fSPetar Avramovic case G_CTLZ:
484366857a2SPetar Jovanovic OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
485366857a2SPetar Jovanovic break;
486e4af9de3SPetar Avramovic case G_ADD:
487c46d24f5SPetar Avramovic case G_SUB:
488d1815dacSPetar Avramovic case G_MUL:
4891d7f79c0SPetar Avramovic case G_SDIV:
4901d7f79c0SPetar Avramovic case G_SREM:
4911d7f79c0SPetar Avramovic case G_UDIV:
4921d7f79c0SPetar Avramovic case G_UREM:
493e4af9de3SPetar Avramovic OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
494e4af9de3SPetar Avramovic if (Op0Size == 128)
495e4af9de3SPetar Avramovic OperandsMapping = getMSAMapping(MF);
496e4af9de3SPetar Avramovic break;
497f7c213c9SPetar Avramovic case G_STORE:
49892c80529SPetar Avramovic case G_LOAD: {
499599591f3SPetar Avramovic if (Op0Size == 128) {
500599591f3SPetar Avramovic OperandsMapping = getOperandsMapping(
501599591f3SPetar Avramovic {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
502599591f3SPetar Avramovic break;
503599591f3SPetar Avramovic }
504599591f3SPetar Avramovic
505f7c213c9SPetar Avramovic if (!Op0Ty.isPointer())
506aa699b20SPetar Avramovic InstTy = TI.determineInstType(&MI);
507aa699b20SPetar Avramovic
50892c80529SPetar Avramovic if (isFloatingPoint_32or64(InstTy, Op0Size) ||
50992c80529SPetar Avramovic isAmbiguous_64(InstTy, Op0Size)) {
510f7c213c9SPetar Avramovic OperandsMapping = getOperandsMapping(
511f7c213c9SPetar Avramovic {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
51292c80529SPetar Avramovic } else {
51392c80529SPetar Avramovic assert((isInteger_32(InstTy, Op0Size) ||
51492c80529SPetar Avramovic isAmbiguous_32(InstTy, Op0Size) ||
51592c80529SPetar Avramovic isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
51692c80529SPetar Avramovic "Unexpected Inst type");
517aa699b20SPetar Avramovic OperandsMapping =
518f7c213c9SPetar Avramovic getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
519aa699b20SPetar Avramovic &Mips::ValueMappings[Mips::GPRIdx]});
52092c80529SPetar Avramovic }
521aa699b20SPetar Avramovic
522aa699b20SPetar Avramovic break;
52392c80529SPetar Avramovic }
52492c80529SPetar Avramovic case G_PHI: {
525f7c213c9SPetar Avramovic if (!Op0Ty.isPointer())
526ec575f6eSPetar Avramovic InstTy = TI.determineInstType(&MI);
527be20e361SPetar Avramovic
528be20e361SPetar Avramovic // PHI is copylike and should have one regbank in mapping for def register.
52992c80529SPetar Avramovic if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
530be20e361SPetar Avramovic OperandsMapping =
531be20e361SPetar Avramovic getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
53292c80529SPetar Avramovic TI.clearTypeInfoData(&MI);
533be20e361SPetar Avramovic return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
534be20e361SPetar Avramovic /*NumOperands=*/1);
535be20e361SPetar Avramovic }
53692c80529SPetar Avramovic assert((isInteger_32(InstTy, Op0Size) ||
53792c80529SPetar Avramovic isFloatingPoint_32or64(InstTy, Op0Size) ||
53892c80529SPetar Avramovic isAmbiguous_32or64(InstTy, Op0Size)) &&
53992c80529SPetar Avramovic "Unexpected Inst type");
540be20e361SPetar Avramovic // Use default handling for PHI, i.e. set reg bank of def operand to match
541be20e361SPetar Avramovic // register banks of use operands.
542f7c213c9SPetar Avramovic return getInstrMappingImpl(MI);
54392c80529SPetar Avramovic }
544dbb6d01dSPetar Avramovic case G_SELECT: {
545f7c213c9SPetar Avramovic if (!Op0Ty.isPointer())
546dbb6d01dSPetar Avramovic InstTy = TI.determineInstType(&MI);
54792c80529SPetar Avramovic if (isFloatingPoint_32or64(InstTy, Op0Size) ||
54892c80529SPetar Avramovic isAmbiguous_64(InstTy, Op0Size)) {
549f7c213c9SPetar Avramovic const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
550dbb6d01dSPetar Avramovic OperandsMapping = getOperandsMapping(
551dbb6d01dSPetar Avramovic {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
552dbb6d01dSPetar Avramovic break;
553f7c213c9SPetar Avramovic } else {
55492c80529SPetar Avramovic assert((isInteger_32(InstTy, Op0Size) ||
55592c80529SPetar Avramovic isAmbiguous_32(InstTy, Op0Size) ||
55692c80529SPetar Avramovic isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
55792c80529SPetar Avramovic "Unexpected Inst type");
558dbb6d01dSPetar Avramovic const RegisterBankInfo::ValueMapping *Bank =
559f7c213c9SPetar Avramovic getGprbOrCustomMapping(Op0Size, MappingID);
560dbb6d01dSPetar Avramovic OperandsMapping = getOperandsMapping(
561dbb6d01dSPetar Avramovic {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
562dbb6d01dSPetar Avramovic }
563dbb6d01dSPetar Avramovic break;
564dbb6d01dSPetar Avramovic }
56592c80529SPetar Avramovic case G_IMPLICIT_DEF: {
566f7c213c9SPetar Avramovic if (!Op0Ty.isPointer())
56775e43a60SPetar Avramovic InstTy = TI.determineInstType(&MI);
56875e43a60SPetar Avramovic
56992c80529SPetar Avramovic if (isFloatingPoint_32or64(InstTy, Op0Size))
570f7c213c9SPetar Avramovic OperandsMapping = getFprbMapping(Op0Size);
57192c80529SPetar Avramovic else {
57292c80529SPetar Avramovic assert((isInteger_32(InstTy, Op0Size) ||
57392c80529SPetar Avramovic isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
57492c80529SPetar Avramovic "Unexpected Inst type");
575f7c213c9SPetar Avramovic OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
57692c80529SPetar Avramovic }
57792c80529SPetar Avramovic } break;
57892c80529SPetar Avramovic case G_UNMERGE_VALUES: {
57992c80529SPetar Avramovic assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
58092c80529SPetar Avramovic unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
58192c80529SPetar Avramovic InstTy = TI.determineInstType(&MI);
58292c80529SPetar Avramovic assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
58392c80529SPetar Avramovic isFloatingPoint_64(InstTy, Op3Size)) &&
58492c80529SPetar Avramovic "Unexpected Inst type");
585aa699b20SPetar Avramovic OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
586aa699b20SPetar Avramovic &Mips::ValueMappings[Mips::GPRIdx],
587aa699b20SPetar Avramovic &Mips::ValueMappings[Mips::DPRIdx]});
58892c80529SPetar Avramovic if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
589aa699b20SPetar Avramovic MappingID = CustomMappingID;
590aa699b20SPetar Avramovic break;
59192c80529SPetar Avramovic }
59292c80529SPetar Avramovic case G_MERGE_VALUES: {
59392c80529SPetar Avramovic InstTy = TI.determineInstType(&MI);
59492c80529SPetar Avramovic assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
59592c80529SPetar Avramovic isFloatingPoint_64(InstTy, Op0Size)) &&
59692c80529SPetar Avramovic "Unexpected Inst type");
597ec575f6eSPetar Avramovic OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
598ec575f6eSPetar Avramovic &Mips::ValueMappings[Mips::GPRIdx],
599ec575f6eSPetar Avramovic &Mips::ValueMappings[Mips::GPRIdx]});
60092c80529SPetar Avramovic if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
601ec575f6eSPetar Avramovic MappingID = CustomMappingID;
602ec575f6eSPetar Avramovic break;
60392c80529SPetar Avramovic }
604afa3afa3SPetar Avramovic case G_FADD:
605afa3afa3SPetar Avramovic case G_FSUB:
606afa3afa3SPetar Avramovic case G_FMUL:
6070a1fd355SPetar Avramovic case G_FDIV:
608e3b49df5SPetar Avramovic case G_FABS:
609417dd678SPetar Avramovic case G_FSQRT:
610f7c213c9SPetar Avramovic OperandsMapping = getFprbMapping(Op0Size);
611914ce664SPetar Avramovic if (Op0Size == 128)
612914ce664SPetar Avramovic OperandsMapping = getMSAMapping(MF);
613afa3afa3SPetar Avramovic break;
614f7c213c9SPetar Avramovic case G_FCONSTANT:
615f7c213c9SPetar Avramovic OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
6161af05df3SPetar Avramovic break;
61722e99c43SPetar Avramovic case G_FCMP: {
618f7c213c9SPetar Avramovic unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
61922e99c43SPetar Avramovic OperandsMapping =
62022e99c43SPetar Avramovic getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
621f7c213c9SPetar Avramovic getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
62222e99c43SPetar Avramovic break;
62322e99c43SPetar Avramovic }
624a7d00064SPetar Avramovic case G_FPEXT:
625a7d00064SPetar Avramovic OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
626a7d00064SPetar Avramovic &Mips::ValueMappings[Mips::SPRIdx]});
627a7d00064SPetar Avramovic break;
628a7d00064SPetar Avramovic case G_FPTRUNC:
629a7d00064SPetar Avramovic OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
630a7d00064SPetar Avramovic &Mips::ValueMappings[Mips::DPRIdx]});
631a7d00064SPetar Avramovic break;
6324b4dae1cSPetar Avramovic case G_FPTOSI: {
633f7c213c9SPetar Avramovic assert((Op0Size == 32) && "Unsupported integer size");
6344b4dae1cSPetar Avramovic unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
635f7c213c9SPetar Avramovic OperandsMapping = getOperandsMapping(
636f7c213c9SPetar Avramovic {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
637f7c213c9SPetar Avramovic break;
638f7c213c9SPetar Avramovic }
639f7c213c9SPetar Avramovic case G_SITOFP:
640f7c213c9SPetar Avramovic assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
641ddd056c9SFangrui Song "Unsupported integer size");
642f7c213c9SPetar Avramovic OperandsMapping = getOperandsMapping(
643f7c213c9SPetar Avramovic {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
6444b4dae1cSPetar Avramovic break;
645021e4c82SPetar Jovanovic case G_CONSTANT:
646021e4c82SPetar Jovanovic case G_FRAME_INDEX:
64764c10ba8SPetar Jovanovic case G_GLOBAL_VALUE:
648caef9306SPetar Avramovic case G_JUMP_TABLE:
6495d9b8eedSPetar Avramovic case G_BRCOND:
650021e4c82SPetar Jovanovic OperandsMapping =
651021e4c82SPetar Jovanovic getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
652021e4c82SPetar Jovanovic break;
653caef9306SPetar Avramovic case G_BRJT:
654caef9306SPetar Avramovic OperandsMapping =
655caef9306SPetar Avramovic getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
656caef9306SPetar Avramovic &Mips::ValueMappings[Mips::GPRIdx]});
657caef9306SPetar Avramovic break;
658ce4dd0aeSPetar Jovanovic case G_ICMP:
659ce4dd0aeSPetar Jovanovic OperandsMapping =
660ce4dd0aeSPetar Jovanovic getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
661ce4dd0aeSPetar Jovanovic &Mips::ValueMappings[Mips::GPRIdx],
662ce4dd0aeSPetar Jovanovic &Mips::ValueMappings[Mips::GPRIdx]});
663ce4dd0aeSPetar Jovanovic break;
664366857a2SPetar Jovanovic default:
665366857a2SPetar Jovanovic return getInvalidInstructionMapping();
666366857a2SPetar Jovanovic }
667366857a2SPetar Jovanovic
66892c80529SPetar Avramovic if (MappingID == CustomMappingID)
66992c80529SPetar Avramovic TI.clearTypeInfoData(&MI);
670ec575f6eSPetar Avramovic return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
671366857a2SPetar Jovanovic NumOperands);
672366857a2SPetar Jovanovic }
673ec575f6eSPetar Avramovic
674ec575f6eSPetar Avramovic using InstListTy = GISelWorkList<4>;
675ec575f6eSPetar Avramovic namespace {
676ec575f6eSPetar Avramovic class InstManager : public GISelChangeObserver {
677ec575f6eSPetar Avramovic InstListTy &InstList;
678ec575f6eSPetar Avramovic
679ec575f6eSPetar Avramovic public:
InstManager(InstListTy & Insts)680ec575f6eSPetar Avramovic InstManager(InstListTy &Insts) : InstList(Insts) {}
681ec575f6eSPetar Avramovic
createdInstr(MachineInstr & MI)682ec575f6eSPetar Avramovic void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
erasingInstr(MachineInstr & MI)683ec575f6eSPetar Avramovic void erasingInstr(MachineInstr &MI) override {}
changingInstr(MachineInstr & MI)684ec575f6eSPetar Avramovic void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)685ec575f6eSPetar Avramovic void changedInstr(MachineInstr &MI) override {}
686ec575f6eSPetar Avramovic };
687ec575f6eSPetar Avramovic } // end anonymous namespace
688ec575f6eSPetar Avramovic
setRegBank(MachineInstr & MI,MachineRegisterInfo & MRI) const689f7c213c9SPetar Avramovic void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
690f7c213c9SPetar Avramovic MachineRegisterInfo &MRI) const {
691f7c213c9SPetar Avramovic Register Dest = MI.getOperand(0).getReg();
692f7c213c9SPetar Avramovic switch (MI.getOpcode()) {
693f7c213c9SPetar Avramovic case TargetOpcode::G_STORE:
694f7c213c9SPetar Avramovic // No def operands, skip this instruction.
695f7c213c9SPetar Avramovic break;
696f7c213c9SPetar Avramovic case TargetOpcode::G_CONSTANT:
697f7c213c9SPetar Avramovic case TargetOpcode::G_LOAD:
698f7c213c9SPetar Avramovic case TargetOpcode::G_SELECT:
699f7c213c9SPetar Avramovic case TargetOpcode::G_PHI:
700f7c213c9SPetar Avramovic case TargetOpcode::G_IMPLICIT_DEF: {
701f7c213c9SPetar Avramovic assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
702f7c213c9SPetar Avramovic MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
703f7c213c9SPetar Avramovic break;
704f7c213c9SPetar Avramovic }
705e74c5b96SDaniel Sanders case TargetOpcode::G_PTR_ADD: {
706f7c213c9SPetar Avramovic assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
707f7c213c9SPetar Avramovic MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
708f7c213c9SPetar Avramovic break;
709f7c213c9SPetar Avramovic }
710f7c213c9SPetar Avramovic default:
711f7c213c9SPetar Avramovic llvm_unreachable("Unexpected opcode.");
712f7c213c9SPetar Avramovic }
713f7c213c9SPetar Avramovic }
714f7c213c9SPetar Avramovic
715f7c213c9SPetar Avramovic static void
combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner & ArtCombiner,GUnmerge & MI,GISelChangeObserver & Observer)716f7c213c9SPetar Avramovic combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
7175ec0f051SAmara Emerson GUnmerge &MI, GISelChangeObserver &Observer) {
7188731799fSRoman Tereshin SmallVector<Register, 4> UpdatedDefs;
719f7c213c9SPetar Avramovic SmallVector<MachineInstr *, 2> DeadInstrs;
7205ec0f051SAmara Emerson ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
7215ec0f051SAmara Emerson UpdatedDefs, Observer);
722f7c213c9SPetar Avramovic for (MachineInstr *DeadMI : DeadInstrs)
723f7c213c9SPetar Avramovic DeadMI->eraseFromParent();
724f7c213c9SPetar Avramovic }
725f7c213c9SPetar Avramovic
applyMappingImpl(const OperandsMapper & OpdMapper) const726ec575f6eSPetar Avramovic void MipsRegisterBankInfo::applyMappingImpl(
727ec575f6eSPetar Avramovic const OperandsMapper &OpdMapper) const {
728ec575f6eSPetar Avramovic MachineInstr &MI = OpdMapper.getMI();
729ec575f6eSPetar Avramovic InstListTy NewInstrs;
730ec575f6eSPetar Avramovic MachineFunction *MF = MI.getMF();
731ec575f6eSPetar Avramovic MachineRegisterInfo &MRI = OpdMapper.getMRI();
732f7c213c9SPetar Avramovic const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
733ec575f6eSPetar Avramovic
734ec575f6eSPetar Avramovic InstManager NewInstrObserver(NewInstrs);
735d55d592aSMatt Arsenault MachineIRBuilder B(MI, NewInstrObserver);
736d55d592aSMatt Arsenault LegalizerHelper Helper(*MF, NewInstrObserver, B);
737f7c213c9SPetar Avramovic LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo);
738ec575f6eSPetar Avramovic
739ec575f6eSPetar Avramovic switch (MI.getOpcode()) {
740aa699b20SPetar Avramovic case TargetOpcode::G_LOAD:
741dbb6d01dSPetar Avramovic case TargetOpcode::G_STORE:
742be20e361SPetar Avramovic case TargetOpcode::G_PHI:
74375e43a60SPetar Avramovic case TargetOpcode::G_SELECT:
74475e43a60SPetar Avramovic case TargetOpcode::G_IMPLICIT_DEF: {
745ec575f6eSPetar Avramovic Helper.narrowScalar(MI, 0, LLT::scalar(32));
746ec575f6eSPetar Avramovic // Handle new instructions.
747ec575f6eSPetar Avramovic while (!NewInstrs.empty()) {
748ec575f6eSPetar Avramovic MachineInstr *NewMI = NewInstrs.pop_back_val();
749ec575f6eSPetar Avramovic // This is new G_UNMERGE that was created during narrowScalar and will
750ec575f6eSPetar Avramovic // not be considered for regbank selection. RegBankSelect for mips
751ec575f6eSPetar Avramovic // visits/makes corresponding G_MERGE first. Combine them here.
7525ec0f051SAmara Emerson if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
7535ec0f051SAmara Emerson combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
754aa699b20SPetar Avramovic // This G_MERGE will be combined away when its corresponding G_UNMERGE
755aa699b20SPetar Avramovic // gets regBankSelected.
756aa699b20SPetar Avramovic else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
757aa699b20SPetar Avramovic continue;
758aa699b20SPetar Avramovic else
759f7c213c9SPetar Avramovic // Manually set register banks for def operands to 32 bit gprb.
760f7c213c9SPetar Avramovic setRegBank(*NewMI, MRI);
761ec575f6eSPetar Avramovic }
762ec575f6eSPetar Avramovic return;
763ec575f6eSPetar Avramovic }
764f7c213c9SPetar Avramovic case TargetOpcode::G_UNMERGE_VALUES:
7655ec0f051SAmara Emerson combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
7665ec0f051SAmara Emerson NewInstrObserver);
767aa699b20SPetar Avramovic return;
768ec575f6eSPetar Avramovic default:
769ec575f6eSPetar Avramovic break;
770ec575f6eSPetar Avramovic }
771ec575f6eSPetar Avramovic
772ec575f6eSPetar Avramovic return applyDefaultMapping(OpdMapper);
773ec575f6eSPetar Avramovic }
774