1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file implements the targeting of the RegisterBankInfo class for 11 /// AArch64. 12 /// \todo This should be generated by TableGen. 13 //===----------------------------------------------------------------------===// 14 15 #include "AArch64RegisterBankInfo.h" 16 #include "AArch64InstrInfo.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/CodeGen/GlobalISel/RegisterBank.h" 19 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 20 #include "llvm/CodeGen/LowLevelType.h" 21 #include "llvm/CodeGen/MachineFunction.h" 22 #include "llvm/CodeGen/MachineInstr.h" 23 #include "llvm/CodeGen/MachineOperand.h" 24 #include "llvm/CodeGen/MachineRegisterInfo.h" 25 #include "llvm/CodeGen/TargetOpcodes.h" 26 #include "llvm/CodeGen/TargetRegisterInfo.h" 27 #include "llvm/CodeGen/TargetSubtargetInfo.h" 28 #include "llvm/Support/ErrorHandling.h" 29 #include <algorithm> 30 #include <cassert> 31 32 #define GET_TARGET_REGBANK_IMPL 33 #include "AArch64GenRegisterBank.inc" 34 35 // This file will be TableGen'ed at some point. 36 #include "AArch64GenRegisterBankInfo.def" 37 38 using namespace llvm; 39 40 AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI) 41 : AArch64GenRegisterBankInfo() { 42 static bool AlreadyInit = false; 43 // We have only one set of register banks, whatever the subtarget 44 // is. Therefore, the initialization of the RegBanks table should be 45 // done only once. Indeed the table of all register banks 46 // (AArch64::RegBanks) is unique in the compiler. At some point, it 47 // will get tablegen'ed and the whole constructor becomes empty. 48 if (AlreadyInit) 49 return; 50 AlreadyInit = true; 51 52 const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID); 53 (void)RBGPR; 54 assert(&AArch64::GPRRegBank == &RBGPR && 55 "The order in RegBanks is messed up"); 56 57 const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID); 58 (void)RBFPR; 59 assert(&AArch64::FPRRegBank == &RBFPR && 60 "The order in RegBanks is messed up"); 61 62 const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID); 63 (void)RBCCR; 64 assert(&AArch64::CCRegBank == &RBCCR && "The order in RegBanks is messed up"); 65 66 // The GPR register bank is fully defined by all the registers in 67 // GR64all + its subclasses. 68 assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) && 69 "Subclass not added?"); 70 assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); 71 72 // The FPR register bank is fully defined by all the registers in 73 // GR64all + its subclasses. 74 assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) && 75 "Subclass not added?"); 76 assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) && 77 "Subclass not added?"); 78 assert(RBFPR.getSize() == 512 && 79 "FPRs should hold up to 512-bit via QQQQ sequence"); 80 81 assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) && 82 "Class not added?"); 83 assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit"); 84 85 // Check that the TableGen'ed like file is in sync we our expectations. 86 // First, the Idx. 87 assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR, 88 {PMI_GPR32, PMI_GPR64}) && 89 "PartialMappingIdx's are incorrectly ordered"); 90 assert(checkPartialMappingIdx(PMI_FirstFPR, PMI_LastFPR, 91 {PMI_FPR16, PMI_FPR32, PMI_FPR64, PMI_FPR128, 92 PMI_FPR256, PMI_FPR512}) && 93 "PartialMappingIdx's are incorrectly ordered"); 94 // Now, the content. 95 // Check partial mapping. 96 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \ 97 do { \ 98 assert( \ 99 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \ 100 #Idx " is incorrectly initialized"); \ 101 } while (false) 102 103 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR); 104 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR); 105 CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR); 106 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR); 107 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR); 108 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR); 109 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR); 110 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR); 111 112 // Check value mapping. 113 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \ 114 do { \ 115 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \ 116 PartialMappingIdx::PMI_First##RBName, Size, \ 117 Offset) && \ 118 #RBName #Size " " #Offset " is incorrectly initialized"); \ 119 } while (false) 120 121 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0) 122 123 CHECK_VALUEMAP(GPR, 32); 124 CHECK_VALUEMAP(GPR, 64); 125 CHECK_VALUEMAP(FPR, 16); 126 CHECK_VALUEMAP(FPR, 32); 127 CHECK_VALUEMAP(FPR, 64); 128 CHECK_VALUEMAP(FPR, 128); 129 CHECK_VALUEMAP(FPR, 256); 130 CHECK_VALUEMAP(FPR, 512); 131 132 // Check the value mapping for 3-operands instructions where all the operands 133 // map to the same value mapping. 134 #define CHECK_VALUEMAP_3OPS(RBName, Size) \ 135 do { \ 136 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \ 137 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \ 138 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \ 139 } while (false) 140 141 CHECK_VALUEMAP_3OPS(GPR, 32); 142 CHECK_VALUEMAP_3OPS(GPR, 64); 143 CHECK_VALUEMAP_3OPS(FPR, 32); 144 CHECK_VALUEMAP_3OPS(FPR, 64); 145 CHECK_VALUEMAP_3OPS(FPR, 128); 146 CHECK_VALUEMAP_3OPS(FPR, 256); 147 CHECK_VALUEMAP_3OPS(FPR, 512); 148 149 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \ 150 do { \ 151 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \ 152 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \ 153 (void)PartialMapDstIdx; \ 154 (void)PartialMapSrcIdx; \ 155 const ValueMapping *Map = getCopyMapping( \ 156 AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \ 157 (void)Map; \ 158 assert(Map[0].BreakDown == \ 159 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \ 160 Map[0].NumBreakDowns == 1 && #RBNameDst #Size \ 161 " Dst is incorrectly initialized"); \ 162 assert(Map[1].BreakDown == \ 163 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \ 164 Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \ 165 " Src is incorrectly initialized"); \ 166 \ 167 } while (false) 168 169 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32); 170 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32); 171 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64); 172 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64); 173 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32); 174 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32); 175 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64); 176 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64); 177 178 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \ 179 do { \ 180 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \ 181 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \ 182 (void)PartialMapDstIdx; \ 183 (void)PartialMapSrcIdx; \ 184 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \ 185 (void)Map; \ 186 assert(Map[0].BreakDown == \ 187 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \ 188 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \ 189 " Dst is incorrectly initialized"); \ 190 assert(Map[1].BreakDown == \ 191 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \ 192 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \ 193 " Src is incorrectly initialized"); \ 194 \ 195 } while (false) 196 197 CHECK_VALUEMAP_FPEXT(32, 16); 198 CHECK_VALUEMAP_FPEXT(64, 16); 199 CHECK_VALUEMAP_FPEXT(64, 32); 200 CHECK_VALUEMAP_FPEXT(128, 64); 201 202 assert(verify(TRI) && "Invalid register bank information"); 203 } 204 205 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A, 206 const RegisterBank &B, 207 unsigned Size) const { 208 // What do we do with different size? 209 // copy are same size. 210 // Will introduce other hooks for different size: 211 // * extract cost. 212 // * build_sequence cost. 213 214 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV. 215 // FIXME: This should be deduced from the scheduling model. 216 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank) 217 // FMOVXDr or FMOVWSr. 218 return 5; 219 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank) 220 // FMOVDXr or FMOVSWr. 221 return 4; 222 223 return RegisterBankInfo::copyCost(A, B, Size); 224 } 225 226 const RegisterBank &AArch64RegisterBankInfo::getRegBankFromRegClass( 227 const TargetRegisterClass &RC) const { 228 switch (RC.getID()) { 229 case AArch64::FPR8RegClassID: 230 case AArch64::FPR16RegClassID: 231 case AArch64::FPR32RegClassID: 232 case AArch64::FPR64RegClassID: 233 case AArch64::FPR128RegClassID: 234 case AArch64::FPR128_loRegClassID: 235 case AArch64::DDRegClassID: 236 case AArch64::DDDRegClassID: 237 case AArch64::DDDDRegClassID: 238 case AArch64::QQRegClassID: 239 case AArch64::QQQRegClassID: 240 case AArch64::QQQQRegClassID: 241 return getRegBank(AArch64::FPRRegBankID); 242 case AArch64::GPR32commonRegClassID: 243 case AArch64::GPR32RegClassID: 244 case AArch64::GPR32spRegClassID: 245 case AArch64::GPR32sponlyRegClassID: 246 case AArch64::GPR32allRegClassID: 247 case AArch64::GPR64commonRegClassID: 248 case AArch64::GPR64RegClassID: 249 case AArch64::GPR64spRegClassID: 250 case AArch64::GPR64sponlyRegClassID: 251 case AArch64::GPR64allRegClassID: 252 case AArch64::tcGPR64RegClassID: 253 case AArch64::WSeqPairsClassRegClassID: 254 case AArch64::XSeqPairsClassRegClassID: 255 return getRegBank(AArch64::GPRRegBankID); 256 case AArch64::CCRRegClassID: 257 return getRegBank(AArch64::CCRegBankID); 258 default: 259 llvm_unreachable("Register class not supported"); 260 } 261 } 262 263 RegisterBankInfo::InstructionMappings 264 AArch64RegisterBankInfo::getInstrAlternativeMappings( 265 const MachineInstr &MI) const { 266 const MachineFunction &MF = *MI.getParent()->getParent(); 267 const TargetSubtargetInfo &STI = MF.getSubtarget(); 268 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 269 const MachineRegisterInfo &MRI = MF.getRegInfo(); 270 271 switch (MI.getOpcode()) { 272 case TargetOpcode::G_OR: { 273 // 32 and 64-bit or can be mapped on either FPR or 274 // GPR for the same cost. 275 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 276 if (Size != 32 && Size != 64) 277 break; 278 279 // If the instruction has any implicit-defs or uses, 280 // do not mess with it. 281 if (MI.getNumOperands() != 3) 282 break; 283 InstructionMappings AltMappings; 284 const InstructionMapping &GPRMapping = getInstructionMapping( 285 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size), 286 /*NumOperands*/ 3); 287 const InstructionMapping &FPRMapping = getInstructionMapping( 288 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size), 289 /*NumOperands*/ 3); 290 291 AltMappings.push_back(&GPRMapping); 292 AltMappings.push_back(&FPRMapping); 293 return AltMappings; 294 } 295 case TargetOpcode::G_BITCAST: { 296 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 297 if (Size != 32 && Size != 64) 298 break; 299 300 // If the instruction has any implicit-defs or uses, 301 // do not mess with it. 302 if (MI.getNumOperands() != 2) 303 break; 304 305 InstructionMappings AltMappings; 306 const InstructionMapping &GPRMapping = getInstructionMapping( 307 /*ID*/ 1, /*Cost*/ 1, 308 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size), 309 /*NumOperands*/ 2); 310 const InstructionMapping &FPRMapping = getInstructionMapping( 311 /*ID*/ 2, /*Cost*/ 1, 312 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size), 313 /*NumOperands*/ 2); 314 const InstructionMapping &GPRToFPRMapping = getInstructionMapping( 315 /*ID*/ 3, 316 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size), 317 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size), 318 /*NumOperands*/ 2); 319 const InstructionMapping &FPRToGPRMapping = getInstructionMapping( 320 /*ID*/ 3, 321 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size), 322 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size), 323 /*NumOperands*/ 2); 324 325 AltMappings.push_back(&GPRMapping); 326 AltMappings.push_back(&FPRMapping); 327 AltMappings.push_back(&GPRToFPRMapping); 328 AltMappings.push_back(&FPRToGPRMapping); 329 return AltMappings; 330 } 331 case TargetOpcode::G_LOAD: { 332 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 333 if (Size != 64) 334 break; 335 336 // If the instruction has any implicit-defs or uses, 337 // do not mess with it. 338 if (MI.getNumOperands() != 2) 339 break; 340 341 InstructionMappings AltMappings; 342 const InstructionMapping &GPRMapping = getInstructionMapping( 343 /*ID*/ 1, /*Cost*/ 1, 344 getOperandsMapping({getValueMapping(PMI_FirstGPR, Size), 345 // Addresses are GPR 64-bit. 346 getValueMapping(PMI_FirstGPR, 64)}), 347 /*NumOperands*/ 2); 348 const InstructionMapping &FPRMapping = getInstructionMapping( 349 /*ID*/ 2, /*Cost*/ 1, 350 getOperandsMapping({getValueMapping(PMI_FirstFPR, Size), 351 // Addresses are GPR 64-bit. 352 getValueMapping(PMI_FirstGPR, 64)}), 353 /*NumOperands*/ 2); 354 355 AltMappings.push_back(&GPRMapping); 356 AltMappings.push_back(&FPRMapping); 357 return AltMappings; 358 } 359 default: 360 break; 361 } 362 return RegisterBankInfo::getInstrAlternativeMappings(MI); 363 } 364 365 void AArch64RegisterBankInfo::applyMappingImpl( 366 const OperandsMapper &OpdMapper) const { 367 switch (OpdMapper.getMI().getOpcode()) { 368 case TargetOpcode::G_OR: 369 case TargetOpcode::G_BITCAST: 370 case TargetOpcode::G_LOAD: 371 // Those ID must match getInstrAlternativeMappings. 372 assert((OpdMapper.getInstrMapping().getID() >= 1 && 373 OpdMapper.getInstrMapping().getID() <= 4) && 374 "Don't know how to handle that ID"); 375 return applyDefaultMapping(OpdMapper); 376 default: 377 llvm_unreachable("Don't know how to handle that operation"); 378 } 379 } 380 381 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode, 382 /// having only floating-point operands. 383 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) { 384 switch (Opc) { 385 case TargetOpcode::G_FADD: 386 case TargetOpcode::G_FSUB: 387 case TargetOpcode::G_FMUL: 388 case TargetOpcode::G_FDIV: 389 case TargetOpcode::G_FCONSTANT: 390 case TargetOpcode::G_FPEXT: 391 case TargetOpcode::G_FPTRUNC: 392 return true; 393 } 394 return false; 395 } 396 397 const RegisterBankInfo::InstructionMapping & 398 AArch64RegisterBankInfo::getSameKindOfOperandsMapping( 399 const MachineInstr &MI) const { 400 const unsigned Opc = MI.getOpcode(); 401 const MachineFunction &MF = *MI.getParent()->getParent(); 402 const MachineRegisterInfo &MRI = MF.getRegInfo(); 403 404 unsigned NumOperands = MI.getNumOperands(); 405 assert(NumOperands <= 3 && 406 "This code is for instructions with 3 or less operands"); 407 408 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 409 unsigned Size = Ty.getSizeInBits(); 410 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc); 411 412 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR; 413 414 #ifndef NDEBUG 415 // Make sure all the operands are using similar size and type. 416 // Should probably be checked by the machine verifier. 417 // This code won't catch cases where the number of lanes is 418 // different between the operands. 419 // If we want to go to that level of details, it is probably 420 // best to check that the types are the same, period. 421 // Currently, we just check that the register banks are the same 422 // for each types. 423 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) { 424 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg()); 425 assert( 426 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset( 427 RBIdx, OpTy.getSizeInBits()) == 428 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) && 429 "Operand has incompatible size"); 430 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc); 431 (void)OpIsFPR; 432 assert(IsFPR == OpIsFPR && "Operand has incompatible type"); 433 } 434 #endif // End NDEBUG. 435 436 return getInstructionMapping(DefaultMappingID, 1, 437 getValueMapping(RBIdx, Size), NumOperands); 438 } 439 440 const RegisterBankInfo::InstructionMapping & 441 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 442 const unsigned Opc = MI.getOpcode(); 443 444 // Try the default logic for non-generic instructions that are either copies 445 // or already have some operands assigned to banks. 446 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) || 447 Opc == TargetOpcode::G_PHI) { 448 const RegisterBankInfo::InstructionMapping &Mapping = 449 getInstrMappingImpl(MI); 450 if (Mapping.isValid()) 451 return Mapping; 452 } 453 454 const MachineFunction &MF = *MI.getParent()->getParent(); 455 const MachineRegisterInfo &MRI = MF.getRegInfo(); 456 const TargetSubtargetInfo &STI = MF.getSubtarget(); 457 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 458 459 switch (Opc) { 460 // G_{F|S|U}REM are not listed because they are not legal. 461 // Arithmetic ops. 462 case TargetOpcode::G_ADD: 463 case TargetOpcode::G_SUB: 464 case TargetOpcode::G_GEP: 465 case TargetOpcode::G_MUL: 466 case TargetOpcode::G_SDIV: 467 case TargetOpcode::G_UDIV: 468 // Bitwise ops. 469 case TargetOpcode::G_AND: 470 case TargetOpcode::G_OR: 471 case TargetOpcode::G_XOR: 472 // Shifts. 473 case TargetOpcode::G_SHL: 474 case TargetOpcode::G_LSHR: 475 case TargetOpcode::G_ASHR: 476 // Floating point ops. 477 case TargetOpcode::G_FADD: 478 case TargetOpcode::G_FSUB: 479 case TargetOpcode::G_FMUL: 480 case TargetOpcode::G_FDIV: 481 return getSameKindOfOperandsMapping(MI); 482 case TargetOpcode::G_FPEXT: { 483 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 484 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 485 return getInstructionMapping( 486 DefaultMappingID, /*Cost*/ 1, 487 getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()), 488 /*NumOperands*/ 2); 489 } 490 case TargetOpcode::COPY: { 491 unsigned DstReg = MI.getOperand(0).getReg(); 492 unsigned SrcReg = MI.getOperand(1).getReg(); 493 // Check if one of the register is not a generic register. 494 if ((TargetRegisterInfo::isPhysicalRegister(DstReg) || 495 !MRI.getType(DstReg).isValid()) || 496 (TargetRegisterInfo::isPhysicalRegister(SrcReg) || 497 !MRI.getType(SrcReg).isValid())) { 498 const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI); 499 const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI); 500 if (!DstRB) 501 DstRB = SrcRB; 502 else if (!SrcRB) 503 SrcRB = DstRB; 504 // If both RB are null that means both registers are generic. 505 // We shouldn't be here. 506 assert(DstRB && SrcRB && "Both RegBank were nullptr"); 507 unsigned Size = getSizeInBits(DstReg, MRI, TRI); 508 return getInstructionMapping( 509 DefaultMappingID, copyCost(*DstRB, *SrcRB, Size), 510 getCopyMapping(DstRB->getID(), SrcRB->getID(), Size), 511 // We only care about the mapping of the destination. 512 /*NumOperands*/ 1); 513 } 514 // Both registers are generic, use G_BITCAST. 515 LLVM_FALLTHROUGH; 516 } 517 case TargetOpcode::G_BITCAST: { 518 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 519 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 520 unsigned Size = DstTy.getSizeInBits(); 521 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64; 522 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64; 523 const RegisterBank &DstRB = 524 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank; 525 const RegisterBank &SrcRB = 526 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank; 527 return getInstructionMapping( 528 DefaultMappingID, copyCost(DstRB, SrcRB, Size), 529 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size), 530 // We only care about the mapping of the destination for COPY. 531 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1); 532 } 533 default: 534 break; 535 } 536 537 unsigned NumOperands = MI.getNumOperands(); 538 539 // Track the size and bank of each register. We don't do partial mappings. 540 SmallVector<unsigned, 4> OpSize(NumOperands); 541 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 542 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 543 auto &MO = MI.getOperand(Idx); 544 if (!MO.isReg() || !MO.getReg()) 545 continue; 546 547 LLT Ty = MRI.getType(MO.getReg()); 548 OpSize[Idx] = Ty.getSizeInBits(); 549 550 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs. 551 // For floating-point instructions, scalars go in FPRs. 552 if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc) || 553 Ty.getSizeInBits() > 64) 554 OpRegBankIdx[Idx] = PMI_FirstFPR; 555 else 556 OpRegBankIdx[Idx] = PMI_FirstGPR; 557 } 558 559 unsigned Cost = 1; 560 // Some of the floating-point instructions have mixed GPR and FPR operands: 561 // fine-tune the computed mapping. 562 switch (Opc) { 563 case TargetOpcode::G_SITOFP: 564 case TargetOpcode::G_UITOFP: 565 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR}; 566 break; 567 case TargetOpcode::G_FPTOSI: 568 case TargetOpcode::G_FPTOUI: 569 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR}; 570 break; 571 case TargetOpcode::G_FCMP: 572 OpRegBankIdx = {PMI_FirstGPR, 573 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR}; 574 break; 575 case TargetOpcode::G_BITCAST: 576 // This is going to be a cross register bank copy and this is expensive. 577 if (OpRegBankIdx[0] != OpRegBankIdx[1]) 578 Cost = copyCost( 579 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank, 580 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank, 581 OpSize[0]); 582 break; 583 case TargetOpcode::G_LOAD: 584 // Loading in vector unit is slightly more expensive. 585 // This is actually only true for the LD1R and co instructions, 586 // but anyway for the fast mode this number does not matter and 587 // for the greedy mode the cost of the cross bank copy will 588 // offset this number. 589 // FIXME: Should be derived from the scheduling model. 590 if (OpRegBankIdx[0] != PMI_FirstGPR) 591 Cost = 2; 592 else 593 // Check if that load feeds fp instructions. 594 // In that case, we want the default mapping to be on FPR 595 // instead of blind map every scalar to GPR. 596 for (const MachineInstr &UseMI : 597 MRI.use_instructions(MI.getOperand(0).getReg())) { 598 // If we have at least one direct use in a FP instruction, 599 // assume this was a floating point load in the IR. 600 // If it was not, we would have had a bitcast before 601 // reaching that instruction. 602 unsigned UseOpc = UseMI.getOpcode(); 603 if (isPreISelGenericFloatingPointOpcode(UseOpc) || 604 // Check if we feed a copy-like instruction with 605 // floating point constraints. In that case, we are still 606 // feeding fp instructions, but indirectly 607 // (e.g., through ABI copies). 608 ((UseOpc == TargetOpcode::COPY || UseMI.isPHI()) && 609 getRegBank(UseMI.getOperand(0).getReg(), MRI, TRI) == 610 &AArch64::FPRRegBank)) { 611 OpRegBankIdx[0] = PMI_FirstFPR; 612 break; 613 } 614 } 615 break; 616 case TargetOpcode::G_STORE: 617 // Check if that store is fed by fp instructions. 618 if (OpRegBankIdx[0] == PMI_FirstGPR) { 619 unsigned VReg = MI.getOperand(0).getReg(); 620 if (!VReg) 621 break; 622 MachineInstr *DefMI = MRI.getVRegDef(VReg); 623 unsigned DefOpc = DefMI->getOpcode(); 624 if (isPreISelGenericFloatingPointOpcode(DefOpc) || 625 // Check if we come from a copy-like instruction with 626 // floating point constraints. In that case, we are still 627 // fed by fp instructions, but indirectly 628 // (e.g., through ABI copies). 629 ((DefOpc == TargetOpcode::COPY || DefMI->isPHI()) && 630 getRegBank(DefMI->getOperand(0).getReg(), MRI, TRI) == 631 &AArch64::FPRRegBank)) 632 OpRegBankIdx[0] = PMI_FirstFPR; 633 break; 634 } 635 } 636 637 // Finally construct the computed mapping. 638 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 639 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 640 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) { 641 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]); 642 if (!Mapping->isValid()) 643 return getInvalidInstructionMapping(); 644 645 OpdsMapping[Idx] = Mapping; 646 } 647 } 648 649 return getInstructionMapping(DefaultMappingID, Cost, 650 getOperandsMapping(OpdsMapping), NumOperands); 651 } 652