10b57cec5SDimitry Andric //===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for Mips.
100b57cec5SDimitry Andric /// \todo This should be generated by TableGen.
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "MipsRegisterBankInfo.h"
140b57cec5SDimitry Andric #include "MipsInstrInfo.h"
158bcb0991SDimitry Andric #include "MipsTargetMachine.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric #define GET_TARGET_REGBANK_IMPL
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric #include "MipsGenRegisterBank.inc"
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric namespace llvm {
260b57cec5SDimitry Andric namespace Mips {
270b57cec5SDimitry Andric enum PartialMappingIdx {
280b57cec5SDimitry Andric PMI_GPR,
290b57cec5SDimitry Andric PMI_SPR,
300b57cec5SDimitry Andric PMI_DPR,
318bcb0991SDimitry Andric PMI_MSA,
320b57cec5SDimitry Andric PMI_Min = PMI_GPR,
330b57cec5SDimitry Andric };
340b57cec5SDimitry Andric
355f757f3fSDimitry Andric const RegisterBankInfo::PartialMapping PartMappings[]{
360b57cec5SDimitry Andric {0, 32, GPRBRegBank},
370b57cec5SDimitry Andric {0, 32, FPRBRegBank},
388bcb0991SDimitry Andric {0, 64, FPRBRegBank},
398bcb0991SDimitry Andric {0, 128, FPRBRegBank}
400b57cec5SDimitry Andric };
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric enum ValueMappingIdx {
430b57cec5SDimitry Andric InvalidIdx = 0,
440b57cec5SDimitry Andric GPRIdx = 1,
450b57cec5SDimitry Andric SPRIdx = 4,
468bcb0991SDimitry Andric DPRIdx = 7,
478bcb0991SDimitry Andric MSAIdx = 10
480b57cec5SDimitry Andric };
490b57cec5SDimitry Andric
505f757f3fSDimitry Andric const RegisterBankInfo::ValueMapping ValueMappings[] = {
510b57cec5SDimitry Andric // invalid
520b57cec5SDimitry Andric {nullptr, 0},
530b57cec5SDimitry Andric // up to 3 operands in GPRs
540b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1},
550b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1},
560b57cec5SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1},
578bcb0991SDimitry Andric // up to 3 operands in FPRs - single precission
580b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1},
590b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1},
600b57cec5SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1},
618bcb0991SDimitry Andric // up to 3 operands in FPRs - double precission
620b57cec5SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1},
630b57cec5SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1},
648bcb0991SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1},
658bcb0991SDimitry Andric // up to 3 operands in FPRs - MSA
668bcb0991SDimitry Andric {&PartMappings[PMI_MSA - PMI_Min], 1},
678bcb0991SDimitry Andric {&PartMappings[PMI_MSA - PMI_Min], 1},
688bcb0991SDimitry Andric {&PartMappings[PMI_MSA - PMI_Min], 1}
690b57cec5SDimitry Andric };
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric } // end namespace Mips
720b57cec5SDimitry Andric } // end namespace llvm
730b57cec5SDimitry Andric
740b57cec5SDimitry Andric using namespace llvm;
750b57cec5SDimitry Andric
MipsRegisterBankInfo(const TargetRegisterInfo & TRI)7681ad6265SDimitry Andric MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {}
770b57cec5SDimitry Andric
78480093f4SDimitry Andric const RegisterBank &
getRegBankFromRegClass(const TargetRegisterClass & RC,LLT) const79480093f4SDimitry Andric MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
80480093f4SDimitry Andric LLT) const {
810b57cec5SDimitry Andric using namespace Mips;
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric switch (RC.getID()) {
840b57cec5SDimitry Andric case Mips::GPR32RegClassID:
850b57cec5SDimitry Andric case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID:
860b57cec5SDimitry Andric case Mips::GPRMM16MovePPairFirstRegClassID:
870b57cec5SDimitry Andric case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID:
880b57cec5SDimitry Andric case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID:
890b57cec5SDimitry Andric case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID:
900b57cec5SDimitry Andric case Mips::SP32RegClassID:
910b57cec5SDimitry Andric case Mips::GP32RegClassID:
920b57cec5SDimitry Andric return getRegBank(Mips::GPRBRegBankID);
930b57cec5SDimitry Andric case Mips::FGRCCRegClassID:
940b57cec5SDimitry Andric case Mips::FGR32RegClassID:
950b57cec5SDimitry Andric case Mips::FGR64RegClassID:
960b57cec5SDimitry Andric case Mips::AFGR64RegClassID:
978bcb0991SDimitry Andric case Mips::MSA128BRegClassID:
988bcb0991SDimitry Andric case Mips::MSA128HRegClassID:
998bcb0991SDimitry Andric case Mips::MSA128WRegClassID:
1008bcb0991SDimitry Andric case Mips::MSA128DRegClassID:
1010b57cec5SDimitry Andric return getRegBank(Mips::FPRBRegBankID);
1020b57cec5SDimitry Andric default:
1030b57cec5SDimitry Andric llvm_unreachable("Register class not supported");
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric // Instructions where use operands are floating point registers.
1080b57cec5SDimitry Andric // Def operands are general purpose.
isFloatingPointOpcodeUse(unsigned Opc)1090b57cec5SDimitry Andric static bool isFloatingPointOpcodeUse(unsigned Opc) {
1100b57cec5SDimitry Andric switch (Opc) {
1110b57cec5SDimitry Andric case TargetOpcode::G_FPTOSI:
1120b57cec5SDimitry Andric case TargetOpcode::G_FPTOUI:
1130b57cec5SDimitry Andric case TargetOpcode::G_FCMP:
1140b57cec5SDimitry Andric return true;
1150b57cec5SDimitry Andric default:
116*0fca6ea1SDimitry Andric return isPreISelGenericFloatingPointOpcode(Opc);
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric // Instructions where def operands are floating point registers.
1210b57cec5SDimitry Andric // Use operands are general purpose.
isFloatingPointOpcodeDef(unsigned Opc)1220b57cec5SDimitry Andric static bool isFloatingPointOpcodeDef(unsigned Opc) {
1230b57cec5SDimitry Andric switch (Opc) {
1240b57cec5SDimitry Andric case TargetOpcode::G_SITOFP:
1250b57cec5SDimitry Andric case TargetOpcode::G_UITOFP:
1260b57cec5SDimitry Andric return true;
1270b57cec5SDimitry Andric default:
128*0fca6ea1SDimitry Andric return isPreISelGenericFloatingPointOpcode(Opc);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric
isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr * MI)1325ffd83dbSDimitry Andric static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {
1335ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD ||
1345ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_STORE) {
1355ffd83dbSDimitry Andric auto MMO = *MI->memoperands_begin();
13681ad6265SDimitry Andric const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();
1375ffd83dbSDimitry Andric if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&
138*0fca6ea1SDimitry Andric (!MMO->getSize().hasValue() ||
139*0fca6ea1SDimitry Andric MMO->getAlign() < MMO->getSize().getValue())))
1405ffd83dbSDimitry Andric return true;
1415ffd83dbSDimitry Andric }
1425ffd83dbSDimitry Andric return false;
1435ffd83dbSDimitry Andric }
1445ffd83dbSDimitry Andric
isAmbiguous(unsigned Opc)1450b57cec5SDimitry Andric static bool isAmbiguous(unsigned Opc) {
1460b57cec5SDimitry Andric switch (Opc) {
1470b57cec5SDimitry Andric case TargetOpcode::G_LOAD:
1480b57cec5SDimitry Andric case TargetOpcode::G_STORE:
1490b57cec5SDimitry Andric case TargetOpcode::G_PHI:
1500b57cec5SDimitry Andric case TargetOpcode::G_SELECT:
1518bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF:
1525ffd83dbSDimitry Andric case TargetOpcode::G_UNMERGE_VALUES:
1535ffd83dbSDimitry Andric case TargetOpcode::G_MERGE_VALUES:
1540b57cec5SDimitry Andric return true;
1550b57cec5SDimitry Andric default:
1560b57cec5SDimitry Andric return false;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
addDefUses(Register Reg,const MachineRegisterInfo & MRI)1600b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(
1610b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) {
1620b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() &&
1630b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n");
1640b57cec5SDimitry Andric for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {
1650b57cec5SDimitry Andric MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);
1660b57cec5SDimitry Andric // Copy with many uses.
1670b57cec5SDimitry Andric if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&
168bdd1243dSDimitry Andric !NonCopyInstr->getOperand(0).getReg().isPhysical())
1690b57cec5SDimitry Andric addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);
1700b57cec5SDimitry Andric else
1710b57cec5SDimitry Andric DefUses.push_back(skipCopiesOutgoing(&UseMI));
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric
addUseDef(Register Reg,const MachineRegisterInfo & MRI)1750b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
1760b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) {
1770b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() &&
1780b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n");
1790b57cec5SDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(Reg);
1800b57cec5SDimitry Andric UseDefs.push_back(skipCopiesIncoming(DefMI));
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric
1830b57cec5SDimitry Andric MachineInstr *
skipCopiesOutgoing(MachineInstr * MI) const1840b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(
1850b57cec5SDimitry Andric MachineInstr *MI) const {
1860b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent();
1870b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
1880b57cec5SDimitry Andric MachineInstr *Ret = MI;
1890b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY &&
190bdd1243dSDimitry Andric !Ret->getOperand(0).getReg().isPhysical() &&
1910b57cec5SDimitry Andric MRI.hasOneUse(Ret->getOperand(0).getReg())) {
1920b57cec5SDimitry Andric Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric return Ret;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric MachineInstr *
skipCopiesIncoming(MachineInstr * MI) const1980b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(
1990b57cec5SDimitry Andric MachineInstr *MI) const {
2000b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent();
2010b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
2020b57cec5SDimitry Andric MachineInstr *Ret = MI;
2030b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY &&
204bdd1243dSDimitry Andric !Ret->getOperand(1).getReg().isPhysical())
2050b57cec5SDimitry Andric Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());
2060b57cec5SDimitry Andric return Ret;
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric
AmbiguousRegDefUseContainer(const MachineInstr * MI)2090b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
2100b57cec5SDimitry Andric const MachineInstr *MI) {
2110b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) &&
2120b57cec5SDimitry Andric "Not implemented for non Ambiguous opcode.\n");
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD)
2170b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI);
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_STORE)
2200b57cec5SDimitry Andric addUseDef(MI->getOperand(0).getReg(), MRI);
2210b57cec5SDimitry Andric
2227a6dacacSDimitry Andric if (auto *PHI = dyn_cast<GPhi>(MI)) {
2237a6dacacSDimitry Andric addDefUses(PHI->getReg(0), MRI);
2240b57cec5SDimitry Andric
2257a6dacacSDimitry Andric for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)
2267a6dacacSDimitry Andric addUseDef(PHI->getIncomingValue(I), MRI);
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_SELECT) {
2300b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI);
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric addUseDef(MI->getOperand(2).getReg(), MRI);
2330b57cec5SDimitry Andric addUseDef(MI->getOperand(3).getReg(), MRI);
2340b57cec5SDimitry Andric }
2358bcb0991SDimitry Andric
2368bcb0991SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
2378bcb0991SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI);
2385ffd83dbSDimitry Andric
2395ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
2405ffd83dbSDimitry Andric addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);
2415ffd83dbSDimitry Andric
2425ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
2435ffd83dbSDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI);
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
visit(const MachineInstr * MI,const MachineInstr * WaitingForTypeOfMI,InstType & AmbiguousTy)2460b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visit(
2475ffd83dbSDimitry Andric const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,
2485ffd83dbSDimitry Andric InstType &AmbiguousTy) {
2490b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
2500b57cec5SDimitry Andric if (wasVisited(MI))
2510b57cec5SDimitry Andric return true; // InstType has already been determined for MI.
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric startVisit(MI);
2540b57cec5SDimitry Andric AmbiguousRegDefUseContainer DefUseContainer(MI);
2550b57cec5SDimitry Andric
2565ffd83dbSDimitry Andric if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {
2575ffd83dbSDimitry Andric setTypes(MI, Integer);
2585ffd83dbSDimitry Andric return true;
2595ffd83dbSDimitry Andric }
2605ffd83dbSDimitry Andric
2615ffd83dbSDimitry Andric if (AmbiguousTy == InstType::Ambiguous &&
2625ffd83dbSDimitry Andric (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||
2635ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))
2645ffd83dbSDimitry Andric AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;
2655ffd83dbSDimitry Andric
2660b57cec5SDimitry Andric // Visit instructions where MI's DEF operands are USED.
2675ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))
2680b57cec5SDimitry Andric return true;
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric // Visit instructions that DEFINE MI's USE operands.
2715ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))
2720b57cec5SDimitry Andric return true;
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andric // All MI's adjacent instructions, are ambiguous.
2750b57cec5SDimitry Andric if (!WaitingForTypeOfMI) {
2760b57cec5SDimitry Andric // This is chain of ambiguous instructions.
2775ffd83dbSDimitry Andric setTypes(MI, AmbiguousTy);
2780b57cec5SDimitry Andric return true;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous
2810b57cec5SDimitry Andric // instructions or has no other adjacent instructions. Anyway InstType could
2820b57cec5SDimitry Andric // not be determined. There could be unexplored path from some of
2830b57cec5SDimitry Andric // WaitingForTypeOfMI's adjacent instructions to an instruction with only one
2840b57cec5SDimitry Andric // mapping available.
2850b57cec5SDimitry Andric // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,
2860b57cec5SDimitry Andric // this way when WaitingForTypeOfMI figures out its InstType same InstType
2870b57cec5SDimitry Andric // will be assigned to all instructions in this branch.
2880b57cec5SDimitry Andric addToWaitingQueue(WaitingForTypeOfMI, MI);
2890b57cec5SDimitry Andric return false;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric
visitAdjacentInstrs(const MachineInstr * MI,SmallVectorImpl<MachineInstr * > & AdjacentInstrs,bool isDefUse,InstType & AmbiguousTy)2920b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
2930b57cec5SDimitry Andric const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
2945ffd83dbSDimitry Andric bool isDefUse, InstType &AmbiguousTy) {
2950b57cec5SDimitry Andric while (!AdjacentInstrs.empty()) {
2960b57cec5SDimitry Andric MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())
2990b57cec5SDimitry Andric : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
3000b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint);
3010b57cec5SDimitry Andric return true;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andric // Determine InstType from register bank of phys register that is
3050b57cec5SDimitry Andric // 'isDefUse ? def : use' of this copy.
3060b57cec5SDimitry Andric if (AdjMI->getOpcode() == TargetOpcode::COPY) {
3070b57cec5SDimitry Andric setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);
3080b57cec5SDimitry Andric return true;
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric
3115ffd83dbSDimitry Andric // Defaults to integer instruction. Small registers in G_MERGE (uses) and
3125ffd83dbSDimitry Andric // G_UNMERGE (defs) will always be gprb.
3135ffd83dbSDimitry Andric if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||
3145ffd83dbSDimitry Andric (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||
3155ffd83dbSDimitry Andric !isAmbiguous(AdjMI->getOpcode())) {
3160b57cec5SDimitry Andric setTypes(MI, InstType::Integer);
3170b57cec5SDimitry Andric return true;
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric // When AdjMI was visited first, MI has to continue to explore remaining
3210b57cec5SDimitry Andric // adjacent instructions and determine InstType without visiting AdjMI.
3220b57cec5SDimitry Andric if (!wasVisited(AdjMI) ||
3230b57cec5SDimitry Andric getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {
3245ffd83dbSDimitry Andric if (visit(AdjMI, MI, AmbiguousTy)) {
3250b57cec5SDimitry Andric // InstType is successfully determined and is same as for AdjMI.
3260b57cec5SDimitry Andric setTypes(MI, getRecordedTypeForInstr(AdjMI));
3270b57cec5SDimitry Andric return true;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric return false;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric
setTypes(const MachineInstr * MI,InstType InstTy)3340b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
3350b57cec5SDimitry Andric InstType InstTy) {
3360b57cec5SDimitry Andric changeRecordedTypeForInstr(MI, InstTy);
3370b57cec5SDimitry Andric for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {
3380b57cec5SDimitry Andric setTypes(WaitingInstr, InstTy);
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric
setTypesAccordingToPhysicalRegister(const MachineInstr * MI,const MachineInstr * CopyInst,unsigned Op)3420b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
3430b57cec5SDimitry Andric const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
344bdd1243dSDimitry Andric assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&
3450b57cec5SDimitry Andric "Copies of non physical registers should not be considered here.\n");
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric const MachineFunction &MF = *CopyInst->getMF();
3480b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
3490b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
3500b57cec5SDimitry Andric const RegisterBankInfo &RBI =
3510b57cec5SDimitry Andric *CopyInst->getMF()->getSubtarget().getRegBankInfo();
3520b57cec5SDimitry Andric const RegisterBank *Bank =
3530b57cec5SDimitry Andric RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric if (Bank == &Mips::FPRBRegBank)
3560b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint);
3570b57cec5SDimitry Andric else if (Bank == &Mips::GPRBRegBank)
3580b57cec5SDimitry Andric setTypes(MI, InstType::Integer);
3590b57cec5SDimitry Andric else
3600b57cec5SDimitry Andric llvm_unreachable("Unsupported register bank.\n");
3610b57cec5SDimitry Andric }
3620b57cec5SDimitry Andric
3630b57cec5SDimitry Andric MipsRegisterBankInfo::InstType
determineInstType(const MachineInstr * MI)3640b57cec5SDimitry Andric MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
3655ffd83dbSDimitry Andric InstType DefaultAmbiguousType = InstType::Ambiguous;
3665ffd83dbSDimitry Andric visit(MI, nullptr, DefaultAmbiguousType);
3670b57cec5SDimitry Andric return getRecordedTypeForInstr(MI);
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric
cleanupIfNewFunction(llvm::StringRef FunctionName)3700b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
3710b57cec5SDimitry Andric llvm::StringRef FunctionName) {
3720b57cec5SDimitry Andric if (MFName != FunctionName) {
3735ffd83dbSDimitry Andric MFName = std::string(FunctionName);
3740b57cec5SDimitry Andric WaitingQueues.clear();
3750b57cec5SDimitry Andric Types.clear();
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric
3798bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *
getMSAMapping(const MachineFunction & MF)3808bcb0991SDimitry Andric getMSAMapping(const MachineFunction &MF) {
38181ad6265SDimitry Andric assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&
3828bcb0991SDimitry Andric "MSA mapping not available on target without MSA.");
3838bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::MSAIdx];
3848bcb0991SDimitry Andric }
3858bcb0991SDimitry Andric
getFprbMapping(unsigned Size)3868bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {
3878bcb0991SDimitry Andric return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
3888bcb0991SDimitry Andric : &Mips::ValueMappings[Mips::DPRIdx];
3898bcb0991SDimitry Andric }
3908bcb0991SDimitry Andric
3918bcb0991SDimitry Andric static const unsigned CustomMappingID = 1;
3928bcb0991SDimitry Andric
3938bcb0991SDimitry Andric // Only 64 bit mapping is available in fprb and will be marked as custom, i.e.
3948bcb0991SDimitry Andric // will be split into two 32 bit registers in gprb.
3958bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *
getGprbOrCustomMapping(unsigned Size,unsigned & MappingID)3968bcb0991SDimitry Andric getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {
3978bcb0991SDimitry Andric if (Size == 32)
3988bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::GPRIdx];
3998bcb0991SDimitry Andric
4008bcb0991SDimitry Andric MappingID = CustomMappingID;
4018bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::DPRIdx];
4028bcb0991SDimitry Andric }
4038bcb0991SDimitry Andric
4040b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const4050b57cec5SDimitry Andric MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
4060b57cec5SDimitry Andric
4070b57cec5SDimitry Andric static TypeInfoForMF TI;
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric // Reset TI internal data when MF changes.
4100b57cec5SDimitry Andric TI.cleanupIfNewFunction(MI.getMF()->getName());
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric unsigned Opc = MI.getOpcode();
4130b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent();
4140b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo();
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric if (MI.getOpcode() != TargetOpcode::G_PHI) {
4170b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &Mapping =
4180b57cec5SDimitry Andric getInstrMappingImpl(MI);
4190b57cec5SDimitry Andric if (Mapping.isValid())
4200b57cec5SDimitry Andric return Mapping;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric
4230b57cec5SDimitry Andric using namespace TargetOpcode;
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric unsigned NumOperands = MI.getNumOperands();
4260b57cec5SDimitry Andric const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4270b57cec5SDimitry Andric unsigned MappingID = DefaultMappingID;
4288bcb0991SDimitry Andric
4298bcb0991SDimitry Andric // Check if LLT sizes match sizes of available register banks.
4308bcb0991SDimitry Andric for (const MachineOperand &Op : MI.operands()) {
4318bcb0991SDimitry Andric if (Op.isReg()) {
4328bcb0991SDimitry Andric LLT RegTy = MRI.getType(Op.getReg());
4338bcb0991SDimitry Andric
4348bcb0991SDimitry Andric if (RegTy.isScalar() &&
4358bcb0991SDimitry Andric (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))
4368bcb0991SDimitry Andric return getInvalidInstructionMapping();
4378bcb0991SDimitry Andric
4388bcb0991SDimitry Andric if (RegTy.isVector() && RegTy.getSizeInBits() != 128)
4398bcb0991SDimitry Andric return getInvalidInstructionMapping();
4408bcb0991SDimitry Andric }
4418bcb0991SDimitry Andric }
4428bcb0991SDimitry Andric
4438bcb0991SDimitry Andric const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());
4448bcb0991SDimitry Andric unsigned Op0Size = Op0Ty.getSizeInBits();
4458bcb0991SDimitry Andric InstType InstTy = InstType::Integer;
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andric switch (Opc) {
4480b57cec5SDimitry Andric case G_TRUNC:
4490b57cec5SDimitry Andric case G_UMULH:
4500b57cec5SDimitry Andric case G_ZEXTLOAD:
4510b57cec5SDimitry Andric case G_SEXTLOAD:
452480093f4SDimitry Andric case G_PTR_ADD:
4538bcb0991SDimitry Andric case G_INTTOPTR:
4548bcb0991SDimitry Andric case G_PTRTOINT:
4550b57cec5SDimitry Andric case G_AND:
4560b57cec5SDimitry Andric case G_OR:
4570b57cec5SDimitry Andric case G_XOR:
4580b57cec5SDimitry Andric case G_SHL:
4590b57cec5SDimitry Andric case G_ASHR:
4600b57cec5SDimitry Andric case G_LSHR:
4618bcb0991SDimitry Andric case G_BRINDIRECT:
4628bcb0991SDimitry Andric case G_VASTART:
463480093f4SDimitry Andric case G_BSWAP:
4645ffd83dbSDimitry Andric case G_CTLZ:
4650b57cec5SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4660b57cec5SDimitry Andric break;
4678bcb0991SDimitry Andric case G_ADD:
468480093f4SDimitry Andric case G_SUB:
469480093f4SDimitry Andric case G_MUL:
470480093f4SDimitry Andric case G_SDIV:
471480093f4SDimitry Andric case G_SREM:
472480093f4SDimitry Andric case G_UDIV:
473480093f4SDimitry Andric case G_UREM:
4748bcb0991SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
4758bcb0991SDimitry Andric if (Op0Size == 128)
4768bcb0991SDimitry Andric OperandsMapping = getMSAMapping(MF);
4778bcb0991SDimitry Andric break;
4788bcb0991SDimitry Andric case G_STORE:
4795ffd83dbSDimitry Andric case G_LOAD: {
4808bcb0991SDimitry Andric if (Op0Size == 128) {
4818bcb0991SDimitry Andric OperandsMapping = getOperandsMapping(
4828bcb0991SDimitry Andric {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});
4838bcb0991SDimitry Andric break;
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric
4868bcb0991SDimitry Andric if (!Op0Ty.isPointer())
4878bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI);
4888bcb0991SDimitry Andric
4895ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) ||
4905ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) {
4918bcb0991SDimitry Andric OperandsMapping = getOperandsMapping(
4928bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
4935ffd83dbSDimitry Andric } else {
4945ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) ||
4955ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) ||
4965ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
4975ffd83dbSDimitry Andric "Unexpected Inst type");
4980b57cec5SDimitry Andric OperandsMapping =
4998bcb0991SDimitry Andric getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),
5000b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]});
5015ffd83dbSDimitry Andric }
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric break;
5045ffd83dbSDimitry Andric }
5055ffd83dbSDimitry Andric case G_PHI: {
5068bcb0991SDimitry Andric if (!Op0Ty.isPointer())
5070b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI);
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric // PHI is copylike and should have one regbank in mapping for def register.
5105ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {
5110b57cec5SDimitry Andric OperandsMapping =
5120b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});
5135ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI);
5140b57cec5SDimitry Andric return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,
5150b57cec5SDimitry Andric /*NumOperands=*/1);
5160b57cec5SDimitry Andric }
5175ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) ||
5185ffd83dbSDimitry Andric isFloatingPoint_32or64(InstTy, Op0Size) ||
5195ffd83dbSDimitry Andric isAmbiguous_32or64(InstTy, Op0Size)) &&
5205ffd83dbSDimitry Andric "Unexpected Inst type");
5210b57cec5SDimitry Andric // Use default handling for PHI, i.e. set reg bank of def operand to match
5220b57cec5SDimitry Andric // register banks of use operands.
5238bcb0991SDimitry Andric return getInstrMappingImpl(MI);
5245ffd83dbSDimitry Andric }
5250b57cec5SDimitry Andric case G_SELECT: {
5268bcb0991SDimitry Andric if (!Op0Ty.isPointer())
5270b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI);
5285ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) ||
5295ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) {
5308bcb0991SDimitry Andric const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);
5310b57cec5SDimitry Andric OperandsMapping = getOperandsMapping(
5320b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
5330b57cec5SDimitry Andric break;
5348bcb0991SDimitry Andric } else {
5355ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) ||
5365ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) ||
5375ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
5385ffd83dbSDimitry Andric "Unexpected Inst type");
5390b57cec5SDimitry Andric const RegisterBankInfo::ValueMapping *Bank =
5408bcb0991SDimitry Andric getGprbOrCustomMapping(Op0Size, MappingID);
5410b57cec5SDimitry Andric OperandsMapping = getOperandsMapping(
5420b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric break;
5450b57cec5SDimitry Andric }
5465ffd83dbSDimitry Andric case G_IMPLICIT_DEF: {
5478bcb0991SDimitry Andric if (!Op0Ty.isPointer())
5488bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI);
5498bcb0991SDimitry Andric
5505ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size))
5518bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size);
5525ffd83dbSDimitry Andric else {
5535ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) ||
5545ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&
5555ffd83dbSDimitry Andric "Unexpected Inst type");
5568bcb0991SDimitry Andric OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);
5575ffd83dbSDimitry Andric }
5585ffd83dbSDimitry Andric } break;
5595ffd83dbSDimitry Andric case G_UNMERGE_VALUES: {
5605ffd83dbSDimitry Andric assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");
5615ffd83dbSDimitry Andric unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
5625ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI);
5635ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||
5645ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op3Size)) &&
5655ffd83dbSDimitry Andric "Unexpected Inst type");
5660b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],
5670b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx],
5680b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]});
5695ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))
5700b57cec5SDimitry Andric MappingID = CustomMappingID;
5710b57cec5SDimitry Andric break;
5725ffd83dbSDimitry Andric }
5735ffd83dbSDimitry Andric case G_MERGE_VALUES: {
5745ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI);
5755ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||
5765ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op0Size)) &&
5775ffd83dbSDimitry Andric "Unexpected Inst type");
5780b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
5790b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx],
5800b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]});
5815ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))
5820b57cec5SDimitry Andric MappingID = CustomMappingID;
5830b57cec5SDimitry Andric break;
5845ffd83dbSDimitry Andric }
5850b57cec5SDimitry Andric case G_FADD:
5860b57cec5SDimitry Andric case G_FSUB:
5870b57cec5SDimitry Andric case G_FMUL:
5880b57cec5SDimitry Andric case G_FDIV:
5890b57cec5SDimitry Andric case G_FABS:
5908bcb0991SDimitry Andric case G_FSQRT:
5918bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size);
592480093f4SDimitry Andric if (Op0Size == 128)
593480093f4SDimitry Andric OperandsMapping = getMSAMapping(MF);
5940b57cec5SDimitry Andric break;
5958bcb0991SDimitry Andric case G_FCONSTANT:
5968bcb0991SDimitry Andric OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});
5970b57cec5SDimitry Andric break;
5980b57cec5SDimitry Andric case G_FCMP: {
5998bcb0991SDimitry Andric unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
6000b57cec5SDimitry Andric OperandsMapping =
6010b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6028bcb0991SDimitry Andric getFprbMapping(Op2Size), getFprbMapping(Op2Size)});
6030b57cec5SDimitry Andric break;
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric case G_FPEXT:
6060b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
6070b57cec5SDimitry Andric &Mips::ValueMappings[Mips::SPRIdx]});
6080b57cec5SDimitry Andric break;
6090b57cec5SDimitry Andric case G_FPTRUNC:
6100b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],
6110b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]});
6120b57cec5SDimitry Andric break;
6130b57cec5SDimitry Andric case G_FPTOSI: {
6148bcb0991SDimitry Andric assert((Op0Size == 32) && "Unsupported integer size");
6150b57cec5SDimitry Andric unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
6168bcb0991SDimitry Andric OperandsMapping = getOperandsMapping(
6178bcb0991SDimitry Andric {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});
6188bcb0991SDimitry Andric break;
6198bcb0991SDimitry Andric }
6208bcb0991SDimitry Andric case G_SITOFP:
6218bcb0991SDimitry Andric assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&
6220b57cec5SDimitry Andric "Unsupported integer size");
6238bcb0991SDimitry Andric OperandsMapping = getOperandsMapping(
6248bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});
6250b57cec5SDimitry Andric break;
6260b57cec5SDimitry Andric case G_CONSTANT:
6270b57cec5SDimitry Andric case G_FRAME_INDEX:
6280b57cec5SDimitry Andric case G_GLOBAL_VALUE:
6298bcb0991SDimitry Andric case G_JUMP_TABLE:
6300b57cec5SDimitry Andric case G_BRCOND:
6310b57cec5SDimitry Andric OperandsMapping =
6320b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});
6330b57cec5SDimitry Andric break;
6348bcb0991SDimitry Andric case G_BRJT:
6358bcb0991SDimitry Andric OperandsMapping =
6368bcb0991SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6378bcb0991SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]});
6388bcb0991SDimitry Andric break;
6390b57cec5SDimitry Andric case G_ICMP:
6400b57cec5SDimitry Andric OperandsMapping =
6410b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,
6420b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx],
6430b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]});
6440b57cec5SDimitry Andric break;
6450b57cec5SDimitry Andric default:
6460b57cec5SDimitry Andric return getInvalidInstructionMapping();
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric
6495ffd83dbSDimitry Andric if (MappingID == CustomMappingID)
6505ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI);
6510b57cec5SDimitry Andric return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
6520b57cec5SDimitry Andric NumOperands);
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric
6550b57cec5SDimitry Andric using InstListTy = GISelWorkList<4>;
6560b57cec5SDimitry Andric namespace {
6570b57cec5SDimitry Andric class InstManager : public GISelChangeObserver {
6580b57cec5SDimitry Andric InstListTy &InstList;
6595f757f3fSDimitry Andric MachineIRBuilder &B;
6600b57cec5SDimitry Andric
6610b57cec5SDimitry Andric public:
InstManager(MachineIRBuilder & B,InstListTy & Insts)6625f757f3fSDimitry Andric InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {
6635f757f3fSDimitry Andric assert(!B.isObservingChanges());
6645f757f3fSDimitry Andric B.setChangeObserver(*this);
6655f757f3fSDimitry Andric }
6665f757f3fSDimitry Andric
~InstManager()6675f757f3fSDimitry Andric ~InstManager() { B.stopObservingChanges(); }
6680b57cec5SDimitry Andric
createdInstr(MachineInstr & MI)6690b57cec5SDimitry Andric void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
erasingInstr(MachineInstr & MI)6700b57cec5SDimitry Andric void erasingInstr(MachineInstr &MI) override {}
changingInstr(MachineInstr & MI)6710b57cec5SDimitry Andric void changingInstr(MachineInstr &MI) override {}
changedInstr(MachineInstr & MI)6720b57cec5SDimitry Andric void changedInstr(MachineInstr &MI) override {}
6730b57cec5SDimitry Andric };
6740b57cec5SDimitry Andric } // end anonymous namespace
6750b57cec5SDimitry Andric
setRegBank(MachineInstr & MI,MachineRegisterInfo & MRI) const6768bcb0991SDimitry Andric void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,
6778bcb0991SDimitry Andric MachineRegisterInfo &MRI) const {
6788bcb0991SDimitry Andric Register Dest = MI.getOperand(0).getReg();
6798bcb0991SDimitry Andric switch (MI.getOpcode()) {
6808bcb0991SDimitry Andric case TargetOpcode::G_STORE:
6818bcb0991SDimitry Andric // No def operands, skip this instruction.
6828bcb0991SDimitry Andric break;
6838bcb0991SDimitry Andric case TargetOpcode::G_CONSTANT:
6848bcb0991SDimitry Andric case TargetOpcode::G_LOAD:
6858bcb0991SDimitry Andric case TargetOpcode::G_SELECT:
6868bcb0991SDimitry Andric case TargetOpcode::G_PHI:
6878bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: {
6888bcb0991SDimitry Andric assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");
6898bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
6908bcb0991SDimitry Andric break;
6918bcb0991SDimitry Andric }
692480093f4SDimitry Andric case TargetOpcode::G_PTR_ADD: {
6938bcb0991SDimitry Andric assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");
6948bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));
6958bcb0991SDimitry Andric break;
6968bcb0991SDimitry Andric }
6978bcb0991SDimitry Andric default:
6988bcb0991SDimitry Andric llvm_unreachable("Unexpected opcode.");
6998bcb0991SDimitry Andric }
7008bcb0991SDimitry Andric }
7018bcb0991SDimitry Andric
7028bcb0991SDimitry Andric static void
combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner & ArtCombiner,GUnmerge & MI,GISelChangeObserver & Observer)7038bcb0991SDimitry Andric combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,
704fe6060f1SDimitry Andric GUnmerge &MI, GISelChangeObserver &Observer) {
705480093f4SDimitry Andric SmallVector<Register, 4> UpdatedDefs;
7068bcb0991SDimitry Andric SmallVector<MachineInstr *, 2> DeadInstrs;
707fe6060f1SDimitry Andric ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,
708fe6060f1SDimitry Andric UpdatedDefs, Observer);
7098bcb0991SDimitry Andric for (MachineInstr *DeadMI : DeadInstrs)
7108bcb0991SDimitry Andric DeadMI->eraseFromParent();
7118bcb0991SDimitry Andric }
7128bcb0991SDimitry Andric
applyMappingImpl(MachineIRBuilder & Builder,const OperandsMapper & OpdMapper) const7130b57cec5SDimitry Andric void MipsRegisterBankInfo::applyMappingImpl(
7145f757f3fSDimitry Andric MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
7150b57cec5SDimitry Andric MachineInstr &MI = OpdMapper.getMI();
7165f757f3fSDimitry Andric Builder.setInstrAndDebugLoc(MI);
7175f757f3fSDimitry Andric
7180b57cec5SDimitry Andric InstListTy NewInstrs;
7190b57cec5SDimitry Andric MachineFunction *MF = MI.getMF();
7200b57cec5SDimitry Andric MachineRegisterInfo &MRI = OpdMapper.getMRI();
7218bcb0991SDimitry Andric const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();
7220b57cec5SDimitry Andric
7235f757f3fSDimitry Andric InstManager NewInstrObserver(Builder, NewInstrs);
7245f757f3fSDimitry Andric LegalizerHelper Helper(*MF, NewInstrObserver, Builder);
7255f757f3fSDimitry Andric LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);
7260b57cec5SDimitry Andric
7270b57cec5SDimitry Andric switch (MI.getOpcode()) {
7280b57cec5SDimitry Andric case TargetOpcode::G_LOAD:
7290b57cec5SDimitry Andric case TargetOpcode::G_STORE:
7300b57cec5SDimitry Andric case TargetOpcode::G_PHI:
7318bcb0991SDimitry Andric case TargetOpcode::G_SELECT:
7328bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: {
7330b57cec5SDimitry Andric Helper.narrowScalar(MI, 0, LLT::scalar(32));
7340b57cec5SDimitry Andric // Handle new instructions.
7350b57cec5SDimitry Andric while (!NewInstrs.empty()) {
7360b57cec5SDimitry Andric MachineInstr *NewMI = NewInstrs.pop_back_val();
7370b57cec5SDimitry Andric // This is new G_UNMERGE that was created during narrowScalar and will
7380b57cec5SDimitry Andric // not be considered for regbank selection. RegBankSelect for mips
7390b57cec5SDimitry Andric // visits/makes corresponding G_MERGE first. Combine them here.
740fe6060f1SDimitry Andric if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))
741fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);
7420b57cec5SDimitry Andric // This G_MERGE will be combined away when its corresponding G_UNMERGE
7430b57cec5SDimitry Andric // gets regBankSelected.
7440b57cec5SDimitry Andric else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)
7450b57cec5SDimitry Andric continue;
7460b57cec5SDimitry Andric else
7478bcb0991SDimitry Andric // Manually set register banks for def operands to 32 bit gprb.
7488bcb0991SDimitry Andric setRegBank(*NewMI, MRI);
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric return;
7510b57cec5SDimitry Andric }
7528bcb0991SDimitry Andric case TargetOpcode::G_UNMERGE_VALUES:
753fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),
754fe6060f1SDimitry Andric NewInstrObserver);
7550b57cec5SDimitry Andric return;
7560b57cec5SDimitry Andric default:
7570b57cec5SDimitry Andric break;
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric return applyDefaultMapping(OpdMapper);
7610b57cec5SDimitry Andric }
762