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