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 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 use operands are floating point registers. 1080b57cec5SDimitry Andric // Def operands are general purpose. 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. 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 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 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 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 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 * 1840b57cec5SDimitry 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 * 1980b57cec5SDimitry 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 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 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 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 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 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 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 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 * 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 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 * 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 & 4050b57cec5SDimitry 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: 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 6675f757f3fSDimitry Andric ~InstManager() { B.stopObservingChanges(); } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } 6700b57cec5SDimitry Andric void erasingInstr(MachineInstr &MI) override {} 6710b57cec5SDimitry Andric void changingInstr(MachineInstr &MI) override {} 6720b57cec5SDimitry Andric void changedInstr(MachineInstr &MI) override {} 6730b57cec5SDimitry Andric }; 6740b57cec5SDimitry Andric } // end anonymous namespace 6750b57cec5SDimitry Andric 6768bcb0991SDimitry 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 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 7130b57cec5SDimitry 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