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 if (UseMI.getOpcode() == TargetOpcode::COPY && 164 !TargetRegisterInfo::isPhysicalRegister(UseMI.getOperand(0).getReg())) 165 // Copies of non-physical registers are not supported 166 return; 167 168 DefUses.push_back(&UseMI); 169 } 170 } 171 172 void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef( 173 Register Reg, const MachineRegisterInfo &MRI) { 174 assert(!MRI.getType(Reg).isPointer() && 175 "Pointers are gprb, they should not be considered as ambiguous.\n"); 176 MachineInstr *DefMI = MRI.getVRegDef(Reg); 177 if (DefMI->getOpcode() == TargetOpcode::COPY && 178 !TargetRegisterInfo::isPhysicalRegister(DefMI->getOperand(1).getReg())) 179 // Copies from non-physical registers are not supported. 180 return; 181 182 UseDefs.push_back(DefMI); 183 } 184 185 MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer( 186 const MachineInstr *MI) { 187 assert(isAmbiguous(MI->getOpcode()) && 188 "Not implemented for non Ambiguous opcode.\n"); 189 190 const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo(); 191 192 if (MI->getOpcode() == TargetOpcode::G_LOAD) 193 addDefUses(MI->getOperand(0).getReg(), MRI); 194 195 if (MI->getOpcode() == TargetOpcode::G_STORE) 196 addUseDef(MI->getOperand(0).getReg(), MRI); 197 } 198 199 bool MipsRegisterBankInfo::TypeInfoForMF::visit(const MachineInstr *MI) { 200 assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n"); 201 202 startVisit(MI); 203 AmbiguousRegDefUseContainer DefUseContainer(MI); 204 205 // Visit instructions where MI's DEF operands are USED. 206 if (visitAdjacentInstrs(MI, DefUseContainer.getDefUses(), true)) 207 return true; 208 209 // Visit instructions that DEFINE MI's USE operands. 210 if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs(), false)) 211 return true; 212 213 return false; 214 } 215 216 bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs( 217 const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs, 218 bool isDefUse) { 219 while (!AdjacentInstrs.empty()) { 220 MachineInstr *AdjMI = AdjacentInstrs.pop_back_val(); 221 222 if (isDefUse ? isFloatingPointOpcodeUse(AdjMI->getOpcode()) 223 : isFloatingPointOpcodeDef(AdjMI->getOpcode())) { 224 setTypes(MI, InstType::FloatingPoint); 225 return true; 226 } 227 228 // Determine InstType from register bank of phys register that is 229 // 'isDefUse ? def : use' of this copy. 230 if (AdjMI->getOpcode() == TargetOpcode::COPY) { 231 setTypesAccordingToPhysicalRegister(MI, AdjMI, isDefUse ? 0 : 1); 232 return true; 233 } 234 235 if (isAmbiguous(AdjMI->getOpcode())) { 236 // Chains of ambiguous instructions are not supported. 237 return false; 238 } 239 240 // Defaults to integer instruction. Includes G_MERGE_VALUES and 241 // G_UNMERGE_VALUES. 242 setTypes(MI, InstType::Integer); 243 return true; 244 } 245 return false; 246 } 247 248 void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI, 249 InstType InstTy) { 250 changeRecordedTypeForInstr(MI, InstTy); 251 } 252 253 void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister( 254 const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) { 255 assert((TargetRegisterInfo::isPhysicalRegister( 256 CopyInst->getOperand(Op).getReg())) && 257 "Copies of non physical registers should not be considered here.\n"); 258 259 const MachineFunction &MF = *CopyInst->getMF(); 260 const MachineRegisterInfo &MRI = MF.getRegInfo(); 261 const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); 262 const RegisterBankInfo &RBI = 263 *CopyInst->getMF()->getSubtarget().getRegBankInfo(); 264 const RegisterBank *Bank = 265 RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI); 266 267 if (Bank == &Mips::FPRBRegBank) 268 setTypes(MI, InstType::FloatingPoint); 269 else if (Bank == &Mips::GPRBRegBank) 270 setTypes(MI, InstType::Integer); 271 else 272 llvm_unreachable("Unsupported register bank.\n"); 273 } 274 275 MipsRegisterBankInfo::InstType 276 MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) { 277 visit(MI); 278 return getRecordedTypeForInstr(MI); 279 } 280 281 void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction( 282 llvm::StringRef FunctionName) { 283 if (MFName != FunctionName) { 284 MFName = FunctionName; 285 Types.clear(); 286 } 287 } 288 289 const RegisterBankInfo::InstructionMapping & 290 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 291 292 static TypeInfoForMF TI; 293 294 // Reset TI internal data when MF changes. 295 TI.cleanupIfNewFunction(MI.getMF()->getName()); 296 297 unsigned Opc = MI.getOpcode(); 298 const MachineFunction &MF = *MI.getParent()->getParent(); 299 const MachineRegisterInfo &MRI = MF.getRegInfo(); 300 301 const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); 302 if (Mapping.isValid()) 303 return Mapping; 304 305 using namespace TargetOpcode; 306 307 unsigned NumOperands = MI.getNumOperands(); 308 const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 309 unsigned MappingID = DefaultMappingID; 310 const unsigned CustomMappingID = 1; 311 312 switch (Opc) { 313 case G_TRUNC: 314 case G_ADD: 315 case G_SUB: 316 case G_MUL: 317 case G_UMULH: 318 case G_ZEXTLOAD: 319 case G_SEXTLOAD: 320 case G_GEP: 321 case G_AND: 322 case G_OR: 323 case G_XOR: 324 case G_SHL: 325 case G_ASHR: 326 case G_LSHR: 327 case G_SDIV: 328 case G_UDIV: 329 case G_SREM: 330 case G_UREM: 331 OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; 332 break; 333 case G_LOAD: { 334 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 335 InstType InstTy = InstType::Integer; 336 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 337 InstTy = TI.determineInstType(&MI); 338 } 339 340 if (InstTy == InstType::FloatingPoint) { // fprb 341 OperandsMapping = 342 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 343 : &Mips::ValueMappings[Mips::DPRIdx], 344 &Mips::ValueMappings[Mips::GPRIdx]}); 345 break; 346 } else { // gprb 347 OperandsMapping = 348 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] 349 : &Mips::ValueMappings[Mips::DPRIdx], 350 &Mips::ValueMappings[Mips::GPRIdx]}); 351 if (Size == 64) 352 MappingID = CustomMappingID; 353 } 354 355 break; 356 } 357 case G_STORE: { 358 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 359 InstType InstTy = InstType::Integer; 360 if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) { 361 InstTy = TI.determineInstType(&MI); 362 } 363 364 if (InstTy == InstType::FloatingPoint) { // fprb 365 OperandsMapping = 366 getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 367 : &Mips::ValueMappings[Mips::DPRIdx], 368 &Mips::ValueMappings[Mips::GPRIdx]}); 369 break; 370 } else { // gprb 371 OperandsMapping = 372 getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx] 373 : &Mips::ValueMappings[Mips::DPRIdx], 374 &Mips::ValueMappings[Mips::GPRIdx]}); 375 if (Size == 64) 376 MappingID = CustomMappingID; 377 } 378 break; 379 } 380 case G_UNMERGE_VALUES: { 381 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], 382 &Mips::ValueMappings[Mips::GPRIdx], 383 &Mips::ValueMappings[Mips::DPRIdx]}); 384 MappingID = CustomMappingID; 385 break; 386 } 387 case G_MERGE_VALUES: { 388 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 389 &Mips::ValueMappings[Mips::GPRIdx], 390 &Mips::ValueMappings[Mips::GPRIdx]}); 391 MappingID = CustomMappingID; 392 break; 393 } 394 case G_FADD: 395 case G_FSUB: 396 case G_FMUL: 397 case G_FDIV: 398 case G_FABS: 399 case G_FSQRT:{ 400 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 401 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 402 OperandsMapping = Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 403 : &Mips::ValueMappings[Mips::DPRIdx]; 404 break; 405 } 406 case G_FCONSTANT: { 407 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 408 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 409 const RegisterBankInfo::ValueMapping *FPRValueMapping = 410 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 411 : &Mips::ValueMappings[Mips::DPRIdx]; 412 OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr}); 413 break; 414 } 415 case G_FCMP: { 416 unsigned Size = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 417 assert((Size == 32 || Size == 64) && "Unsupported floating point size"); 418 const RegisterBankInfo::ValueMapping *FPRValueMapping = 419 Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 420 : &Mips::ValueMappings[Mips::DPRIdx]; 421 OperandsMapping = 422 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 423 FPRValueMapping, FPRValueMapping}); 424 break; 425 } 426 case G_FPEXT: 427 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx], 428 &Mips::ValueMappings[Mips::SPRIdx]}); 429 break; 430 case G_FPTRUNC: 431 OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::SPRIdx], 432 &Mips::ValueMappings[Mips::DPRIdx]}); 433 break; 434 case G_FPTOSI: { 435 unsigned SizeFP = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 436 assert((MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() == 32) && 437 "Unsupported integer size"); 438 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); 439 OperandsMapping = getOperandsMapping({ 440 &Mips::ValueMappings[Mips::GPRIdx], 441 SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 442 : &Mips::ValueMappings[Mips::DPRIdx], 443 }); 444 break; 445 } 446 case G_SITOFP: { 447 unsigned SizeInt = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits(); 448 unsigned SizeFP = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 449 (void)SizeInt; 450 assert((SizeInt == 32) && "Unsupported integer size"); 451 assert((SizeFP == 32 || SizeFP == 64) && "Unsupported floating point size"); 452 OperandsMapping = 453 getOperandsMapping({SizeFP == 32 ? &Mips::ValueMappings[Mips::SPRIdx] 454 : &Mips::ValueMappings[Mips::DPRIdx], 455 &Mips::ValueMappings[Mips::GPRIdx]}); 456 break; 457 } 458 case G_CONSTANT: 459 case G_FRAME_INDEX: 460 case G_GLOBAL_VALUE: 461 case G_BRCOND: 462 OperandsMapping = 463 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); 464 break; 465 case G_ICMP: 466 OperandsMapping = 467 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr, 468 &Mips::ValueMappings[Mips::GPRIdx], 469 &Mips::ValueMappings[Mips::GPRIdx]}); 470 break; 471 case G_SELECT: 472 OperandsMapping = 473 getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], 474 &Mips::ValueMappings[Mips::GPRIdx], 475 &Mips::ValueMappings[Mips::GPRIdx], 476 &Mips::ValueMappings[Mips::GPRIdx]}); 477 break; 478 default: 479 return getInvalidInstructionMapping(); 480 } 481 482 return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping, 483 NumOperands); 484 } 485 486 using InstListTy = GISelWorkList<4>; 487 namespace { 488 class InstManager : public GISelChangeObserver { 489 InstListTy &InstList; 490 491 public: 492 InstManager(InstListTy &Insts) : InstList(Insts) {} 493 494 void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); } 495 void erasingInstr(MachineInstr &MI) override {} 496 void changingInstr(MachineInstr &MI) override {} 497 void changedInstr(MachineInstr &MI) override {} 498 }; 499 } // end anonymous namespace 500 501 /// Here we have to narrowScalar s64 operands to s32, combine away 502 /// G_MERGE/G_UNMERGE and erase instructions that became dead in the process. 503 /// We manually assign 32 bit gprb to register operands of all new instructions 504 /// that got created in the process since they will not end up in RegBankSelect 505 /// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++. 506 void MipsRegisterBankInfo::applyMappingImpl( 507 const OperandsMapper &OpdMapper) const { 508 MachineInstr &MI = OpdMapper.getMI(); 509 InstListTy NewInstrs; 510 MachineIRBuilder B(MI); 511 MachineFunction *MF = MI.getMF(); 512 MachineRegisterInfo &MRI = OpdMapper.getMRI(); 513 514 InstManager NewInstrObserver(NewInstrs); 515 GISelObserverWrapper WrapperObserver(&NewInstrObserver); 516 LegalizerHelper Helper(*MF, WrapperObserver, B); 517 LegalizationArtifactCombiner ArtCombiner( 518 B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo()); 519 520 switch (MI.getOpcode()) { 521 case TargetOpcode::G_LOAD: 522 case TargetOpcode::G_STORE: { 523 Helper.narrowScalar(MI, 0, LLT::scalar(32)); 524 // Handle new instructions. 525 while (!NewInstrs.empty()) { 526 MachineInstr *NewMI = NewInstrs.pop_back_val(); 527 // This is new G_UNMERGE that was created during narrowScalar and will 528 // not be considered for regbank selection. RegBankSelect for mips 529 // visits/makes corresponding G_MERGE first. Combine them here. 530 if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) { 531 SmallVector<MachineInstr *, 2> DeadInstrs; 532 ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs); 533 for (MachineInstr *DeadMI : DeadInstrs) 534 DeadMI->eraseFromParent(); 535 } 536 // This G_MERGE will be combined away when its corresponding G_UNMERGE 537 // gets regBankSelected. 538 else if (NewMI->getOpcode() == TargetOpcode::G_MERGE_VALUES) 539 continue; 540 else 541 // Manually set register banks for all register operands to 32 bit gprb. 542 for (auto Op : NewMI->operands()) { 543 if (Op.isReg()) { 544 assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 && 545 "Only 32 bit gprb is handled here.\n"); 546 MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID)); 547 } 548 } 549 } 550 return; 551 } 552 case TargetOpcode::G_UNMERGE_VALUES: { 553 SmallVector<MachineInstr *, 2> DeadInstrs; 554 ArtCombiner.tryCombineMerges(MI, DeadInstrs); 555 for (MachineInstr *DeadMI : DeadInstrs) 556 DeadMI->eraseFromParent(); 557 return; 558 } 559 default: 560 break; 561 } 562 563 return applyDefaultMapping(OpdMapper); 564 } 565