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 350b57cec5SDimitry Andric 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 500b57cec5SDimitry Andric 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 760b57cec5SDimitry Andric MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) 770b57cec5SDimitry Andric : MipsGenRegisterBankInfo() {} 780b57cec5SDimitry Andric 79480093f4SDimitry Andric const RegisterBank & 80480093f4SDimitry Andric MipsRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 81480093f4SDimitry Andric LLT) const { 820b57cec5SDimitry Andric using namespace Mips; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric switch (RC.getID()) { 850b57cec5SDimitry Andric case Mips::GPR32RegClassID: 860b57cec5SDimitry Andric case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: 870b57cec5SDimitry Andric case Mips::GPRMM16MovePPairFirstRegClassID: 880b57cec5SDimitry Andric case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID: 890b57cec5SDimitry Andric case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: 900b57cec5SDimitry Andric case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID: 910b57cec5SDimitry Andric case Mips::SP32RegClassID: 920b57cec5SDimitry Andric case Mips::GP32RegClassID: 930b57cec5SDimitry Andric return getRegBank(Mips::GPRBRegBankID); 940b57cec5SDimitry Andric case Mips::FGRCCRegClassID: 950b57cec5SDimitry Andric case Mips::FGR32RegClassID: 960b57cec5SDimitry Andric case Mips::FGR64RegClassID: 970b57cec5SDimitry Andric case Mips::AFGR64RegClassID: 988bcb0991SDimitry Andric case Mips::MSA128BRegClassID: 998bcb0991SDimitry Andric case Mips::MSA128HRegClassID: 1008bcb0991SDimitry Andric case Mips::MSA128WRegClassID: 1018bcb0991SDimitry Andric case Mips::MSA128DRegClassID: 1020b57cec5SDimitry Andric return getRegBank(Mips::FPRBRegBankID); 1030b57cec5SDimitry Andric default: 1040b57cec5SDimitry Andric llvm_unreachable("Register class not supported"); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric // Instructions where all register operands are floating point. 1090b57cec5SDimitry Andric static bool isFloatingPointOpcode(unsigned Opc) { 1100b57cec5SDimitry Andric switch (Opc) { 1110b57cec5SDimitry Andric case TargetOpcode::G_FCONSTANT: 1120b57cec5SDimitry Andric case TargetOpcode::G_FADD: 1130b57cec5SDimitry Andric case TargetOpcode::G_FSUB: 1140b57cec5SDimitry Andric case TargetOpcode::G_FMUL: 1150b57cec5SDimitry Andric case TargetOpcode::G_FDIV: 1160b57cec5SDimitry Andric case TargetOpcode::G_FABS: 1170b57cec5SDimitry Andric case TargetOpcode::G_FSQRT: 1180b57cec5SDimitry Andric case TargetOpcode::G_FCEIL: 1190b57cec5SDimitry Andric case TargetOpcode::G_FFLOOR: 1200b57cec5SDimitry Andric case TargetOpcode::G_FPEXT: 1210b57cec5SDimitry Andric case TargetOpcode::G_FPTRUNC: 1220b57cec5SDimitry Andric return true; 1230b57cec5SDimitry Andric default: 1240b57cec5SDimitry Andric return false; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // Instructions where use operands are floating point registers. 1290b57cec5SDimitry Andric // Def operands are general purpose. 1300b57cec5SDimitry Andric static bool isFloatingPointOpcodeUse(unsigned Opc) { 1310b57cec5SDimitry Andric switch (Opc) { 1320b57cec5SDimitry Andric case TargetOpcode::G_FPTOSI: 1330b57cec5SDimitry Andric case TargetOpcode::G_FPTOUI: 1340b57cec5SDimitry Andric case TargetOpcode::G_FCMP: 1350b57cec5SDimitry Andric return true; 1360b57cec5SDimitry Andric default: 1370b57cec5SDimitry Andric return isFloatingPointOpcode(Opc); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // Instructions where def operands are floating point registers. 1420b57cec5SDimitry Andric // Use operands are general purpose. 1430b57cec5SDimitry Andric static bool isFloatingPointOpcodeDef(unsigned Opc) { 1440b57cec5SDimitry Andric switch (Opc) { 1450b57cec5SDimitry Andric case TargetOpcode::G_SITOFP: 1460b57cec5SDimitry Andric case TargetOpcode::G_UITOFP: 1470b57cec5SDimitry Andric return true; 1480b57cec5SDimitry Andric default: 1490b57cec5SDimitry Andric return isFloatingPointOpcode(Opc); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1535ffd83dbSDimitry Andric static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) { 1545ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD || 1555ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_STORE) { 1565ffd83dbSDimitry Andric auto MMO = *MI->memoperands_begin(); 1575ffd83dbSDimitry Andric const MipsSubtarget &STI = 1585ffd83dbSDimitry Andric static_cast<const MipsSubtarget &>(MI->getMF()->getSubtarget()); 1595ffd83dbSDimitry Andric if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() && 1605ffd83dbSDimitry Andric MMO->getAlign() < MMO->getSize())) 1615ffd83dbSDimitry Andric return true; 1625ffd83dbSDimitry Andric } 1635ffd83dbSDimitry Andric return false; 1645ffd83dbSDimitry Andric } 1655ffd83dbSDimitry Andric 1660b57cec5SDimitry Andric static bool isAmbiguous(unsigned Opc) { 1670b57cec5SDimitry Andric switch (Opc) { 1680b57cec5SDimitry Andric case TargetOpcode::G_LOAD: 1690b57cec5SDimitry Andric case TargetOpcode::G_STORE: 1700b57cec5SDimitry Andric case TargetOpcode::G_PHI: 1710b57cec5SDimitry Andric case TargetOpcode::G_SELECT: 1728bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: 1735ffd83dbSDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: 1745ffd83dbSDimitry Andric case TargetOpcode::G_MERGE_VALUES: 1750b57cec5SDimitry Andric return true; 1760b57cec5SDimitry Andric default: 1770b57cec5SDimitry Andric return false; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses( 1820b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) { 1830b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() && 1840b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n"); 1850b57cec5SDimitry Andric for (MachineInstr &UseMI : MRI.use_instructions(Reg)) { 1860b57cec5SDimitry Andric MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI); 1870b57cec5SDimitry Andric // Copy with many uses. 1880b57cec5SDimitry Andric if (NonCopyInstr->getOpcode() == TargetOpcode::COPY && 1898bcb0991SDimitry Andric !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg())) 1900b57cec5SDimitry Andric addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI); 1910b57cec5SDimitry Andric else 1920b57cec5SDimitry Andric DefUses.push_back(skipCopiesOutgoing(&UseMI)); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( 1970b57cec5SDimitry Andric Register Reg, const MachineRegisterInfo &MRI) { 1980b57cec5SDimitry Andric assert(!MRI.getType(Reg).isPointer() && 1990b57cec5SDimitry Andric "Pointers are gprb, they should not be considered as ambiguous.\n"); 2000b57cec5SDimitry Andric MachineInstr *DefMI = MRI.getVRegDef(Reg); 2010b57cec5SDimitry Andric UseDefs.push_back(skipCopiesIncoming(DefMI)); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric MachineInstr * 2050b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing( 2060b57cec5SDimitry Andric MachineInstr *MI) const { 2070b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2080b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2090b57cec5SDimitry Andric MachineInstr *Ret = MI; 2100b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY && 2118bcb0991SDimitry Andric !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) && 2120b57cec5SDimitry Andric MRI.hasOneUse(Ret->getOperand(0).getReg())) { 2130b57cec5SDimitry Andric Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg())); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric return Ret; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric MachineInstr * 2190b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming( 2200b57cec5SDimitry Andric MachineInstr *MI) const { 2210b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2220b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2230b57cec5SDimitry Andric MachineInstr *Ret = MI; 2240b57cec5SDimitry Andric while (Ret->getOpcode() == TargetOpcode::COPY && 2258bcb0991SDimitry Andric !Register::isPhysicalRegister(Ret->getOperand(1).getReg())) 2260b57cec5SDimitry Andric Ret = MRI.getVRegDef(Ret->getOperand(1).getReg()); 2270b57cec5SDimitry Andric return Ret; 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( 2310b57cec5SDimitry Andric const MachineInstr *MI) { 2320b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) && 2330b57cec5SDimitry Andric "Not implemented for non Ambiguous opcode.\n"); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_LOAD) 2380b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_STORE) 2410b57cec5SDimitry Andric addUseDef(MI->getOperand(0).getReg(), MRI); 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_PHI) { 2440b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric for (unsigned i = 1; i < MI->getNumOperands(); i += 2) 2470b57cec5SDimitry Andric addUseDef(MI->getOperand(i).getReg(), MRI); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_SELECT) { 2510b57cec5SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric addUseDef(MI->getOperand(2).getReg(), MRI); 2540b57cec5SDimitry Andric addUseDef(MI->getOperand(3).getReg(), MRI); 2550b57cec5SDimitry Andric } 2568bcb0991SDimitry Andric 2578bcb0991SDimitry Andric if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF) 2588bcb0991SDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2595ffd83dbSDimitry Andric 2605ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) 2615ffd83dbSDimitry Andric addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI); 2625ffd83dbSDimitry Andric 2635ffd83dbSDimitry Andric if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 2645ffd83dbSDimitry Andric addDefUses(MI->getOperand(0).getReg(), MRI); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visit( 2685ffd83dbSDimitry Andric const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI, 2695ffd83dbSDimitry Andric InstType &AmbiguousTy) { 2700b57cec5SDimitry Andric assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); 2710b57cec5SDimitry Andric if (wasVisited(MI)) 2720b57cec5SDimitry Andric return true; // InstType has already been determined for MI. 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric startVisit(MI); 2750b57cec5SDimitry Andric AmbiguousRegDefUseContainer DefUseContainer(MI); 2760b57cec5SDimitry Andric 2775ffd83dbSDimitry Andric if (isGprbTwoInstrUnalignedLoadOrStore(MI)) { 2785ffd83dbSDimitry Andric setTypes(MI, Integer); 2795ffd83dbSDimitry Andric return true; 2805ffd83dbSDimitry Andric } 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric if (AmbiguousTy == InstType::Ambiguous && 2835ffd83dbSDimitry Andric (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES || 2845ffd83dbSDimitry Andric MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)) 2855ffd83dbSDimitry Andric AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge; 2865ffd83dbSDimitry Andric 2870b57cec5SDimitry Andric // Visit instructions where MI's DEF operands are USED. 2885ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy)) 2890b57cec5SDimitry Andric return true; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // Visit instructions that DEFINE MI's USE operands. 2925ffd83dbSDimitry Andric if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy)) 2930b57cec5SDimitry Andric return true; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // All MI's adjacent instructions, are ambiguous. 2960b57cec5SDimitry Andric if (!WaitingForTypeOfMI) { 2970b57cec5SDimitry Andric // This is chain of ambiguous instructions. 2985ffd83dbSDimitry Andric setTypes(MI, AmbiguousTy); 2990b57cec5SDimitry Andric return true; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous 3020b57cec5SDimitry Andric // instructions or has no other adjacent instructions. Anyway InstType could 3030b57cec5SDimitry Andric // not be determined. There could be unexplored path from some of 3040b57cec5SDimitry Andric // WaitingForTypeOfMI's adjacent instructions to an instruction with only one 3050b57cec5SDimitry Andric // mapping available. 3060b57cec5SDimitry Andric // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue, 3070b57cec5SDimitry Andric // this way when WaitingForTypeOfMI figures out its InstType same InstType 3080b57cec5SDimitry Andric // will be assigned to all instructions in this branch. 3090b57cec5SDimitry Andric addToWaitingQueue(WaitingForTypeOfMI, MI); 3100b57cec5SDimitry Andric return false; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( 3140b57cec5SDimitry Andric const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, 3155ffd83dbSDimitry Andric bool isDefUse, InstType &AmbiguousTy) { 3160b57cec5SDimitry Andric while (!AdjacentInstrs.empty()) { 3170b57cec5SDimitry Andric MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) 3200b57cec5SDimitry Andric : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { 3210b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint); 3220b57cec5SDimitry Andric return true; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric // Determine InstType from register bank of phys register that is 3260b57cec5SDimitry Andric // 'isDefUse ? def : use' of this copy. 3270b57cec5SDimitry Andric if (AdjMI->getOpcode() == TargetOpcode::COPY) { 3280b57cec5SDimitry Andric setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); 3290b57cec5SDimitry Andric return true; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3325ffd83dbSDimitry Andric // Defaults to integer instruction. Small registers in G_MERGE (uses) and 3335ffd83dbSDimitry Andric // G_UNMERGE (defs) will always be gprb. 3345ffd83dbSDimitry Andric if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) || 3355ffd83dbSDimitry Andric (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) || 3365ffd83dbSDimitry Andric !isAmbiguous(AdjMI->getOpcode())) { 3370b57cec5SDimitry Andric setTypes(MI, InstType::Integer); 3380b57cec5SDimitry Andric return true; 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric // When AdjMI was visited first, MI has to continue to explore remaining 3420b57cec5SDimitry Andric // adjacent instructions and determine InstType without visiting AdjMI. 3430b57cec5SDimitry Andric if (!wasVisited(AdjMI) || 3440b57cec5SDimitry Andric getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) { 3455ffd83dbSDimitry Andric if (visit(AdjMI, MI, AmbiguousTy)) { 3460b57cec5SDimitry Andric // InstType is successfully determined and is same as for AdjMI. 3470b57cec5SDimitry Andric setTypes(MI, getRecordedTypeForInstr(AdjMI)); 3480b57cec5SDimitry Andric return true; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric return false; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, 3560b57cec5SDimitry Andric InstType InstTy) { 3570b57cec5SDimitry Andric changeRecordedTypeForInstr(MI, InstTy); 3580b57cec5SDimitry Andric for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) { 3590b57cec5SDimitry Andric setTypes(WaitingInstr, InstTy); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( 3640b57cec5SDimitry Andric const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { 3658bcb0991SDimitry Andric assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) && 3660b57cec5SDimitry Andric "Copies of non physical registers should not be considered here.\n"); 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric const MachineFunction &MF = *CopyInst->getMF(); 3690b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 3700b57cec5SDimitry Andric const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 3710b57cec5SDimitry Andric const RegisterBankInfo &RBI = 3720b57cec5SDimitry Andric *CopyInst->getMF()->getSubtarget().getRegBankInfo(); 3730b57cec5SDimitry Andric const RegisterBank *Bank = 3740b57cec5SDimitry Andric RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric if (Bank == &Mips::FPRBRegBank) 3770b57cec5SDimitry Andric setTypes(MI, InstType::FloatingPoint); 3780b57cec5SDimitry Andric else if (Bank == &Mips::GPRBRegBank) 3790b57cec5SDimitry Andric setTypes(MI, InstType::Integer); 3800b57cec5SDimitry Andric else 3810b57cec5SDimitry Andric llvm_unreachable("Unsupported register bank.\n"); 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric MipsRegisterBankInfo::InstType 3850b57cec5SDimitry Andric MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { 3865ffd83dbSDimitry Andric InstType DefaultAmbiguousType = InstType::Ambiguous; 3875ffd83dbSDimitry Andric visit(MI, nullptr, DefaultAmbiguousType); 3880b57cec5SDimitry Andric return getRecordedTypeForInstr(MI); 3890b57cec5SDimitry Andric } 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( 3920b57cec5SDimitry Andric llvm::StringRef FunctionName) { 3930b57cec5SDimitry Andric if (MFName != FunctionName) { 3945ffd83dbSDimitry Andric MFName = std::string(FunctionName); 3950b57cec5SDimitry Andric WaitingQueues.clear(); 3960b57cec5SDimitry Andric Types.clear(); 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric } 3990b57cec5SDimitry Andric 4008bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping * 4018bcb0991SDimitry Andric getMSAMapping(const MachineFunction &MF) { 4028bcb0991SDimitry Andric assert(static_cast<const MipsSubtarget &>(MF.getSubtarget()).hasMSA() && 4038bcb0991SDimitry Andric "MSA mapping not available on target without MSA."); 4048bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::MSAIdx]; 4058bcb0991SDimitry Andric } 4068bcb0991SDimitry Andric 4078bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) { 4088bcb0991SDimitry Andric return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 4098bcb0991SDimitry Andric : &Mips::ValueMappings[Mips::DPRIdx]; 4108bcb0991SDimitry Andric } 4118bcb0991SDimitry Andric 4128bcb0991SDimitry Andric static const unsigned CustomMappingID = 1; 4138bcb0991SDimitry Andric 4148bcb0991SDimitry Andric // Only 64 bit mapping is available in fprb and will be marked as custom, i.e. 4158bcb0991SDimitry Andric // will be split into two 32 bit registers in gprb. 4168bcb0991SDimitry Andric static const MipsRegisterBankInfo::ValueMapping * 4178bcb0991SDimitry Andric getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) { 4188bcb0991SDimitry Andric if (Size == 32) 4198bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::GPRIdx]; 4208bcb0991SDimitry Andric 4218bcb0991SDimitry Andric MappingID = CustomMappingID; 4228bcb0991SDimitry Andric return &Mips::ValueMappings[Mips::DPRIdx]; 4238bcb0991SDimitry Andric } 4248bcb0991SDimitry Andric 4250b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping & 4260b57cec5SDimitry Andric MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric static TypeInfoForMF TI; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric // Reset TI internal data when MF changes. 4310b57cec5SDimitry Andric TI.cleanupIfNewFunction(MI.getMF()->getName()); 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric unsigned Opc = MI.getOpcode(); 4340b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 4350b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric if (MI.getOpcode() != TargetOpcode::G_PHI) { 4380b57cec5SDimitry Andric const RegisterBankInfo::InstructionMapping &Mapping = 4390b57cec5SDimitry Andric getInstrMappingImpl(MI); 4400b57cec5SDimitry Andric if (Mapping.isValid()) 4410b57cec5SDimitry Andric return Mapping; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric using namespace TargetOpcode; 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric unsigned NumOperands = MI.getNumOperands(); 4470b57cec5SDimitry Andric const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4480b57cec5SDimitry Andric unsigned MappingID = DefaultMappingID; 4498bcb0991SDimitry Andric 4508bcb0991SDimitry Andric // Check if LLT sizes match sizes of available register banks. 4518bcb0991SDimitry Andric for (const MachineOperand &Op : MI.operands()) { 4528bcb0991SDimitry Andric if (Op.isReg()) { 4538bcb0991SDimitry Andric LLT RegTy = MRI.getType(Op.getReg()); 4548bcb0991SDimitry Andric 4558bcb0991SDimitry Andric if (RegTy.isScalar() && 4568bcb0991SDimitry Andric (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64)) 4578bcb0991SDimitry Andric return getInvalidInstructionMapping(); 4588bcb0991SDimitry Andric 4598bcb0991SDimitry Andric if (RegTy.isVector() && RegTy.getSizeInBits() != 128) 4608bcb0991SDimitry Andric return getInvalidInstructionMapping(); 4618bcb0991SDimitry Andric } 4628bcb0991SDimitry Andric } 4638bcb0991SDimitry Andric 4648bcb0991SDimitry Andric const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg()); 4658bcb0991SDimitry Andric unsigned Op0Size = Op0Ty.getSizeInBits(); 4668bcb0991SDimitry Andric InstType InstTy = InstType::Integer; 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric switch (Opc) { 4690b57cec5SDimitry Andric case G_TRUNC: 4700b57cec5SDimitry Andric case G_UMULH: 4710b57cec5SDimitry Andric case G_ZEXTLOAD: 4720b57cec5SDimitry Andric case G_SEXTLOAD: 473480093f4SDimitry Andric case G_PTR_ADD: 4748bcb0991SDimitry Andric case G_INTTOPTR: 4758bcb0991SDimitry Andric case G_PTRTOINT: 4760b57cec5SDimitry Andric case G_AND: 4770b57cec5SDimitry Andric case G_OR: 4780b57cec5SDimitry Andric case G_XOR: 4790b57cec5SDimitry Andric case G_SHL: 4800b57cec5SDimitry Andric case G_ASHR: 4810b57cec5SDimitry Andric case G_LSHR: 4828bcb0991SDimitry Andric case G_BRINDIRECT: 4838bcb0991SDimitry Andric case G_VASTART: 484480093f4SDimitry Andric case G_BSWAP: 4855ffd83dbSDimitry Andric case G_CTLZ: 4860b57cec5SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4870b57cec5SDimitry Andric break; 4888bcb0991SDimitry Andric case G_ADD: 489480093f4SDimitry Andric case G_SUB: 490480093f4SDimitry Andric case G_MUL: 491480093f4SDimitry Andric case G_SDIV: 492480093f4SDimitry Andric case G_SREM: 493480093f4SDimitry Andric case G_UDIV: 494480093f4SDimitry Andric case G_UREM: 4958bcb0991SDimitry Andric OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 4968bcb0991SDimitry Andric if (Op0Size == 128) 4978bcb0991SDimitry Andric OperandsMapping = getMSAMapping(MF); 4988bcb0991SDimitry Andric break; 4998bcb0991SDimitry Andric case G_STORE: 5005ffd83dbSDimitry Andric case G_LOAD: { 5018bcb0991SDimitry Andric if (Op0Size == 128) { 5028bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 5038bcb0991SDimitry Andric {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]}); 5048bcb0991SDimitry Andric break; 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5078bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5088bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI); 5098bcb0991SDimitry Andric 5105ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) || 5115ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) { 5128bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 5138bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]}); 5145ffd83dbSDimitry Andric } else { 5155ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5165ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) || 5175ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5185ffd83dbSDimitry Andric "Unexpected Inst type"); 5190b57cec5SDimitry Andric OperandsMapping = 5208bcb0991SDimitry Andric getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID), 5210b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 5225ffd83dbSDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric break; 5255ffd83dbSDimitry Andric } 5265ffd83dbSDimitry Andric case G_PHI: { 5278bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5280b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI); 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric // PHI is copylike and should have one regbank in mapping for def register. 5315ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) { 5320b57cec5SDimitry Andric OperandsMapping = 5330b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]}); 5345ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI); 5350b57cec5SDimitry Andric return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping, 5360b57cec5SDimitry Andric /*NumOperands=*/1); 5370b57cec5SDimitry Andric } 5385ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5395ffd83dbSDimitry Andric isFloatingPoint_32or64(InstTy, Op0Size) || 5405ffd83dbSDimitry Andric isAmbiguous_32or64(InstTy, Op0Size)) && 5415ffd83dbSDimitry Andric "Unexpected Inst type"); 5420b57cec5SDimitry Andric // Use default handling for PHI, i.e. set reg bank of def operand to match 5430b57cec5SDimitry Andric // register banks of use operands. 5448bcb0991SDimitry Andric return getInstrMappingImpl(MI); 5455ffd83dbSDimitry Andric } 5460b57cec5SDimitry Andric case G_SELECT: { 5478bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5480b57cec5SDimitry Andric InstTy = TI.determineInstType(&MI); 5495ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size) || 5505ffd83dbSDimitry Andric isAmbiguous_64(InstTy, Op0Size)) { 5518bcb0991SDimitry Andric const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size); 5520b57cec5SDimitry Andric OperandsMapping = getOperandsMapping( 5530b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 5540b57cec5SDimitry Andric break; 5558bcb0991SDimitry Andric } else { 5565ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5575ffd83dbSDimitry Andric isAmbiguous_32(InstTy, Op0Size) || 5585ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5595ffd83dbSDimitry Andric "Unexpected Inst type"); 5600b57cec5SDimitry Andric const RegisterBankInfo::ValueMapping *Bank = 5618bcb0991SDimitry Andric getGprbOrCustomMapping(Op0Size, MappingID); 5620b57cec5SDimitry Andric OperandsMapping = getOperandsMapping( 5630b57cec5SDimitry Andric {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric break; 5660b57cec5SDimitry Andric } 5675ffd83dbSDimitry Andric case G_IMPLICIT_DEF: { 5688bcb0991SDimitry Andric if (!Op0Ty.isPointer()) 5698bcb0991SDimitry Andric InstTy = TI.determineInstType(&MI); 5708bcb0991SDimitry Andric 5715ffd83dbSDimitry Andric if (isFloatingPoint_32or64(InstTy, Op0Size)) 5728bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size); 5735ffd83dbSDimitry Andric else { 5745ffd83dbSDimitry Andric assert((isInteger_32(InstTy, Op0Size) || 5755ffd83dbSDimitry Andric isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) && 5765ffd83dbSDimitry Andric "Unexpected Inst type"); 5778bcb0991SDimitry Andric OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID); 5785ffd83dbSDimitry Andric } 5795ffd83dbSDimitry Andric } break; 5805ffd83dbSDimitry Andric case G_UNMERGE_VALUES: { 5815ffd83dbSDimitry Andric assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES"); 5825ffd83dbSDimitry Andric unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 5835ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI); 5845ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) || 5855ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op3Size)) && 5865ffd83dbSDimitry Andric "Unexpected Inst type"); 5870b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], 5880b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 5890b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]}); 5905ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size)) 5910b57cec5SDimitry Andric MappingID = CustomMappingID; 5920b57cec5SDimitry Andric break; 5935ffd83dbSDimitry Andric } 5945ffd83dbSDimitry Andric case G_MERGE_VALUES: { 5955ffd83dbSDimitry Andric InstTy = TI.determineInstType(&MI); 5965ffd83dbSDimitry Andric assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) || 5975ffd83dbSDimitry Andric isFloatingPoint_64(InstTy, Op0Size)) && 5985ffd83dbSDimitry Andric "Unexpected Inst type"); 5990b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 6000b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 6010b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6025ffd83dbSDimitry Andric if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) 6030b57cec5SDimitry Andric MappingID = CustomMappingID; 6040b57cec5SDimitry Andric break; 6055ffd83dbSDimitry Andric } 6060b57cec5SDimitry Andric case G_FADD: 6070b57cec5SDimitry Andric case G_FSUB: 6080b57cec5SDimitry Andric case G_FMUL: 6090b57cec5SDimitry Andric case G_FDIV: 6100b57cec5SDimitry Andric case G_FABS: 6118bcb0991SDimitry Andric case G_FSQRT: 6128bcb0991SDimitry Andric OperandsMapping = getFprbMapping(Op0Size); 613480093f4SDimitry Andric if (Op0Size == 128) 614480093f4SDimitry Andric OperandsMapping = getMSAMapping(MF); 6150b57cec5SDimitry Andric break; 6168bcb0991SDimitry Andric case G_FCONSTANT: 6178bcb0991SDimitry Andric OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr}); 6180b57cec5SDimitry Andric break; 6190b57cec5SDimitry Andric case G_FCMP: { 6208bcb0991SDimitry Andric unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 6210b57cec5SDimitry Andric OperandsMapping = 6220b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6238bcb0991SDimitry Andric getFprbMapping(Op2Size), getFprbMapping(Op2Size)}); 6240b57cec5SDimitry Andric break; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric case G_FPEXT: 6270b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 6280b57cec5SDimitry Andric &Mips::ValueMappings[Mips::SPRIdx]}); 6290b57cec5SDimitry Andric break; 6300b57cec5SDimitry Andric case G_FPTRUNC: 6310b57cec5SDimitry Andric OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], 6320b57cec5SDimitry Andric &Mips::ValueMappings[Mips::DPRIdx]}); 6330b57cec5SDimitry Andric break; 6340b57cec5SDimitry Andric case G_FPTOSI: { 6358bcb0991SDimitry Andric assert((Op0Size == 32) && "Unsupported integer size"); 6360b57cec5SDimitry Andric unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 6378bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 6388bcb0991SDimitry Andric {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)}); 6398bcb0991SDimitry Andric break; 6408bcb0991SDimitry Andric } 6418bcb0991SDimitry Andric case G_SITOFP: 6428bcb0991SDimitry Andric assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) && 6430b57cec5SDimitry Andric "Unsupported integer size"); 6448bcb0991SDimitry Andric OperandsMapping = getOperandsMapping( 6458bcb0991SDimitry Andric {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]}); 6460b57cec5SDimitry Andric break; 6470b57cec5SDimitry Andric case G_CONSTANT: 6480b57cec5SDimitry Andric case G_FRAME_INDEX: 6490b57cec5SDimitry Andric case G_GLOBAL_VALUE: 6508bcb0991SDimitry Andric case G_JUMP_TABLE: 6510b57cec5SDimitry Andric case G_BRCOND: 6520b57cec5SDimitry Andric OperandsMapping = 6530b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); 6540b57cec5SDimitry Andric break; 6558bcb0991SDimitry Andric case G_BRJT: 6568bcb0991SDimitry Andric OperandsMapping = 6578bcb0991SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6588bcb0991SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6598bcb0991SDimitry Andric break; 6600b57cec5SDimitry Andric case G_ICMP: 6610b57cec5SDimitry Andric OperandsMapping = 6620b57cec5SDimitry Andric getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 6630b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx], 6640b57cec5SDimitry Andric &Mips::ValueMappings[Mips::GPRIdx]}); 6650b57cec5SDimitry Andric break; 6660b57cec5SDimitry Andric default: 6670b57cec5SDimitry Andric return getInvalidInstructionMapping(); 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6705ffd83dbSDimitry Andric if (MappingID == CustomMappingID) 6715ffd83dbSDimitry Andric TI.clearTypeInfoData(&MI); 6720b57cec5SDimitry Andric return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, 6730b57cec5SDimitry Andric NumOperands); 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric using InstListTy = GISelWorkList<4>; 6770b57cec5SDimitry Andric namespace { 6780b57cec5SDimitry Andric class InstManager : public GISelChangeObserver { 6790b57cec5SDimitry Andric InstListTy &InstList; 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric public: 6820b57cec5SDimitry Andric InstManager(InstListTy &Insts) : InstList(Insts) {} 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } 6850b57cec5SDimitry Andric void erasingInstr(MachineInstr &MI) override {} 6860b57cec5SDimitry Andric void changingInstr(MachineInstr &MI) override {} 6870b57cec5SDimitry Andric void changedInstr(MachineInstr &MI) override {} 6880b57cec5SDimitry Andric }; 6890b57cec5SDimitry Andric } // end anonymous namespace 6900b57cec5SDimitry Andric 6918bcb0991SDimitry Andric void MipsRegisterBankInfo::setRegBank(MachineInstr &MI, 6928bcb0991SDimitry Andric MachineRegisterInfo &MRI) const { 6938bcb0991SDimitry Andric Register Dest = MI.getOperand(0).getReg(); 6948bcb0991SDimitry Andric switch (MI.getOpcode()) { 6958bcb0991SDimitry Andric case TargetOpcode::G_STORE: 6968bcb0991SDimitry Andric // No def operands, skip this instruction. 6978bcb0991SDimitry Andric break; 6988bcb0991SDimitry Andric case TargetOpcode::G_CONSTANT: 6998bcb0991SDimitry Andric case TargetOpcode::G_LOAD: 7008bcb0991SDimitry Andric case TargetOpcode::G_SELECT: 7018bcb0991SDimitry Andric case TargetOpcode::G_PHI: 7028bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 7038bcb0991SDimitry Andric assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type."); 7048bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); 7058bcb0991SDimitry Andric break; 7068bcb0991SDimitry Andric } 707480093f4SDimitry Andric case TargetOpcode::G_PTR_ADD: { 7088bcb0991SDimitry Andric assert(MRI.getType(Dest).isPointer() && "Unexpected operand type."); 7098bcb0991SDimitry Andric MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID)); 7108bcb0991SDimitry Andric break; 7118bcb0991SDimitry Andric } 7128bcb0991SDimitry Andric default: 7138bcb0991SDimitry Andric llvm_unreachable("Unexpected opcode."); 7148bcb0991SDimitry Andric } 7158bcb0991SDimitry Andric } 7168bcb0991SDimitry Andric 7178bcb0991SDimitry Andric static void 7188bcb0991SDimitry Andric combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner, 719*fe6060f1SDimitry Andric GUnmerge &MI, GISelChangeObserver &Observer) { 720480093f4SDimitry Andric SmallVector<Register, 4> UpdatedDefs; 7218bcb0991SDimitry Andric SmallVector<MachineInstr *, 2> DeadInstrs; 722*fe6060f1SDimitry Andric ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs, 723*fe6060f1SDimitry Andric UpdatedDefs, Observer); 7248bcb0991SDimitry Andric for (MachineInstr *DeadMI : DeadInstrs) 7258bcb0991SDimitry Andric DeadMI->eraseFromParent(); 7268bcb0991SDimitry Andric } 7278bcb0991SDimitry Andric 7280b57cec5SDimitry Andric void MipsRegisterBankInfo::applyMappingImpl( 7290b57cec5SDimitry Andric const OperandsMapper &OpdMapper) const { 7300b57cec5SDimitry Andric MachineInstr &MI = OpdMapper.getMI(); 7310b57cec5SDimitry Andric InstListTy NewInstrs; 7320b57cec5SDimitry Andric MachineFunction *MF = MI.getMF(); 7330b57cec5SDimitry Andric MachineRegisterInfo &MRI = OpdMapper.getMRI(); 7348bcb0991SDimitry Andric const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo(); 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric InstManager NewInstrObserver(NewInstrs); 737e8d8bef9SDimitry Andric MachineIRBuilder B(MI, NewInstrObserver); 738e8d8bef9SDimitry Andric LegalizerHelper Helper(*MF, NewInstrObserver, B); 7398bcb0991SDimitry Andric LegalizationArtifactCombiner ArtCombiner(B, MF->getRegInfo(), LegInfo); 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric switch (MI.getOpcode()) { 7420b57cec5SDimitry Andric case TargetOpcode::G_LOAD: 7430b57cec5SDimitry Andric case TargetOpcode::G_STORE: 7440b57cec5SDimitry Andric case TargetOpcode::G_PHI: 7458bcb0991SDimitry Andric case TargetOpcode::G_SELECT: 7468bcb0991SDimitry Andric case TargetOpcode::G_IMPLICIT_DEF: { 7470b57cec5SDimitry Andric Helper.narrowScalar(MI, 0, LLT::scalar(32)); 7480b57cec5SDimitry Andric // Handle new instructions. 7490b57cec5SDimitry Andric while (!NewInstrs.empty()) { 7500b57cec5SDimitry Andric MachineInstr *NewMI = NewInstrs.pop_back_val(); 7510b57cec5SDimitry Andric // This is new G_UNMERGE that was created during narrowScalar and will 7520b57cec5SDimitry Andric // not be considered for regbank selection. RegBankSelect for mips 7530b57cec5SDimitry Andric // visits/makes corresponding G_MERGE first. Combine them here. 754*fe6060f1SDimitry Andric if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI)) 755*fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver); 7560b57cec5SDimitry Andric // This G_MERGE will be combined away when its corresponding G_UNMERGE 7570b57cec5SDimitry Andric // gets regBankSelected. 7580b57cec5SDimitry Andric else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 7590b57cec5SDimitry Andric continue; 7600b57cec5SDimitry Andric else 7618bcb0991SDimitry Andric // Manually set register banks for def operands to 32 bit gprb. 7628bcb0991SDimitry Andric setRegBank(*NewMI, MRI); 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric return; 7650b57cec5SDimitry Andric } 7668bcb0991SDimitry Andric case TargetOpcode::G_UNMERGE_VALUES: 767*fe6060f1SDimitry Andric combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI), 768*fe6060f1SDimitry Andric NewInstrObserver); 7690b57cec5SDimitry Andric return; 7700b57cec5SDimitry Andric default: 7710b57cec5SDimitry Andric break; 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric return applyDefaultMapping(OpdMapper); 7750b57cec5SDimitry Andric } 776