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 35*5f757f3fSDimitry 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 50*5f757f3fSDimitry 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 7681ad6265SDimitry Andric MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {} 770b57cec5SDimitry Andric 78480093f4SDimitry Andric const RegisterBank & 79480093f4SDimitry 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 all register operands are floating point. 1080b57cec5SDimitry Andric static bool isFloatingPointOpcode(unsigned Opc) { 1090b57cec5SDimitry Andric switch (Opc) { 1100b57cec5SDimitry Andric case TargetOpcode::G_FCONSTANT: 1110b57cec5SDimitry Andric case TargetOpcode::G_FADD: 1120b57cec5SDimitry Andric case TargetOpcode::G_FSUB: 1130b57cec5SDimitry Andric case TargetOpcode::G_FMUL: 1140b57cec5SDimitry Andric case TargetOpcode::G_FDIV: 1150b57cec5SDimitry Andric case TargetOpcode::G_FABS: 1160b57cec5SDimitry Andric case TargetOpcode::G_FSQRT: 1170b57cec5SDimitry Andric case TargetOpcode::G_FCEIL: 1180b57cec5SDimitry Andric case TargetOpcode::G_FFLOOR: 1190b57cec5SDimitry Andric case TargetOpcode::G_FPEXT: 1200b57cec5SDimitry Andric case TargetOpcode::G_FPTRUNC: 1210b57cec5SDimitry Andric return true; 1220b57cec5SDimitry Andric default: 1230b57cec5SDimitry Andric return false; 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric // Instructions where use operands are floating point registers. 1280b57cec5SDimitry Andric // Def operands are general purpose. 1290b57cec5SDimitry Andric static bool isFloatingPointOpcodeUse(unsigned Opc) { 1300b57cec5SDimitry Andric switch (Opc) { 1310b57cec5SDimitry Andric case TargetOpcode::G_FPTOSI: 1320b57cec5SDimitry Andric case TargetOpcode::G_FPTOUI: 1330b57cec5SDimitry Andric case TargetOpcode::G_FCMP: 1340b57cec5SDimitry Andric return true; 1350b57cec5SDimitry Andric default: 1360b57cec5SDimitry Andric return isFloatingPointOpcode(Opc); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Instructions where def operands are floating point registers. 1410b57cec5SDimitry Andric // Use operands are general purpose. 1420b57cec5SDimitry Andric static bool isFloatingPointOpcodeDef(unsigned Opc) { 1430b57cec5SDimitry Andric switch (Opc) { 1440b57cec5SDimitry Andric case TargetOpcode::G_SITOFP: 1450b57cec5SDimitry Andric case TargetOpcode::G_UITOFP: 1460b57cec5SDimitry Andric return true; 1470b57cec5SDimitry Andric default: 1480b57cec5SDimitry Andric return isFloatingPointOpcode(Opc); 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1525ffd83dbSDimitry Andric static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) { 1535ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD || 1545ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_STORE) { 1555ffd83dbSDimitry Andric auto MMO = *MI->memoperands_begin(); 15681ad6265SDimitry Andric const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>(); 1575ffd83dbSDimitry Andric if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() && 1585ffd83dbSDimitry Andric MMO->getAlign() < MMO->getSize())) 1595ffd83dbSDimitry Andric return true; 1605ffd83dbSDimitry Andric } 1615ffd83dbSDimitry Andric return false; 1625ffd83dbSDimitry Andric } 1635ffd83dbSDimitry Andric 1640b57cec5SDimitry Andric static bool isAmbiguous(unsigned Opc) { 1650b57cec5SDimitry Andric switch (Opc) { 1660b57cec5SDimitry Andric case TargetOpcode::G_LOAD: 1670b57cec5SDimitry Andric case TargetOpcode::G_STORE: 1680b57cec5SDimitry Andric case TargetOpcode::G_PHI: 1690b57cec5SDimitry Andric case TargetOpcode::G_SELECT: 1708bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: 1715ffd83dbSDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: 1725ffd83dbSDimitry Andric case TargetOpcode::G_MERGE_VALUES: 1730b57cec5SDimitry Andric return true; 1740b57cec5SDimitry Andric default: 1750b57cec5SDimitry Andric return false; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses( 1800b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) { 1810b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() && 1820b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n"); 1830b57cec5SDimitry Andric for (MachineInstr &UseMI : MRI.use_instructions(Reg)) { 1840b57cec5SDimitry Andric MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI); 1850b57cec5SDimitry Andric // Copy with many uses. 1860b57cec5SDimitry Andric if (NonCopyInstr->getOpcode() == TargetOpcode::COPY && 187bdd1243dSDimitry Andric !NonCopyInstr->getOperand(0).getReg().isPhysical()) 1880b57cec5SDimitry Andric addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI); 1890b57cec5SDimitry Andric else 1900b57cec5SDimitry Andric DefUses.push_back(skipCopiesOutgoing(&UseMI)); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( 1950b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) { 1960b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() && 1970b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n"); 1980b57cec5SDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(Reg); 1990b57cec5SDimitry Andric UseDefs.push_back(skipCopiesIncoming(DefMI)); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric MachineInstr * 2030b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing( 2040b57cec5SDimitry Andric MachineInstr *MI) const { 2050b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2060b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2070b57cec5SDimitry Andric MachineInstr *Ret = MI; 2080b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY && 209bdd1243dSDimitry Andric !Ret->getOperand(0).getReg().isPhysical() && 2100b57cec5SDimitry Andric MRI.hasOneUse(Ret->getOperand(0).getReg())) { 2110b57cec5SDimitry Andric Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg())); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric return Ret; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric MachineInstr * 2170b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming( 2180b57cec5SDimitry Andric MachineInstr *MI) const { 2190b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2200b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2210b57cec5SDimitry Andric MachineInstr *Ret = MI; 2220b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY && 223bdd1243dSDimitry Andric !Ret->getOperand(1).getReg().isPhysical()) 2240b57cec5SDimitry Andric Ret = MRI.getVRegDef(Ret->getOperand(1).getReg()); 2250b57cec5SDimitry Andric return Ret; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( 2290b57cec5SDimitry Andric const MachineInstr *MI) { 2300b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) && 2310b57cec5SDimitry Andric "Not implemented for non Ambiguous opcode.\n"); 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD) 2360b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_STORE) 2390b57cec5SDimitry Andric addUseDef(MI->getOperand(0).getReg(), MRI); 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_PHI) { 2420b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric for (unsigned i = 1; i < MI->getNumOperands(); i += 2) 2450b57cec5SDimitry Andric addUseDef(MI->getOperand(i).getReg(), MRI); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_SELECT) { 2490b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric addUseDef(MI->getOperand(2).getReg(), MRI); 2520b57cec5SDimitry Andric addUseDef(MI->getOperand(3).getReg(), MRI); 2530b57cec5SDimitry Andric } 2548bcb0991SDimitry Andric 2558bcb0991SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) 2568bcb0991SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2575ffd83dbSDimitry Andric 2585ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) 2595ffd83dbSDimitry Andric addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI); 2605ffd83dbSDimitry Andric 2615ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 2625ffd83dbSDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visit( 2665ffd83dbSDimitry Andric const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI, 2675ffd83dbSDimitry Andric InstType &AmbiguousTy) { 2680b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); 2690b57cec5SDimitry Andric if (wasVisited(MI)) 2700b57cec5SDimitry Andric return true; // InstType has already been determined for MI. 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric startVisit(MI); 2730b57cec5SDimitry Andric AmbiguousRegDefUseContainer DefUseContainer(MI); 2740b57cec5SDimitry Andric 2755ffd83dbSDimitry Andric if (isGprbTwoInstrUnalignedLoadOrStore(MI)) { 2765ffd83dbSDimitry Andric setTypes(MI, Integer); 2775ffd83dbSDimitry Andric return true; 2785ffd83dbSDimitry Andric } 2795ffd83dbSDimitry Andric 2805ffd83dbSDimitry Andric if (AmbiguousTy == InstType::Ambiguous && 2815ffd83dbSDimitry Andric (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES || 2825ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)) 2835ffd83dbSDimitry Andric AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge; 2845ffd83dbSDimitry Andric 2850b57cec5SDimitry Andric // Visit instructions where MI's DEF operands are USED. 2865ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy)) 2870b57cec5SDimitry Andric return true; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric // Visit instructions that DEFINE MI's USE operands. 2905ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy)) 2910b57cec5SDimitry Andric return true; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric // All MI's adjacent instructions, are ambiguous. 2940b57cec5SDimitry Andric if (!WaitingForTypeOfMI) { 2950b57cec5SDimitry Andric // This is chain of ambiguous instructions. 2965ffd83dbSDimitry Andric setTypes(MI, AmbiguousTy); 2970b57cec5SDimitry Andric return true; 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous 3000b57cec5SDimitry Andric // instructions or has no other adjacent instructions. Anyway InstType could 3010b57cec5SDimitry Andric // not be determined. There could be unexplored path from some of 3020b57cec5SDimitry Andric // WaitingForTypeOfMI's adjacent instructions to an instruction with only one 3030b57cec5SDimitry Andric // mapping available. 3040b57cec5SDimitry Andric // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue, 3050b57cec5SDimitry Andric // this way when WaitingForTypeOfMI figures out its InstType same InstType 3060b57cec5SDimitry Andric // will be assigned to all instructions in this branch. 3070b57cec5SDimitry Andric addToWaitingQueue(WaitingForTypeOfMI, MI); 3080b57cec5SDimitry Andric return false; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( 3120b57cec5SDimitry Andric const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, 3135ffd83dbSDimitry Andric bool isDefUse, InstType &AmbiguousTy) { 3140b57cec5SDimitry Andric while (!AdjacentInstrs.empty()) { 3150b57cec5SDimitry Andric MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) 3180b57cec5SDimitry Andric : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { 3190b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint); 3200b57cec5SDimitry Andric return true; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric // Determine InstType from register bank of phys register that is 3240b57cec5SDimitry Andric // 'isDefUse ? def : use' of this copy. 3250b57cec5SDimitry Andric if (AdjMI->getOpcode() == TargetOpcode::COPY) { 3260b57cec5SDimitry Andric setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); 3270b57cec5SDimitry Andric return true; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3305ffd83dbSDimitry Andric // Defaults to integer instruction. Small registers in G_MERGE (uses) and 3315ffd83dbSDimitry Andric // G_UNMERGE (defs) will always be gprb. 3325ffd83dbSDimitry Andric if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) || 3335ffd83dbSDimitry Andric (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) || 3345ffd83dbSDimitry Andric !isAmbiguous(AdjMI->getOpcode())) { 3350b57cec5SDimitry Andric setTypes(MI, InstType::Integer); 3360b57cec5SDimitry Andric return true; 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric // When AdjMI was visited first, MI has to continue to explore remaining 3400b57cec5SDimitry Andric // adjacent instructions and determine InstType without visiting AdjMI. 3410b57cec5SDimitry Andric if (!wasVisited(AdjMI) || 3420b57cec5SDimitry Andric getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) { 3435ffd83dbSDimitry Andric if (visit(AdjMI, MI, AmbiguousTy)) { 3440b57cec5SDimitry Andric // InstType is successfully determined and is same as for AdjMI. 3450b57cec5SDimitry Andric setTypes(MI, getRecordedTypeForInstr(AdjMI)); 3460b57cec5SDimitry Andric return true; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric return false; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, 3540b57cec5SDimitry Andric InstType InstTy) { 3550b57cec5SDimitry Andric changeRecordedTypeForInstr(MI, InstTy); 3560b57cec5SDimitry Andric for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) { 3570b57cec5SDimitry Andric setTypes(WaitingInstr, InstTy); 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( 3620b57cec5SDimitry Andric const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { 363bdd1243dSDimitry Andric assert((CopyInst->getOperand(Op).getReg().isPhysical()) && 3640b57cec5SDimitry Andric "Copies of non physical registers should not be considered here.\n"); 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric const MachineFunction &MF = *CopyInst->getMF(); 3670b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 3680b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 3690b57cec5SDimitry Andric const RegisterBankInfo &RBI = 3700b57cec5SDimitry Andric *CopyInst->getMF()->getSubtarget().getRegBankInfo(); 3710b57cec5SDimitry Andric const RegisterBank *Bank = 3720b57cec5SDimitry Andric RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric if (Bank == &Mips::FPRBRegBank) 3750b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint); 3760b57cec5SDimitry Andric else if (Bank == &Mips::GPRBRegBank) 3770b57cec5SDimitry Andric setTypes(MI, InstType::Integer); 3780b57cec5SDimitry Andric else 3790b57cec5SDimitry Andric llvm_unreachable("Unsupported register bank.\n"); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric MipsRegisterBankInfo::InstType 3830b57cec5SDimitry Andric MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { 3845ffd83dbSDimitry Andric InstType DefaultAmbiguousType = InstType::Ambiguous; 3855ffd83dbSDimitry Andric visit(MI, nullptr, DefaultAmbiguousType); 3860b57cec5SDimitry Andric return getRecordedTypeForInstr(MI); 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( 3900b57cec5SDimitry Andric llvm::StringRef FunctionName) { 3910b57cec5SDimitry Andric if (MFName != FunctionName) { 3925ffd83dbSDimitry Andric MFName = std::string(FunctionName); 3930b57cec5SDimitry Andric WaitingQueues.clear(); 3940b57cec5SDimitry Andric Types.clear(); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3988bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping * 3998bcb0991SDimitry Andric getMSAMapping(const MachineFunction &MF) { 40081ad6265SDimitry Andric assert(MF.getSubtarget<MipsSubtarget>().hasMSA() && 4018bcb0991SDimitry Andric "MSA mapping not available on target without MSA."); 4028bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::MSAIdx]; 4038bcb0991SDimitry Andric } 4048bcb0991SDimitry Andric 4058bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) { 4068bcb0991SDimitry Andric return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 4078bcb0991SDimitry Andric : &Mips::ValueMappings[Mips::DPRIdx]; 4088bcb0991SDimitry Andric } 4098bcb0991SDimitry Andric 4108bcb0991SDimitry Andric static const unsigned CustomMappingID = 1; 4118bcb0991SDimitry Andric 4128bcb0991SDimitry Andric // Only 64 bit mapping is available in fprb and will be marked as custom, i.e. 4138bcb0991SDimitry Andric // will be split into two 32 bit registers in gprb. 4148bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping * 4158bcb0991SDimitry Andric getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) { 4168bcb0991SDimitry Andric if (Size == 32) 4178bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::GPRIdx]; 4188bcb0991SDimitry Andric 4198bcb0991SDimitry Andric MappingID = CustomMappingID; 4208bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::DPRIdx]; 4218bcb0991SDimitry Andric } 4228bcb0991SDimitry Andric 4230b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping & 4240b57cec5SDimitry Andric MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric static TypeInfoForMF TI; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric // Reset TI internal data when MF changes. 4290b57cec5SDimitry Andric TI.cleanupIfNewFunction(MI.getMF()->getName()); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 4320b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 4330b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric if (MI.getOpcode() != TargetOpcode::G_PHI) { 4360b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &Mapping = 4370b57cec5SDimitry Andric getInstrMappingImpl(MI); 4380b57cec5SDimitry Andric if (Mapping.isValid()) 4390b57cec5SDimitry Andric return Mapping; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric using namespace TargetOpcode; 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric unsigned NumOperands = MI.getNumOperands(); 4450b57cec5SDimitry Andric const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4460b57cec5SDimitry Andric unsigned MappingID = DefaultMappingID; 4478bcb0991SDimitry Andric 4488bcb0991SDimitry Andric // Check if LLT sizes match sizes of available register banks. 4498bcb0991SDimitry Andric for (const MachineOperand &Op : MI.operands()) { 4508bcb0991SDimitry Andric if (Op.isReg()) { 4518bcb0991SDimitry Andric LLT RegTy = MRI.getType(Op.getReg()); 4528bcb0991SDimitry Andric 4538bcb0991SDimitry Andric if (RegTy.isScalar() && 4548bcb0991SDimitry Andric (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64)) 4558bcb0991SDimitry Andric return getInvalidInstructionMapping(); 4568bcb0991SDimitry Andric 4578bcb0991SDimitry Andric if (RegTy.isVector() && RegTy.getSizeInBits() != 128) 4588bcb0991SDimitry Andric return getInvalidInstructionMapping(); 4598bcb0991SDimitry Andric } 4608bcb0991SDimitry Andric } 4618bcb0991SDimitry Andric 4628bcb0991SDimitry Andric const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg()); 4638bcb0991SDimitry Andric unsigned Op0Size = Op0Ty.getSizeInBits(); 4648bcb0991SDimitry Andric InstType InstTy = InstType::Integer; 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric switch (Opc) { 4670b57cec5SDimitry Andric case G_TRUNC: 4680b57cec5SDimitry Andric case G_UMULH: 4690b57cec5SDimitry Andric case G_ZEXTLOAD: 4700b57cec5SDimitry Andric case G_SEXTLOAD: 471480093f4SDimitry Andric case G_PTR_ADD: 4728bcb0991SDimitry Andric case G_INTTOPTR: 4738bcb0991SDimitry Andric case G_PTRTOINT: 4740b57cec5SDimitry Andric case G_AND: 4750b57cec5SDimitry Andric case G_OR: 4760b57cec5SDimitry Andric case G_XOR: 4770b57cec5SDimitry Andric case G_SHL: 4780b57cec5SDimitry Andric case G_ASHR: 4790b57cec5SDimitry Andric case G_LSHR: 4808bcb0991SDimitry Andric case G_BRINDIRECT: 4818bcb0991SDimitry Andric case G_VASTART: 482480093f4SDimitry Andric case G_BSWAP: 4835ffd83dbSDimitry Andric case G_CTLZ: 4840b57cec5SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4850b57cec5SDimitry Andric break; 4868bcb0991SDimitry Andric case G_ADD: 487480093f4SDimitry Andric case G_SUB: 488480093f4SDimitry Andric case G_MUL: 489480093f4SDimitry Andric case G_SDIV: 490480093f4SDimitry Andric case G_SREM: 491480093f4SDimitry Andric case G_UDIV: 492480093f4SDimitry Andric case G_UREM: 4938bcb0991SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4948bcb0991SDimitry Andric if (Op0Size == 128) 4958bcb0991SDimitry Andric OperandsMapping = getMSAMapping(MF); 4968bcb0991SDimitry Andric break; 4978bcb0991SDimitry Andric case G_STORE: 4985ffd83dbSDimitry Andric case G_LOAD: { 4998bcb0991SDimitry Andric if (Op0Size == 128) { 5008bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 5018bcb0991SDimitry Andric {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]}); 5028bcb0991SDimitry Andric break; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5058bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5068bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI); 5078bcb0991SDimitry Andric 5085ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) || 5095ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) { 5108bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 5118bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]}); 5125ffd83dbSDimitry Andric } else { 5135ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5145ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) || 5155ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5165ffd83dbSDimitry Andric "Unexpected Inst type"); 5170b57cec5SDimitry Andric OperandsMapping = 5188bcb0991SDimitry Andric getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID), 5190b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 5205ffd83dbSDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric break; 5235ffd83dbSDimitry Andric } 5245ffd83dbSDimitry Andric case G_PHI: { 5258bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5260b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI); 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric // PHI is copylike and should have one regbank in mapping for def register. 5295ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) { 5300b57cec5SDimitry Andric OperandsMapping = 5310b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]}); 5325ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI); 5330b57cec5SDimitry Andric return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping, 5340b57cec5SDimitry Andric /*NumOperands=*/1); 5350b57cec5SDimitry Andric } 5365ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5375ffd83dbSDimitry Andric isFloatingPoint_32or64(InstTy, Op0Size) || 5385ffd83dbSDimitry Andric isAmbiguous_32or64(InstTy, Op0Size)) && 5395ffd83dbSDimitry Andric "Unexpected Inst type"); 5400b57cec5SDimitry Andric // Use default handling for PHI, i.e. set reg bank of def operand to match 5410b57cec5SDimitry Andric // register banks of use operands. 5428bcb0991SDimitry Andric return getInstrMappingImpl(MI); 5435ffd83dbSDimitry Andric } 5440b57cec5SDimitry Andric case G_SELECT: { 5458bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5460b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI); 5475ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) || 5485ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) { 5498bcb0991SDimitry Andric const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size); 5500b57cec5SDimitry Andric OperandsMapping = getOperandsMapping( 5510b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 5520b57cec5SDimitry Andric break; 5538bcb0991SDimitry Andric } else { 5545ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5555ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) || 5565ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5575ffd83dbSDimitry Andric "Unexpected Inst type"); 5580b57cec5SDimitry Andric const RegisterBankInfo::ValueMapping *Bank = 5598bcb0991SDimitry Andric getGprbOrCustomMapping(Op0Size, MappingID); 5600b57cec5SDimitry Andric OperandsMapping = getOperandsMapping( 5610b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric break; 5640b57cec5SDimitry Andric } 5655ffd83dbSDimitry Andric case G_IMPLICIT_DEF: { 5668bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5678bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI); 5688bcb0991SDimitry Andric 5695ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size)) 5708bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size); 5715ffd83dbSDimitry Andric else { 5725ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5735ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5745ffd83dbSDimitry Andric "Unexpected Inst type"); 5758bcb0991SDimitry Andric OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID); 5765ffd83dbSDimitry Andric } 5775ffd83dbSDimitry Andric } break; 5785ffd83dbSDimitry Andric case G_UNMERGE_VALUES: { 5795ffd83dbSDimitry Andric assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES"); 5805ffd83dbSDimitry Andric unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 5815ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI); 5825ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) || 5835ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op3Size)) && 5845ffd83dbSDimitry Andric "Unexpected Inst type"); 5850b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], 5860b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 5870b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]}); 5885ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size)) 5890b57cec5SDimitry Andric MappingID = CustomMappingID; 5900b57cec5SDimitry Andric break; 5915ffd83dbSDimitry Andric } 5925ffd83dbSDimitry Andric case G_MERGE_VALUES: { 5935ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI); 5945ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) || 5955ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op0Size)) && 5965ffd83dbSDimitry Andric "Unexpected Inst type"); 5970b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 5980b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 5990b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6005ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) 6010b57cec5SDimitry Andric MappingID = CustomMappingID; 6020b57cec5SDimitry Andric break; 6035ffd83dbSDimitry Andric } 6040b57cec5SDimitry Andric case G_FADD: 6050b57cec5SDimitry Andric case G_FSUB: 6060b57cec5SDimitry Andric case G_FMUL: 6070b57cec5SDimitry Andric case G_FDIV: 6080b57cec5SDimitry Andric case G_FABS: 6098bcb0991SDimitry Andric case G_FSQRT: 6108bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size); 611480093f4SDimitry Andric if (Op0Size == 128) 612480093f4SDimitry Andric OperandsMapping = getMSAMapping(MF); 6130b57cec5SDimitry Andric break; 6148bcb0991SDimitry Andric case G_FCONSTANT: 6158bcb0991SDimitry Andric OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr}); 6160b57cec5SDimitry Andric break; 6170b57cec5SDimitry Andric case G_FCMP: { 6188bcb0991SDimitry Andric unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 6190b57cec5SDimitry Andric OperandsMapping = 6200b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6218bcb0991SDimitry Andric getFprbMapping(Op2Size), getFprbMapping(Op2Size)}); 6220b57cec5SDimitry Andric break; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric case G_FPEXT: 6250b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 6260b57cec5SDimitry Andric &Mips::ValueMappings[Mips::SPRIdx]}); 6270b57cec5SDimitry Andric break; 6280b57cec5SDimitry Andric case G_FPTRUNC: 6290b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], 6300b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]}); 6310b57cec5SDimitry Andric break; 6320b57cec5SDimitry Andric case G_FPTOSI: { 6338bcb0991SDimitry Andric assert((Op0Size == 32) && "Unsupported integer size"); 6340b57cec5SDimitry Andric unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 6358bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 6368bcb0991SDimitry Andric {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)}); 6378bcb0991SDimitry Andric break; 6388bcb0991SDimitry Andric } 6398bcb0991SDimitry Andric case G_SITOFP: 6408bcb0991SDimitry Andric assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) && 6410b57cec5SDimitry Andric "Unsupported integer size"); 6428bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 6438bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]}); 6440b57cec5SDimitry Andric break; 6450b57cec5SDimitry Andric case G_CONSTANT: 6460b57cec5SDimitry Andric case G_FRAME_INDEX: 6470b57cec5SDimitry Andric case G_GLOBAL_VALUE: 6488bcb0991SDimitry Andric case G_JUMP_TABLE: 6490b57cec5SDimitry Andric case G_BRCOND: 6500b57cec5SDimitry Andric OperandsMapping = 6510b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); 6520b57cec5SDimitry Andric break; 6538bcb0991SDimitry Andric case G_BRJT: 6548bcb0991SDimitry Andric OperandsMapping = 6558bcb0991SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6568bcb0991SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6578bcb0991SDimitry Andric break; 6580b57cec5SDimitry Andric case G_ICMP: 6590b57cec5SDimitry Andric OperandsMapping = 6600b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6610b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 6620b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6630b57cec5SDimitry Andric break; 6640b57cec5SDimitry Andric default: 6650b57cec5SDimitry Andric return getInvalidInstructionMapping(); 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 6685ffd83dbSDimitry Andric if (MappingID == CustomMappingID) 6695ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI); 6700b57cec5SDimitry Andric return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, 6710b57cec5SDimitry Andric NumOperands); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric using InstListTy = GISelWorkList<4>; 6750b57cec5SDimitry Andric namespace { 6760b57cec5SDimitry Andric class InstManager : public GISelChangeObserver { 6770b57cec5SDimitry Andric InstListTy &InstList; 678*5f757f3fSDimitry Andric MachineIRBuilder &B; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric public: 681*5f757f3fSDimitry Andric InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) { 682*5f757f3fSDimitry Andric assert(!B.isObservingChanges()); 683*5f757f3fSDimitry Andric B.setChangeObserver(*this); 684*5f757f3fSDimitry Andric } 685*5f757f3fSDimitry Andric 686*5f757f3fSDimitry Andric ~InstManager() { B.stopObservingChanges(); } 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } 6890b57cec5SDimitry Andric void erasingInstr(MachineInstr &MI) override {} 6900b57cec5SDimitry Andric void changingInstr(MachineInstr &MI) override {} 6910b57cec5SDimitry Andric void changedInstr(MachineInstr &MI) override {} 6920b57cec5SDimitry Andric }; 6930b57cec5SDimitry Andric } // end anonymous namespace 6940b57cec5SDimitry Andric 6958bcb0991SDimitry Andric void MipsRegisterBankInfo::setRegBank(MachineInstr &MI, 6968bcb0991SDimitry Andric MachineRegisterInfo &MRI) const { 6978bcb0991SDimitry Andric Register Dest = MI.getOperand(0).getReg(); 6988bcb0991SDimitry Andric switch (MI.getOpcode()) { 6998bcb0991SDimitry Andric case TargetOpcode::G_STORE: 7008bcb0991SDimitry Andric // No def operands, skip this instruction. 7018bcb0991SDimitry Andric break; 7028bcb0991SDimitry Andric case TargetOpcode::G_CONSTANT: 7038bcb0991SDimitry Andric case TargetOpcode::G_LOAD: 7048bcb0991SDimitry Andric case TargetOpcode::G_SELECT: 7058bcb0991SDimitry Andric case TargetOpcode::G_PHI: 7068bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 7078bcb0991SDimitry Andric assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type."); 7088bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); 7098bcb0991SDimitry Andric break; 7108bcb0991SDimitry Andric } 711480093f4SDimitry Andric case TargetOpcode::G_PTR_ADD: { 7128bcb0991SDimitry Andric assert(MRI.getType(Dest).isPointer() && "Unexpected operand type."); 7138bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); 7148bcb0991SDimitry Andric break; 7158bcb0991SDimitry Andric } 7168bcb0991SDimitry Andric default: 7178bcb0991SDimitry Andric llvm_unreachable("Unexpected opcode."); 7188bcb0991SDimitry Andric } 7198bcb0991SDimitry Andric } 7208bcb0991SDimitry Andric 7218bcb0991SDimitry Andric static void 7228bcb0991SDimitry Andric combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner, 723fe6060f1SDimitry Andric GUnmerge &MI, GISelChangeObserver &Observer) { 724480093f4SDimitry Andric SmallVector<Register, 4> UpdatedDefs; 7258bcb0991SDimitry Andric SmallVector<MachineInstr *, 2> DeadInstrs; 726fe6060f1SDimitry Andric ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs, 727fe6060f1SDimitry Andric UpdatedDefs, Observer); 7288bcb0991SDimitry Andric for (MachineInstr *DeadMI : DeadInstrs) 7298bcb0991SDimitry Andric DeadMI->eraseFromParent(); 7308bcb0991SDimitry Andric } 7318bcb0991SDimitry Andric 7320b57cec5SDimitry Andric void MipsRegisterBankInfo::applyMappingImpl( 733*5f757f3fSDimitry Andric MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const { 7340b57cec5SDimitry Andric MachineInstr &MI = OpdMapper.getMI(); 735*5f757f3fSDimitry Andric Builder.setInstrAndDebugLoc(MI); 736*5f757f3fSDimitry Andric 7370b57cec5SDimitry Andric InstListTy NewInstrs; 7380b57cec5SDimitry Andric MachineFunction *MF = MI.getMF(); 7390b57cec5SDimitry Andric MachineRegisterInfo &MRI = OpdMapper.getMRI(); 7408bcb0991SDimitry Andric const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo(); 7410b57cec5SDimitry Andric 742*5f757f3fSDimitry Andric InstManager NewInstrObserver(Builder, NewInstrs); 743*5f757f3fSDimitry Andric LegalizerHelper Helper(*MF, NewInstrObserver, Builder); 744*5f757f3fSDimitry Andric LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo); 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric switch (MI.getOpcode()) { 7470b57cec5SDimitry Andric case TargetOpcode::G_LOAD: 7480b57cec5SDimitry Andric case TargetOpcode::G_STORE: 7490b57cec5SDimitry Andric case TargetOpcode::G_PHI: 7508bcb0991SDimitry Andric case TargetOpcode::G_SELECT: 7518bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 7520b57cec5SDimitry Andric Helper.narrowScalar(MI, 0, LLT::scalar(32)); 7530b57cec5SDimitry Andric // Handle new instructions. 7540b57cec5SDimitry Andric while (!NewInstrs.empty()) { 7550b57cec5SDimitry Andric MachineInstr *NewMI = NewInstrs.pop_back_val(); 7560b57cec5SDimitry Andric // This is new G_UNMERGE that was created during narrowScalar and will 7570b57cec5SDimitry Andric // not be considered for regbank selection. RegBankSelect for mips 7580b57cec5SDimitry Andric // visits/makes corresponding G_MERGE first. Combine them here. 759fe6060f1SDimitry Andric if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI)) 760fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver); 7610b57cec5SDimitry Andric // This G_MERGE will be combined away when its corresponding G_UNMERGE 7620b57cec5SDimitry Andric // gets regBankSelected. 7630b57cec5SDimitry Andric else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 7640b57cec5SDimitry Andric continue; 7650b57cec5SDimitry Andric else 7668bcb0991SDimitry Andric // Manually set register banks for def operands to 32 bit gprb. 7678bcb0991SDimitry Andric setRegBank(*NewMI, MRI); 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric return; 7700b57cec5SDimitry Andric } 7718bcb0991SDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: 772fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI), 773fe6060f1SDimitry Andric NewInstrObserver); 7740b57cec5SDimitry Andric return; 7750b57cec5SDimitry Andric default: 7760b57cec5SDimitry Andric break; 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric return applyDefaultMapping(OpdMapper); 7800b57cec5SDimitry Andric } 781