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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 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_IMPL 22 23 #include "MipsGenRegisterBank.inc" 24 25 namespace llvm { 26 namespace Mips { 27 enum PartialMappingIdx { 28 PMI_GPR, 29 PMI_SPR, 30 PMI_DPR, 31 PMI_MSA, 32 PMI_Min = PMI_GPR, 33 }; 34 35 const RegisterBankInfo::PartialMapping PartMappings[]{ 36 {0, 32, GPRBRegBank}, 37 {0, 32, FPRBRegBank}, 38 {0, 64, FPRBRegBank}, 39 {0, 128, FPRBRegBank} 40 }; 41 42 enum ValueMappingIdx { 43 InvalidIdx = 0, 44 GPRIdx = 1, 45 SPRIdx = 4, 46 DPRIdx = 7, 47 MSAIdx = 10 48 }; 49 50 const RegisterBankInfo::ValueMapping ValueMappings[] = { 51 // invalid 52 {nullptr, 0}, 53 // up to 3 operands in GPRs 54 {&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 precission 58 {&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 precission 62 {&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 - MSA 66 {&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 Mips 72 } // end namespace llvm 73 74 using namespace llvm; 75 76 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) {} 77 78 // Instructions where use operands are floating point registers. 79 // Def operands are general purpose. 80 static 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. 93 static 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 103 static 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 116 static 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 131 void 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 else 142 DefUses.push_back(skipCopiesOutgoing(&UseMI)); 143 } 144 } 145 146 void 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 154 MachineInstr * 155 MipsRegisterBankInfo::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 168 MachineInstr * 169 MipsRegisterBankInfo::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 180 MipsRegisterBankInfo::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 217 bool 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 ambiguous 252 // instructions or has no other adjacent instructions. Anyway InstType could 253 // not be determined. There could be unexplored path from some of 254 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one 255 // 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 InstType 258 // will be assigned to all instructions in this branch. 259 addToWaitingQueue(WaitingForTypeOfMI, MI); 260 return false; 261 } 262 263 bool 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 is 276 // '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) and 283 // 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 remaining 292 // 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 305 void 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 313 void 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 else 331 llvm_unreachable("Unsupported register bank.\n"); 332 } 333 334 MipsRegisterBankInfo::InstType 335 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { 336 InstType DefaultAmbiguousType = InstType::Ambiguous; 337 visit(MI, nullptr, DefaultAmbiguousType); 338 return getRecordedTypeForInstr(MI); 339 } 340 341 void 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 350 static const MipsRegisterBankInfo::ValueMapping * 351 getMSAMapping(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 357 static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) { 358 return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 359 : &Mips::ValueMappings[Mips::DPRIdx]; 360 } 361 362 static 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. 366 static const MipsRegisterBankInfo::ValueMapping * 367 getGprbOrCustomMapping(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 375 const RegisterBankInfo::InstructionMapping & 376 MipsRegisterBankInfo::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 match 493 // 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 626 using InstListTy = GISelWorkList<4>; 627 namespace { 628 class InstManager : public GISelChangeObserver { 629 InstListTy &InstList; 630 MachineIRBuilder &B; 631 632 public: 633 InstManager(MachineIRBuilder &B, InstListTy &Insts) : InstList(Insts), B(B) { 634 assert(!B.isObservingChanges()); 635 B.setChangeObserver(*this); 636 } 637 638 ~InstManager() { 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 namespace 646 647 void 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 673 static void 674 combineAwayG_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 684 void 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 will 709 // not be considered for regbank selection. RegBankSelect for mips 710 // 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_UNMERGE 714 // gets regBankSelected. 715 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 716 continue; 717 else 718 // 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