733 lines · cpp
1//===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements the targeting of the RegisterBankInfo class for Mips.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//12 13#include "MipsRegisterBankInfo.h"14#include "MipsInstrInfo.h"15#include "MipsTargetMachine.h"16#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"17#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"18#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20 21#define GET_TARGET_REGBANK_IMPL22 23#include "MipsGenRegisterBank.inc"24 25namespace llvm {26namespace Mips {27enum PartialMappingIdx {28 PMI_GPR,29 PMI_SPR,30 PMI_DPR,31 PMI_MSA,32 PMI_Min = PMI_GPR,33};34 35const RegisterBankInfo::PartialMapping PartMappings[]{36 {0, 32, GPRBRegBank},37 {0, 32, FPRBRegBank},38 {0, 64, FPRBRegBank},39 {0, 128, FPRBRegBank}40};41 42enum ValueMappingIdx {43 InvalidIdx = 0,44 GPRIdx = 1,45 SPRIdx = 4,46 DPRIdx = 7,47 MSAIdx = 1048};49 50const RegisterBankInfo::ValueMapping ValueMappings[] = {51 // invalid52 {nullptr, 0},53 // up to 3 operands in GPRs54 {&PartMappings[PMI_GPR - PMI_Min], 1},55 {&PartMappings[PMI_GPR - PMI_Min], 1},56 {&PartMappings[PMI_GPR - PMI_Min], 1},57 // up to 3 operands in FPRs - single precission58 {&PartMappings[PMI_SPR - PMI_Min], 1},59 {&PartMappings[PMI_SPR - PMI_Min], 1},60 {&PartMappings[PMI_SPR - PMI_Min], 1},61 // up to 3 operands in FPRs - double precission62 {&PartMappings[PMI_DPR - PMI_Min], 1},63 {&PartMappings[PMI_DPR - PMI_Min], 1},64 {&PartMappings[PMI_DPR - PMI_Min], 1},65 // up to 3 operands in FPRs - MSA66 {&PartMappings[PMI_MSA - PMI_Min], 1},67 {&PartMappings[PMI_MSA - PMI_Min], 1},68 {&PartMappings[PMI_MSA - PMI_Min], 1}69};70 71} // end namespace Mips72} // end namespace llvm73 74using namespace llvm;75 76MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {}77 78// Instructions where use operands are floating point registers.79// Def operands are general purpose.80static bool isFloatingPointOpcodeUse(unsigned Opc) {81 switch (Opc) {82 case TargetOpcode::G_FPTOSI:83 case TargetOpcode::G_FPTOUI:84 case TargetOpcode::G_FCMP:85 return true;86 default:87 return isPreISelGenericFloatingPointOpcode(Opc);88 }89}90 91// Instructions where def operands are floating point registers.92// Use operands are general purpose.93static bool isFloatingPointOpcodeDef(unsigned Opc) {94 switch (Opc) {95 case TargetOpcode::G_SITOFP:96 case TargetOpcode::G_UITOFP:97 return true;98 default:99 return isPreISelGenericFloatingPointOpcode(Opc);100 }101}102 103static bool isGprbTwoInstrUnalignedLoadOrStore(const MachineInstr *MI) {104 if (MI->getOpcode() == TargetOpcode::G_LOAD ||105 MI->getOpcode() == TargetOpcode::G_STORE) {106 auto MMO = *MI->memoperands_begin();107 const MipsSubtarget &STI = MI->getMF()->getSubtarget<MipsSubtarget>();108 if (MMO->getSize() == 4 && (!STI.systemSupportsUnalignedAccess() &&109 (!MMO->getSize().hasValue() ||110 MMO->getAlign() < MMO->getSize().getValue())))111 return true;112 }113 return false;114}115 116static bool isAmbiguous(unsigned Opc) {117 switch (Opc) {118 case TargetOpcode::G_LOAD:119 case TargetOpcode::G_STORE:120 case TargetOpcode::G_PHI:121 case TargetOpcode::G_SELECT:122 case TargetOpcode::G_IMPLICIT_DEF:123 case TargetOpcode::G_UNMERGE_VALUES:124 case TargetOpcode::G_MERGE_VALUES:125 return true;126 default:127 return false;128 }129}130 131void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses(132 Register Reg, const MachineRegisterInfo &MRI) {133 assert(!MRI.getType(Reg).isPointer() &&134 "Pointers are gprb, they should not be considered as ambiguous.\n");135 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) {136 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI);137 // Copy with many uses.138 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY &&139 !NonCopyInstr->getOperand(0).getReg().isPhysical())140 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI);141 else142 DefUses.push_back(skipCopiesOutgoing(&UseMI));143 }144}145 146void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(147 Register Reg, const MachineRegisterInfo &MRI) {148 assert(!MRI.getType(Reg).isPointer() &&149 "Pointers are gprb, they should not be considered as ambiguous.\n");150 MachineInstr *DefMI = MRI.getVRegDef(Reg);151 UseDefs.push_back(skipCopiesIncoming(DefMI));152}153 154MachineInstr *155MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing(156 MachineInstr *MI) const {157 const MachineFunction &MF = *MI->getParent()->getParent();158 const MachineRegisterInfo &MRI = MF.getRegInfo();159 MachineInstr *Ret = MI;160 while (Ret->getOpcode() == TargetOpcode::COPY &&161 !Ret->getOperand(0).getReg().isPhysical() &&162 MRI.hasOneUse(Ret->getOperand(0).getReg())) {163 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg()));164 }165 return Ret;166}167 168MachineInstr *169MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming(170 MachineInstr *MI) const {171 const MachineFunction &MF = *MI->getParent()->getParent();172 const MachineRegisterInfo &MRI = MF.getRegInfo();173 MachineInstr *Ret = MI;174 while (Ret->getOpcode() == TargetOpcode::COPY &&175 !Ret->getOperand(1).getReg().isPhysical())176 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg());177 return Ret;178}179 180MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(181 const MachineInstr *MI) {182 assert(isAmbiguous(MI->getOpcode()) &&183 "Not implemented for non Ambiguous opcode.\n");184 185 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();186 187 if (MI->getOpcode() == TargetOpcode::G_LOAD)188 addDefUses(MI->getOperand(0).getReg(), MRI);189 190 if (MI->getOpcode() == TargetOpcode::G_STORE)191 addUseDef(MI->getOperand(0).getReg(), MRI);192 193 if (auto *PHI = dyn_cast<GPhi>(MI)) {194 addDefUses(PHI->getReg(0), MRI);195 196 for (unsigned I = 1; I < PHI->getNumIncomingValues(); ++I)197 addUseDef(PHI->getIncomingValue(I), MRI);198 }199 200 if (MI->getOpcode() == TargetOpcode::G_SELECT) {201 addDefUses(MI->getOperand(0).getReg(), MRI);202 203 addUseDef(MI->getOperand(2).getReg(), MRI);204 addUseDef(MI->getOperand(3).getReg(), MRI);205 }206 207 if (MI->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)208 addDefUses(MI->getOperand(0).getReg(), MRI);209 210 if (MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)211 addUseDef(MI->getOperand(MI->getNumOperands() - 1).getReg(), MRI);212 213 if (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES)214 addDefUses(MI->getOperand(0).getReg(), MRI);215}216 217bool MipsRegisterBankInfo::TypeInfoForMF::visit(218 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,219 InstType &AmbiguousTy) {220 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");221 if (wasVisited(MI))222 return true; // InstType has already been determined for MI.223 224 startVisit(MI);225 AmbiguousRegDefUseContainer DefUseContainer(MI);226 227 if (isGprbTwoInstrUnalignedLoadOrStore(MI)) {228 setTypes(MI, Integer);229 return true;230 }231 232 if (AmbiguousTy == InstType::Ambiguous &&233 (MI->getOpcode() == TargetOpcode::G_MERGE_VALUES ||234 MI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES))235 AmbiguousTy = InstType::AmbiguousWithMergeOrUnmerge;236 237 // Visit instructions where MI's DEF operands are USED.238 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true, AmbiguousTy))239 return true;240 241 // Visit instructions that DEFINE MI's USE operands.242 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false, AmbiguousTy))243 return true;244 245 // All MI's adjacent instructions, are ambiguous.246 if (!WaitingForTypeOfMI) {247 // This is chain of ambiguous instructions.248 setTypes(MI, AmbiguousTy);249 return true;250 }251 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous252 // instructions or has no other adjacent instructions. Anyway InstType could253 // not be determined. There could be unexplored path from some of254 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one255 // mapping available.256 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue,257 // this way when WaitingForTypeOfMI figures out its InstType same InstType258 // will be assigned to all instructions in this branch.259 addToWaitingQueue(WaitingForTypeOfMI, MI);260 return false;261}262 263bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(264 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs,265 bool isDefUse, InstType &AmbiguousTy) {266 while (!AdjacentInstrs.empty()) {267 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();268 269 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode())270 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) {271 setTypes(MI, InstType::FloatingPoint);272 return true;273 }274 275 // Determine InstType from register bank of phys register that is276 // 'isDefUse ? def : use' of this copy.277 if (AdjMI->getOpcode() == TargetOpcode::COPY) {278 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1);279 return true;280 }281 282 // Defaults to integer instruction. Small registers in G_MERGE (uses) and283 // G_UNMERGE (defs) will always be gprb.284 if ((!isDefUse && AdjMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) ||285 (isDefUse && AdjMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) ||286 !isAmbiguous(AdjMI->getOpcode())) {287 setTypes(MI, InstType::Integer);288 return true;289 }290 291 // When AdjMI was visited first, MI has to continue to explore remaining292 // adjacent instructions and determine InstType without visiting AdjMI.293 if (!wasVisited(AdjMI) ||294 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) {295 if (visit(AdjMI, MI, AmbiguousTy)) {296 // InstType is successfully determined and is same as for AdjMI.297 setTypes(MI, getRecordedTypeForInstr(AdjMI));298 return true;299 }300 }301 }302 return false;303}304 305void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,306 InstType InstTy) {307 changeRecordedTypeForInstr(MI, InstTy);308 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) {309 setTypes(WaitingInstr, InstTy);310 }311}312 313void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(314 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {315 assert((CopyInst->getOperand(Op).getReg().isPhysical()) &&316 "Copies of non physical registers should not be considered here.\n");317 318 const MachineFunction &MF = *CopyInst->getMF();319 const MachineRegisterInfo &MRI = MF.getRegInfo();320 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();321 const RegisterBankInfo &RBI =322 *CopyInst->getMF()->getSubtarget().getRegBankInfo();323 const RegisterBank *Bank =324 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);325 326 if (Bank == &Mips::FPRBRegBank)327 setTypes(MI, InstType::FloatingPoint);328 else if (Bank == &Mips::GPRBRegBank)329 setTypes(MI, InstType::Integer);330 else331 llvm_unreachable("Unsupported register bank.\n");332}333 334MipsRegisterBankInfo::InstType335MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {336 InstType DefaultAmbiguousType = InstType::Ambiguous;337 visit(MI, nullptr, DefaultAmbiguousType);338 return getRecordedTypeForInstr(MI);339}340 341void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(342 llvm::StringRef FunctionName) {343 if (MFName != FunctionName) {344 MFName = std::string(FunctionName);345 WaitingQueues.clear();346 Types.clear();347 }348}349 350static const MipsRegisterBankInfo::ValueMapping *351getMSAMapping(const MachineFunction &MF) {352 assert(MF.getSubtarget<MipsSubtarget>().hasMSA() &&353 "MSA mapping not available on target without MSA.");354 return &Mips::ValueMappings[Mips::MSAIdx];355}356 357static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) {358 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]359 : &Mips::ValueMappings[Mips::DPRIdx];360}361 362static const unsigned CustomMappingID = 1;363 364// Only 64 bit mapping is available in fprb and will be marked as custom, i.e.365// will be split into two 32 bit registers in gprb.366static const MipsRegisterBankInfo::ValueMapping *367getGprbOrCustomMapping(unsigned Size, unsigned &MappingID) {368 if (Size == 32)369 return &Mips::ValueMappings[Mips::GPRIdx];370 371 MappingID = CustomMappingID;372 return &Mips::ValueMappings[Mips::DPRIdx];373}374 375const RegisterBankInfo::InstructionMapping &376MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {377 378 static TypeInfoForMF TI;379 380 // Reset TI internal data when MF changes.381 TI.cleanupIfNewFunction(MI.getMF()->getName());382 383 unsigned Opc = MI.getOpcode();384 const MachineFunction &MF = *MI.getParent()->getParent();385 const MachineRegisterInfo &MRI = MF.getRegInfo();386 387 if (MI.getOpcode() != TargetOpcode::G_PHI) {388 const RegisterBankInfo::InstructionMapping &Mapping =389 getInstrMappingImpl(MI);390 if (Mapping.isValid())391 return Mapping;392 }393 394 using namespace TargetOpcode;395 396 unsigned NumOperands = MI.getNumOperands();397 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];398 unsigned MappingID = DefaultMappingID;399 400 // Check if LLT sizes match sizes of available register banks.401 for (const MachineOperand &Op : MI.operands()) {402 if (Op.isReg()) {403 LLT RegTy = MRI.getType(Op.getReg());404 405 if (RegTy.isScalar() &&406 (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64))407 return getInvalidInstructionMapping();408 409 if (RegTy.isVector() && RegTy.getSizeInBits() != 128)410 return getInvalidInstructionMapping();411 }412 }413 414 const LLT Op0Ty = MRI.getType(MI.getOperand(0).getReg());415 unsigned Op0Size = Op0Ty.getSizeInBits();416 InstType InstTy = InstType::Integer;417 418 switch (Opc) {419 case G_TRUNC:420 case G_UMULH:421 case G_ZEXTLOAD:422 case G_SEXTLOAD:423 case G_PTR_ADD:424 case G_INTTOPTR:425 case G_PTRTOINT:426 case G_AND:427 case G_OR:428 case G_XOR:429 case G_SHL:430 case G_ASHR:431 case G_LSHR:432 case G_BRINDIRECT:433 case G_VASTART:434 case G_BSWAP:435 case G_CTLZ:436 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];437 break;438 case G_ADD:439 case G_SUB:440 case G_MUL:441 case G_SDIV:442 case G_SREM:443 case G_UDIV:444 case G_UREM:445 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];446 if (Op0Size == 128)447 OperandsMapping = getMSAMapping(MF);448 break;449 case G_STORE:450 case G_LOAD: {451 if (Op0Size == 128) {452 OperandsMapping = getOperandsMapping(453 {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]});454 break;455 }456 457 if (!Op0Ty.isPointer())458 InstTy = TI.determineInstType(&MI);459 460 if (isFloatingPoint_32or64(InstTy, Op0Size) ||461 isAmbiguous_64(InstTy, Op0Size)) {462 OperandsMapping = getOperandsMapping(463 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});464 } else {465 assert((isInteger_32(InstTy, Op0Size) ||466 isAmbiguous_32(InstTy, Op0Size) ||467 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&468 "Unexpected Inst type");469 OperandsMapping =470 getOperandsMapping({getGprbOrCustomMapping(Op0Size, MappingID),471 &Mips::ValueMappings[Mips::GPRIdx]});472 }473 474 break;475 }476 case G_PHI: {477 if (!Op0Ty.isPointer())478 InstTy = TI.determineInstType(&MI);479 480 // PHI is copylike and should have one regbank in mapping for def register.481 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) {482 OperandsMapping =483 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]});484 TI.clearTypeInfoData(&MI);485 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping,486 /*NumOperands=*/1);487 }488 assert((isInteger_32(InstTy, Op0Size) ||489 isFloatingPoint_32or64(InstTy, Op0Size) ||490 isAmbiguous_32or64(InstTy, Op0Size)) &&491 "Unexpected Inst type");492 // Use default handling for PHI, i.e. set reg bank of def operand to match493 // register banks of use operands.494 return getInstrMappingImpl(MI);495 }496 case G_SELECT: {497 if (!Op0Ty.isPointer())498 InstTy = TI.determineInstType(&MI);499 if (isFloatingPoint_32or64(InstTy, Op0Size) ||500 isAmbiguous_64(InstTy, Op0Size)) {501 const RegisterBankInfo::ValueMapping *Bank = getFprbMapping(Op0Size);502 OperandsMapping = getOperandsMapping(503 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});504 break;505 } else {506 assert((isInteger_32(InstTy, Op0Size) ||507 isAmbiguous_32(InstTy, Op0Size) ||508 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&509 "Unexpected Inst type");510 const RegisterBankInfo::ValueMapping *Bank =511 getGprbOrCustomMapping(Op0Size, MappingID);512 OperandsMapping = getOperandsMapping(513 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank});514 }515 break;516 }517 case G_IMPLICIT_DEF: {518 if (!Op0Ty.isPointer())519 InstTy = TI.determineInstType(&MI);520 521 if (isFloatingPoint_32or64(InstTy, Op0Size))522 OperandsMapping = getFprbMapping(Op0Size);523 else {524 assert((isInteger_32(InstTy, Op0Size) ||525 isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size)) &&526 "Unexpected Inst type");527 OperandsMapping = getGprbOrCustomMapping(Op0Size, MappingID);528 }529 } break;530 case G_UNMERGE_VALUES: {531 assert(MI.getNumOperands() == 3 && "Unsupported G_UNMERGE_VALUES");532 unsigned Op3Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();533 InstTy = TI.determineInstType(&MI);534 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size) ||535 isFloatingPoint_64(InstTy, Op3Size)) &&536 "Unexpected Inst type");537 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx],538 &Mips::ValueMappings[Mips::GPRIdx],539 &Mips::ValueMappings[Mips::DPRIdx]});540 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op3Size))541 MappingID = CustomMappingID;542 break;543 }544 case G_MERGE_VALUES: {545 InstTy = TI.determineInstType(&MI);546 assert((isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size) ||547 isFloatingPoint_64(InstTy, Op0Size)) &&548 "Unexpected Inst type");549 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],550 &Mips::ValueMappings[Mips::GPRIdx],551 &Mips::ValueMappings[Mips::GPRIdx]});552 if (isAmbiguousWithMergeOrUnmerge_64(InstTy, Op0Size))553 MappingID = CustomMappingID;554 break;555 }556 case G_FADD:557 case G_FSUB:558 case G_FMUL:559 case G_FDIV:560 case G_FABS:561 case G_FSQRT:562 OperandsMapping = getFprbMapping(Op0Size);563 if (Op0Size == 128)564 OperandsMapping = getMSAMapping(MF);565 break;566 case G_FCONSTANT:567 OperandsMapping = getOperandsMapping({getFprbMapping(Op0Size), nullptr});568 break;569 case G_FCMP: {570 unsigned Op2Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();571 OperandsMapping =572 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,573 getFprbMapping(Op2Size), getFprbMapping(Op2Size)});574 break;575 }576 case G_FPEXT:577 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],578 &Mips::ValueMappings[Mips::SPRIdx]});579 break;580 case G_FPTRUNC:581 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx],582 &Mips::ValueMappings[Mips::DPRIdx]});583 break;584 case G_FPTOSI: {585 assert((Op0Size == 32) && "Unsupported integer size");586 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();587 OperandsMapping = getOperandsMapping(588 {&Mips::ValueMappings[Mips::GPRIdx], getFprbMapping(SizeFP)});589 break;590 }591 case G_SITOFP:592 assert((MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() == 32) &&593 "Unsupported integer size");594 OperandsMapping = getOperandsMapping(595 {getFprbMapping(Op0Size), &Mips::ValueMappings[Mips::GPRIdx]});596 break;597 case G_CONSTANT:598 case G_FRAME_INDEX:599 case G_GLOBAL_VALUE:600 case G_JUMP_TABLE:601 case G_BRCOND:602 OperandsMapping =603 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr});604 break;605 case G_BRJT:606 OperandsMapping =607 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,608 &Mips::ValueMappings[Mips::GPRIdx]});609 break;610 case G_ICMP:611 OperandsMapping =612 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr,613 &Mips::ValueMappings[Mips::GPRIdx],614 &Mips::ValueMappings[Mips::GPRIdx]});615 break;616 default:617 return getInvalidInstructionMapping();618 }619 620 if (MappingID == CustomMappingID)621 TI.clearTypeInfoData(&MI);622 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,623 NumOperands);624}625 626using InstListTy = GISelWorkList<4>;627namespace {628class InstManager : public GISelChangeObserver {629 InstListTy &InstList;630 MachineIRBuilder &B;631 632public:633 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) {634 assert(!B.isObservingChanges());635 B.setChangeObserver(*this);636 }637 638 ~InstManager() override { B.stopObservingChanges(); }639 640 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }641 void erasingInstr(MachineInstr &MI) override {}642 void changingInstr(MachineInstr &MI) override {}643 void changedInstr(MachineInstr &MI) override {}644};645} // end anonymous namespace646 647void MipsRegisterBankInfo::setRegBank(MachineInstr &MI,648 MachineRegisterInfo &MRI) const {649 Register Dest = MI.getOperand(0).getReg();650 switch (MI.getOpcode()) {651 case TargetOpcode::G_STORE:652 // No def operands, skip this instruction.653 break;654 case TargetOpcode::G_CONSTANT:655 case TargetOpcode::G_LOAD:656 case TargetOpcode::G_SELECT:657 case TargetOpcode::G_PHI:658 case TargetOpcode::G_IMPLICIT_DEF: {659 assert(MRI.getType(Dest) == LLT::scalar(32) && "Unexpected operand type.");660 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));661 break;662 }663 case TargetOpcode::G_PTR_ADD: {664 assert(MRI.getType(Dest).isPointer() && "Unexpected operand type.");665 MRI.setRegBank(Dest, getRegBank(Mips::GPRBRegBankID));666 break;667 }668 default:669 llvm_unreachable("Unexpected opcode.");670 }671}672 673static void674combineAwayG_UNMERGE_VALUES(LegalizationArtifactCombiner &ArtCombiner,675 GUnmerge &MI, GISelChangeObserver &Observer) {676 SmallVector<Register, 4> UpdatedDefs;677 SmallVector<MachineInstr *, 2> DeadInstrs;678 ArtCombiner.tryCombineUnmergeValues(MI, DeadInstrs,679 UpdatedDefs, Observer);680 for (MachineInstr *DeadMI : DeadInstrs)681 DeadMI->eraseFromParent();682}683 684void MipsRegisterBankInfo::applyMappingImpl(685 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {686 MachineInstr &MI = OpdMapper.getMI();687 Builder.setInstrAndDebugLoc(MI);688 689 InstListTy NewInstrs;690 MachineFunction *MF = MI.getMF();691 MachineRegisterInfo &MRI = OpdMapper.getMRI();692 const LegalizerInfo &LegInfo = *MF->getSubtarget().getLegalizerInfo();693 694 InstManager NewInstrObserver(Builder, NewInstrs);695 LegalizerHelper Helper(*MF, NewInstrObserver, Builder);696 LegalizationArtifactCombiner ArtCombiner(Builder, MF->getRegInfo(), LegInfo);697 698 switch (MI.getOpcode()) {699 case TargetOpcode::G_LOAD:700 case TargetOpcode::G_STORE:701 case TargetOpcode::G_PHI:702 case TargetOpcode::G_SELECT:703 case TargetOpcode::G_IMPLICIT_DEF: {704 Helper.narrowScalar(MI, 0, LLT::scalar(32));705 // Handle new instructions.706 while (!NewInstrs.empty()) {707 MachineInstr *NewMI = NewInstrs.pop_back_val();708 // This is new G_UNMERGE that was created during narrowScalar and will709 // not be considered for regbank selection. RegBankSelect for mips710 // visits/makes corresponding G_MERGE first. Combine them here.711 if (auto *Unmerge = dyn_cast<GUnmerge>(NewMI))712 combineAwayG_UNMERGE_VALUES(ArtCombiner, *Unmerge, NewInstrObserver);713 // This G_MERGE will be combined away when its corresponding G_UNMERGE714 // gets regBankSelected.715 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES)716 continue;717 else718 // Manually set register banks for def operands to 32 bit gprb.719 setRegBank(*NewMI, MRI);720 }721 return;722 }723 case TargetOpcode::G_UNMERGE_VALUES:724 combineAwayG_UNMERGE_VALUES(ArtCombiner, cast<GUnmerge>(MI),725 NewInstrObserver);726 return;727 default:728 break;729 }730 731 return applyDefaultMapping(OpdMapper);732}733