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 "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" 16 #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h" 17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 20 #define GET_TARGET_REGBANK_IMPL 21 22 #include "MipsGenRegisterBank.inc" 23 24 namespace llvm { 25 namespace Mips { 26 enum PartialMappingIdx { 27 PMI_GPR, 28 PMI_SPR, 29 PMI_DPR, 30 PMI_Min = PMI_GPR, 31 }; 32 33 RegisterBankInfo::PartialMapping PartMappings[]{ 34 {0, 32, GPRBRegBank}, 35 {0, 32, FPRBRegBank}, 36 {0, 64, FPRBRegBank} 37 }; 38 39 enum ValueMappingIdx { 40 InvalidIdx = 0, 41 GPRIdx = 1, 42 SPRIdx = 4, 43 DPRIdx = 7 44 }; 45 46 RegisterBankInfo::ValueMapping ValueMappings[] = { 47 // invalid 48 {nullptr, 0}, 49 // up to 3 operands in GPRs 50 {&PartMappings[PMI_GPR - PMI_Min], 1}, 51 {&PartMappings[PMI_GPR - PMI_Min], 1}, 52 {&PartMappings[PMI_GPR - PMI_Min], 1}, 53 // up to 3 ops operands FPRs - single precission 54 {&PartMappings[PMI_SPR - PMI_Min], 1}, 55 {&PartMappings[PMI_SPR - PMI_Min], 1}, 56 {&PartMappings[PMI_SPR - PMI_Min], 1}, 57 // up to 3 ops operands FPRs - double precission 58 {&PartMappings[PMI_DPR - PMI_Min], 1}, 59 {&PartMappings[PMI_DPR - PMI_Min], 1}, 60 {&PartMappings[PMI_DPR - PMI_Min], 1} 61 }; 62 63 } // end namespace Mips 64 } // end namespace llvm 65 66 using namespace llvm; 67 68 MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) 69 : MipsGenRegisterBankInfo() {} 70 71 const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( 72 const TargetRegisterClass &RC) const { 73 using namespace Mips; 74 75 switch (RC.getID()) { 76 case Mips::GPR32RegClassID: 77 case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: 78 case Mips::GPRMM16MovePPairFirstRegClassID: 79 case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID: 80 case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: 81 case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID: 82 case Mips::SP32RegClassID: 83 case Mips::GP32RegClassID: 84 return getRegBank(Mips::GPRBRegBankID); 85 case Mips::FGRCCRegClassID: 86 case Mips::FGR32RegClassID: 87 case Mips::FGR64RegClassID: 88 case Mips::AFGR64RegClassID: 89 return getRegBank(Mips::FPRBRegBankID); 90 default: 91 llvm_unreachable("Register class not supported"); 92 } 93 } 94 95 // Instructions where all register operands are floating point. 96 static bool isFloatingPointOpcode(unsigned Opc) { 97 switch (Opc) { 98 case TargetOpcode::G_FCONSTANT: 99 case TargetOpcode::G_FADD: 100 case TargetOpcode::G_FSUB: 101 case TargetOpcode::G_FMUL: 102 case TargetOpcode::G_FDIV: 103 case TargetOpcode::G_FABS: 104 case TargetOpcode::G_FSQRT: 105 case TargetOpcode::G_FCEIL: 106 case TargetOpcode::G_FFLOOR: 107 case TargetOpcode::G_FPEXT: 108 case TargetOpcode::G_FPTRUNC: 109 return true; 110 default: 111 return false; 112 } 113 } 114 115 // Instructions where use operands are floating point registers. 116 // Def operands are general purpose. 117 static bool isFloatingPointOpcodeUse(unsigned Opc) { 118 switch (Opc) { 119 case TargetOpcode::G_FPTOSI: 120 case TargetOpcode::G_FPTOUI: 121 case TargetOpcode::G_FCMP: 122 case Mips::MFC1: 123 case Mips::ExtractElementF64: 124 case Mips::ExtractElementF64_64: 125 return true; 126 default: 127 return isFloatingPointOpcode(Opc); 128 } 129 } 130 131 // Instructions where def operands are floating point registers. 132 // Use operands are general purpose. 133 static bool isFloatingPointOpcodeDef(unsigned Opc) { 134 switch (Opc) { 135 case TargetOpcode::G_SITOFP: 136 case TargetOpcode::G_UITOFP: 137 case Mips::MTC1: 138 case Mips::BuildPairF64: 139 case Mips::BuildPairF64_64: 140 return true; 141 default: 142 return isFloatingPointOpcode(Opc); 143 } 144 } 145 146 static bool isAmbiguous(unsigned Opc) { 147 switch (Opc) { 148 case TargetOpcode::G_LOAD: 149 case TargetOpcode::G_STORE: 150 case TargetOpcode::G_PHI: 151 case TargetOpcode::G_SELECT: 152 return true; 153 default: 154 return false; 155 } 156 } 157 158 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addDefUses( 159 Register Reg, const MachineRegisterInfo &MRI) { 160 assert(!MRI.getType(Reg).isPointer() && 161 "Pointers are gprb, they should not be considered as ambiguous.\n"); 162 for (MachineInstr &UseMI : MRI.use_instructions(Reg)) { 163 MachineInstr *NonCopyInstr = skipCopiesOutgoing(&UseMI); 164 // Copy with many uses. 165 if (NonCopyInstr->getOpcode() == TargetOpcode::COPY && 166 !Register::isPhysicalRegister(NonCopyInstr->getOperand(0).getReg())) 167 addDefUses(NonCopyInstr->getOperand(0).getReg(), MRI); 168 else 169 DefUses.push_back(skipCopiesOutgoing(&UseMI)); 170 } 171 } 172 173 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( 174 Register Reg, const MachineRegisterInfo &MRI) { 175 assert(!MRI.getType(Reg).isPointer() && 176 "Pointers are gprb, they should not be considered as ambiguous.\n"); 177 MachineInstr *DefMI = MRI.getVRegDef(Reg); 178 UseDefs.push_back(skipCopiesIncoming(DefMI)); 179 } 180 181 MachineInstr * 182 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesOutgoing( 183 MachineInstr *MI) const { 184 const MachineFunction &MF = *MI->getParent()->getParent(); 185 const MachineRegisterInfo &MRI = MF.getRegInfo(); 186 MachineInstr *Ret = MI; 187 while (Ret->getOpcode() == TargetOpcode::COPY && 188 !Register::isPhysicalRegister(Ret->getOperand(0).getReg()) && 189 MRI.hasOneUse(Ret->getOperand(0).getReg())) { 190 Ret = &(*MRI.use_instr_begin(Ret->getOperand(0).getReg())); 191 } 192 return Ret; 193 } 194 195 MachineInstr * 196 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::skipCopiesIncoming( 197 MachineInstr *MI) const { 198 const MachineFunction &MF = *MI->getParent()->getParent(); 199 const MachineRegisterInfo &MRI = MF.getRegInfo(); 200 MachineInstr *Ret = MI; 201 while (Ret->getOpcode() == TargetOpcode::COPY && 202 !Register::isPhysicalRegister(Ret->getOperand(1).getReg())) 203 Ret = MRI.getVRegDef(Ret->getOperand(1).getReg()); 204 return Ret; 205 } 206 207 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( 208 const MachineInstr *MI) { 209 assert(isAmbiguous(MI->getOpcode()) && 210 "Not implemented for non Ambiguous opcode.\n"); 211 212 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); 213 214 if (MI->getOpcode() == TargetOpcode::G_LOAD) 215 addDefUses(MI->getOperand(0).getReg(), MRI); 216 217 if (MI->getOpcode() == TargetOpcode::G_STORE) 218 addUseDef(MI->getOperand(0).getReg(), MRI); 219 220 if (MI->getOpcode() == TargetOpcode::G_PHI) { 221 addDefUses(MI->getOperand(0).getReg(), MRI); 222 223 for (unsigned i = 1; i < MI->getNumOperands(); i += 2) 224 addUseDef(MI->getOperand(i).getReg(), MRI); 225 } 226 227 if (MI->getOpcode() == TargetOpcode::G_SELECT) { 228 addDefUses(MI->getOperand(0).getReg(), MRI); 229 230 addUseDef(MI->getOperand(2).getReg(), MRI); 231 addUseDef(MI->getOperand(3).getReg(), MRI); 232 } 233 } 234 235 bool MipsRegisterBankInfo::TypeInfoForMF::visit( 236 const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI) { 237 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); 238 if (wasVisited(MI)) 239 return true; // InstType has already been determined for MI. 240 241 startVisit(MI); 242 AmbiguousRegDefUseContainer DefUseContainer(MI); 243 244 // Visit instructions where MI's DEF operands are USED. 245 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true)) 246 return true; 247 248 // Visit instructions that DEFINE MI's USE operands. 249 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false)) 250 return true; 251 252 // All MI's adjacent instructions, are ambiguous. 253 if (!WaitingForTypeOfMI) { 254 // This is chain of ambiguous instructions. 255 setTypes(MI, InstType::Ambiguous); 256 return true; 257 } 258 // Excluding WaitingForTypeOfMI, MI is either connected to chains of ambiguous 259 // instructions or has no other adjacent instructions. Anyway InstType could 260 // not be determined. There could be unexplored path from some of 261 // WaitingForTypeOfMI's adjacent instructions to an instruction with only one 262 // mapping available. 263 // We are done with this branch, add MI to WaitingForTypeOfMI's WaitingQueue, 264 // this way when WaitingForTypeOfMI figures out its InstType same InstType 265 // will be assigned to all instructions in this branch. 266 addToWaitingQueue(WaitingForTypeOfMI, MI); 267 return false; 268 } 269 270 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( 271 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, 272 bool isDefUse) { 273 while (!AdjacentInstrs.empty()) { 274 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); 275 276 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) 277 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { 278 setTypes(MI, InstType::FloatingPoint); 279 return true; 280 } 281 282 // Determine InstType from register bank of phys register that is 283 // 'isDefUse ? def : use' of this copy. 284 if (AdjMI->getOpcode() == TargetOpcode::COPY) { 285 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); 286 return true; 287 } 288 289 // Defaults to integer instruction. Includes G_MERGE_VALUES and 290 // G_UNMERGE_VALUES. 291 if (!isAmbiguous(AdjMI->getOpcode())) { 292 setTypes(MI, InstType::Integer); 293 return true; 294 } 295 296 // When AdjMI was visited first, MI has to continue to explore remaining 297 // adjacent instructions and determine InstType without visiting AdjMI. 298 if (!wasVisited(AdjMI) || 299 getRecordedTypeForInstr(AdjMI) != InstType::NotDetermined) { 300 if (visit(AdjMI, MI)) { 301 // InstType is successfully determined and is same as for AdjMI. 302 setTypes(MI, getRecordedTypeForInstr(AdjMI)); 303 return true; 304 } 305 } 306 } 307 return false; 308 } 309 310 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, 311 InstType InstTy) { 312 changeRecordedTypeForInstr(MI, InstTy); 313 for (const MachineInstr *WaitingInstr : getWaitingQueueFor(MI)) { 314 setTypes(WaitingInstr, InstTy); 315 } 316 } 317 318 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( 319 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { 320 assert((Register::isPhysicalRegister(CopyInst->getOperand(Op).getReg())) && 321 "Copies of non physical registers should not be considered here.\n"); 322 323 const MachineFunction &MF = *CopyInst->getMF(); 324 const MachineRegisterInfo &MRI = MF.getRegInfo(); 325 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 326 const RegisterBankInfo &RBI = 327 *CopyInst->getMF()->getSubtarget().getRegBankInfo(); 328 const RegisterBank *Bank = 329 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); 330 331 if (Bank == &Mips::FPRBRegBank) 332 setTypes(MI, InstType::FloatingPoint); 333 else if (Bank == &Mips::GPRBRegBank) 334 setTypes(MI, InstType::Integer); 335 else 336 llvm_unreachable("Unsupported register bank.\n"); 337 } 338 339 MipsRegisterBankInfo::InstType 340 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { 341 visit(MI, nullptr); 342 return getRecordedTypeForInstr(MI); 343 } 344 345 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( 346 llvm::StringRef FunctionName) { 347 if (MFName != FunctionName) { 348 MFName = FunctionName; 349 WaitingQueues.clear(); 350 Types.clear(); 351 } 352 } 353 354 const RegisterBankInfo::InstructionMapping & 355 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 356 357 static TypeInfoForMF TI; 358 359 // Reset TI internal data when MF changes. 360 TI.cleanupIfNewFunction(MI.getMF()->getName()); 361 362 unsigned Opc = MI.getOpcode(); 363 const MachineFunction &MF = *MI.getParent()->getParent(); 364 const MachineRegisterInfo &MRI = MF.getRegInfo(); 365 366 if (MI.getOpcode() != TargetOpcode::G_PHI) { 367 const RegisterBankInfo::InstructionMapping &Mapping = 368 getInstrMappingImpl(MI); 369 if (Mapping.isValid()) 370 return Mapping; 371 } 372 373 using namespace TargetOpcode; 374 375 unsigned NumOperands = MI.getNumOperands(); 376 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 377 unsigned MappingID = DefaultMappingID; 378 const unsigned CustomMappingID = 1; 379 380 switch (Opc) { 381 case G_TRUNC: 382 case G_ADD: 383 case G_SUB: 384 case G_MUL: 385 case G_UMULH: 386 case G_ZEXTLOAD: 387 case G_SEXTLOAD: 388 case G_GEP: 389 case G_INTTOPTR: 390 case G_PTRTOINT: 391 case G_AND: 392 case G_OR: 393 case G_XOR: 394 case G_SHL: 395 case G_ASHR: 396 case G_LSHR: 397 case G_SDIV: 398 case G_UDIV: 399 case G_SREM: 400 case G_UREM: 401 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 402 break; 403 case G_LOAD: { 404 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 405 InstType InstTy = InstType::Integer; 406 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 407 InstTy = TI.determineInstType(&MI); 408 } 409 410 if (InstTy == InstType::FloatingPoint || 411 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb 412 OperandsMapping = 413 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 414 : &Mips::ValueMappings[Mips::DPRIdx], 415 &Mips::ValueMappings[Mips::GPRIdx]}); 416 break; 417 } else { // gprb 418 OperandsMapping = 419 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] 420 : &Mips::ValueMappings[Mips::DPRIdx], 421 &Mips::ValueMappings[Mips::GPRIdx]}); 422 if (Size == 64) 423 MappingID = CustomMappingID; 424 } 425 426 break; 427 } 428 case G_STORE: { 429 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 430 InstType InstTy = InstType::Integer; 431 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 432 InstTy = TI.determineInstType(&MI); 433 } 434 435 if (InstTy == InstType::FloatingPoint || 436 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb 437 OperandsMapping = 438 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 439 : &Mips::ValueMappings[Mips::DPRIdx], 440 &Mips::ValueMappings[Mips::GPRIdx]}); 441 break; 442 } else { // gprb 443 OperandsMapping = 444 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] 445 : &Mips::ValueMappings[Mips::DPRIdx], 446 &Mips::ValueMappings[Mips::GPRIdx]}); 447 if (Size == 64) 448 MappingID = CustomMappingID; 449 } 450 break; 451 } 452 case G_PHI: { 453 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 454 InstType InstTy = InstType::Integer; 455 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 456 InstTy = TI.determineInstType(&MI); 457 } 458 459 // PHI is copylike and should have one regbank in mapping for def register. 460 if (InstTy == InstType::Integer && Size == 64) { // fprb 461 OperandsMapping = 462 getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx]}); 463 return getInstructionMapping(CustomMappingID, /*Cost=*/1, OperandsMapping, 464 /*NumOperands=*/1); 465 } 466 // Use default handling for PHI, i.e. set reg bank of def operand to match 467 // register banks of use operands. 468 const RegisterBankInfo::InstructionMapping &Mapping = 469 getInstrMappingImpl(MI); 470 return Mapping; 471 } 472 case G_SELECT: { 473 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 474 InstType InstTy = InstType::Integer; 475 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 476 InstTy = TI.determineInstType(&MI); 477 } 478 479 if (InstTy == InstType::FloatingPoint || 480 (Size == 64 && InstTy == InstType::Ambiguous)) { // fprb 481 const RegisterBankInfo::ValueMapping *Bank = 482 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 483 : &Mips::ValueMappings[Mips::DPRIdx]; 484 OperandsMapping = getOperandsMapping( 485 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 486 break; 487 } else { // gprb 488 const RegisterBankInfo::ValueMapping *Bank = 489 Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] 490 : &Mips::ValueMappings[Mips::DPRIdx]; 491 OperandsMapping = getOperandsMapping( 492 {Bank, &Mips::ValueMappings[Mips::GPRIdx], Bank, Bank}); 493 if (Size == 64) 494 MappingID = CustomMappingID; 495 } 496 break; 497 } 498 case G_UNMERGE_VALUES: { 499 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], 500 &Mips::ValueMappings[Mips::GPRIdx], 501 &Mips::ValueMappings[Mips::DPRIdx]}); 502 MappingID = CustomMappingID; 503 break; 504 } 505 case G_MERGE_VALUES: { 506 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 507 &Mips::ValueMappings[Mips::GPRIdx], 508 &Mips::ValueMappings[Mips::GPRIdx]}); 509 MappingID = CustomMappingID; 510 break; 511 } 512 case G_FADD: 513 case G_FSUB: 514 case G_FMUL: 515 case G_FDIV: 516 case G_FABS: 517 case G_FSQRT:{ 518 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 519 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 520 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 521 : &Mips::ValueMappings[Mips::DPRIdx]; 522 break; 523 } 524 case G_FCONSTANT: { 525 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 526 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 527 const RegisterBankInfo::ValueMapping *FPRValueMapping = 528 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 529 : &Mips::ValueMappings[Mips::DPRIdx]; 530 OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr}); 531 break; 532 } 533 case G_FCMP: { 534 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 535 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 536 const RegisterBankInfo::ValueMapping *FPRValueMapping = 537 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 538 : &Mips::ValueMappings[Mips::DPRIdx]; 539 OperandsMapping = 540 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 541 FPRValueMapping, FPRValueMapping}); 542 break; 543 } 544 case G_FPEXT: 545 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 546 &Mips::ValueMappings[Mips::SPRIdx]}); 547 break; 548 case G_FPTRUNC: 549 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], 550 &Mips::ValueMappings[Mips::DPRIdx]}); 551 break; 552 case G_FPTOSI: { 553 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 554 assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) && 555 "Unsupported integer size"); 556 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); 557 OperandsMapping = getOperandsMapping({ 558 &Mips::ValueMappings[Mips::GPRIdx], 559 SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 560 : &Mips::ValueMappings[Mips::DPRIdx], 561 }); 562 break; 563 } 564 case G_SITOFP: { 565 unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 566 unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 567 (void)SizeInt; 568 assert((SizeInt == 32) && "Unsupported integer size"); 569 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); 570 OperandsMapping = 571 getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 572 : &Mips::ValueMappings[Mips::DPRIdx], 573 &Mips::ValueMappings[Mips::GPRIdx]}); 574 break; 575 } 576 case G_CONSTANT: 577 case G_FRAME_INDEX: 578 case G_GLOBAL_VALUE: 579 case G_BRCOND: 580 OperandsMapping = 581 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); 582 break; 583 case G_ICMP: 584 OperandsMapping = 585 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 586 &Mips::ValueMappings[Mips::GPRIdx], 587 &Mips::ValueMappings[Mips::GPRIdx]}); 588 break; 589 default: 590 return getInvalidInstructionMapping(); 591 } 592 593 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, 594 NumOperands); 595 } 596 597 using InstListTy = GISelWorkList<4>; 598 namespace { 599 class InstManager : public GISelChangeObserver { 600 InstListTy &InstList; 601 602 public: 603 InstManager(InstListTy &Insts) : InstList(Insts) {} 604 605 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } 606 void erasingInstr(MachineInstr &MI) override {} 607 void changingInstr(MachineInstr &MI) override {} 608 void changedInstr(MachineInstr &MI) override {} 609 }; 610 } // end anonymous namespace 611 612 /// Here we have to narrowScalar s64 operands to s32, combine away 613 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process. 614 /// We manually assign 32 bit gprb to register operands of all new instructions 615 /// that got created in the process since they will not end up in RegBankSelect 616 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++. 617 void MipsRegisterBankInfo::applyMappingImpl( 618 const OperandsMapper &OpdMapper) const { 619 MachineInstr &MI = OpdMapper.getMI(); 620 InstListTy NewInstrs; 621 MachineIRBuilder B(MI); 622 MachineFunction *MF = MI.getMF(); 623 MachineRegisterInfo &MRI = OpdMapper.getMRI(); 624 625 InstManager NewInstrObserver(NewInstrs); 626 GISelObserverWrapper WrapperObserver(&NewInstrObserver); 627 LegalizerHelper Helper(*MF, WrapperObserver, B); 628 LegalizationArtifactCombiner ArtCombiner( 629 B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo()); 630 631 switch (MI.getOpcode()) { 632 case TargetOpcode::G_LOAD: 633 case TargetOpcode::G_STORE: 634 case TargetOpcode::G_PHI: 635 case TargetOpcode::G_SELECT: { 636 Helper.narrowScalar(MI, 0, LLT::scalar(32)); 637 // Handle new instructions. 638 while (!NewInstrs.empty()) { 639 MachineInstr *NewMI = NewInstrs.pop_back_val(); 640 // This is new G_UNMERGE that was created during narrowScalar and will 641 // not be considered for regbank selection. RegBankSelect for mips 642 // visits/makes corresponding G_MERGE first. Combine them here. 643 if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) { 644 SmallVector<MachineInstr *, 2> DeadInstrs; 645 ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs); 646 for (MachineInstr *DeadMI : DeadInstrs) 647 DeadMI->eraseFromParent(); 648 } 649 // This G_MERGE will be combined away when its corresponding G_UNMERGE 650 // gets regBankSelected. 651 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 652 continue; 653 else 654 // Manually set register banks for all register operands to 32 bit gprb. 655 for (auto Op : NewMI->operands()) { 656 if (Op.isReg()) { 657 assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 && 658 "Only 32 bit gprb is handled here.\n"); 659 MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID)); 660 } 661 } 662 } 663 return; 664 } 665 case TargetOpcode::G_UNMERGE_VALUES: { 666 SmallVector<MachineInstr *, 2> DeadInstrs; 667 ArtCombiner.tryCombineMerges(MI, DeadInstrs); 668 for (MachineInstr *DeadMI : DeadInstrs) 669 DeadMI->eraseFromParent(); 670 return; 671 } 672 default: 673 break; 674 } 675 676 return applyDefaultMapping(OpdMapper); 677 } 678