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