1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===// 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 10 /// AArch64. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "AArch64RegisterBankInfo.h" 15 #include "AArch64RegisterInfo.h" 16 #include "MCTargetDesc/AArch64MCTargetDesc.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 20 #include "llvm/CodeGen/GlobalISel/Utils.h" 21 #include "llvm/CodeGen/LowLevelTypeUtils.h" 22 #include "llvm/CodeGen/MachineFunction.h" 23 #include "llvm/CodeGen/MachineInstr.h" 24 #include "llvm/CodeGen/MachineOperand.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/CodeGen/RegisterBank.h" 27 #include "llvm/CodeGen/RegisterBankInfo.h" 28 #include "llvm/CodeGen/TargetOpcodes.h" 29 #include "llvm/CodeGen/TargetRegisterInfo.h" 30 #include "llvm/CodeGen/TargetSubtargetInfo.h" 31 #include "llvm/IR/IntrinsicsAArch64.h" 32 #include "llvm/Support/ErrorHandling.h" 33 #include <algorithm> 34 #include <cassert> 35 36 #define GET_TARGET_REGBANK_IMPL 37 #include "AArch64GenRegisterBank.inc" 38 39 // This file will be TableGen'ed at some point. 40 #include "AArch64GenRegisterBankInfo.def" 41 42 using namespace llvm; 43 44 AArch64RegisterBankInfo::AArch64RegisterBankInfo( 45 const TargetRegisterInfo &TRI) { 46 static llvm::once_flag InitializeRegisterBankFlag; 47 48 static auto InitializeRegisterBankOnce = [&]() { 49 // We have only one set of register banks, whatever the subtarget 50 // is. Therefore, the initialization of the RegBanks table should be 51 // done only once. Indeed the table of all register banks 52 // (AArch64::RegBanks) is unique in the compiler. At some point, it 53 // will get tablegen'ed and the whole constructor becomes empty. 54 55 const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID); 56 (void)RBGPR; 57 assert(&AArch64::GPRRegBank == &RBGPR && 58 "The order in RegBanks is messed up"); 59 60 const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID); 61 (void)RBFPR; 62 assert(&AArch64::FPRRegBank == &RBFPR && 63 "The order in RegBanks is messed up"); 64 65 const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID); 66 (void)RBCCR; 67 assert(&AArch64::CCRegBank == &RBCCR && 68 "The order in RegBanks is messed up"); 69 70 // The GPR register bank is fully defined by all the registers in 71 // GR64all + its subclasses. 72 assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) && 73 "Subclass not added?"); 74 assert(getMaximumSize(RBGPR.getID()) == 128 && 75 "GPRs should hold up to 128-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(getMaximumSize(RBFPR.getID()) == 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(getMaximumSize(RBCCR.getID()) == 32 && 89 "CCR should hold up to 32-bit"); 90 91 // Check that the TableGen'ed like file is in sync we our expectations. 92 // First, the Idx. 93 assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR, 94 {PMI_GPR32, PMI_GPR64, PMI_GPR128}) && 95 "PartialMappingIdx's are incorrectly ordered"); 96 assert(checkPartialMappingIdx(PMI_FirstFPR, PMI_LastFPR, 97 {PMI_FPR16, PMI_FPR32, PMI_FPR64, PMI_FPR128, 98 PMI_FPR256, PMI_FPR512}) && 99 "PartialMappingIdx's are incorrectly ordered"); 100 // Now, the content. 101 // Check partial mapping. 102 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \ 103 do { \ 104 assert( \ 105 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \ 106 #Idx " is incorrectly initialized"); \ 107 } while (false) 108 109 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR); 110 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR); 111 CHECK_PARTIALMAP(PMI_GPR128, 0, 128, RBGPR); 112 CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR); 113 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR); 114 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR); 115 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR); 116 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR); 117 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR); 118 119 // Check value mapping. 120 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \ 121 do { \ 122 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \ 123 PartialMappingIdx::PMI_First##RBName, Size, \ 124 Offset) && \ 125 #RBName #Size " " #Offset " is incorrectly initialized"); \ 126 } while (false) 127 128 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0) 129 130 CHECK_VALUEMAP(GPR, 32); 131 CHECK_VALUEMAP(GPR, 64); 132 CHECK_VALUEMAP(GPR, 128); 133 CHECK_VALUEMAP(FPR, 16); 134 CHECK_VALUEMAP(FPR, 32); 135 CHECK_VALUEMAP(FPR, 64); 136 CHECK_VALUEMAP(FPR, 128); 137 CHECK_VALUEMAP(FPR, 256); 138 CHECK_VALUEMAP(FPR, 512); 139 140 // Check the value mapping for 3-operands instructions where all the operands 141 // map to the same value mapping. 142 #define CHECK_VALUEMAP_3OPS(RBName, Size) \ 143 do { \ 144 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \ 145 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \ 146 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \ 147 } while (false) 148 149 CHECK_VALUEMAP_3OPS(GPR, 32); 150 CHECK_VALUEMAP_3OPS(GPR, 64); 151 CHECK_VALUEMAP_3OPS(GPR, 128); 152 CHECK_VALUEMAP_3OPS(FPR, 32); 153 CHECK_VALUEMAP_3OPS(FPR, 64); 154 CHECK_VALUEMAP_3OPS(FPR, 128); 155 CHECK_VALUEMAP_3OPS(FPR, 256); 156 CHECK_VALUEMAP_3OPS(FPR, 512); 157 158 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \ 159 do { \ 160 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \ 161 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \ 162 (void)PartialMapDstIdx; \ 163 (void)PartialMapSrcIdx; \ 164 const ValueMapping *Map = getCopyMapping( \ 165 AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \ 166 (void)Map; \ 167 assert(Map[0].BreakDown == \ 168 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \ 169 Map[0].NumBreakDowns == 1 && #RBNameDst #Size \ 170 " Dst is incorrectly initialized"); \ 171 assert(Map[1].BreakDown == \ 172 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \ 173 Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \ 174 " Src is incorrectly initialized"); \ 175 \ 176 } while (false) 177 178 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32); 179 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32); 180 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64); 181 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64); 182 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32); 183 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32); 184 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64); 185 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64); 186 187 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \ 188 do { \ 189 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \ 190 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \ 191 (void)PartialMapDstIdx; \ 192 (void)PartialMapSrcIdx; \ 193 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \ 194 (void)Map; \ 195 assert(Map[0].BreakDown == \ 196 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \ 197 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \ 198 " Dst is incorrectly initialized"); \ 199 assert(Map[1].BreakDown == \ 200 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \ 201 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \ 202 " Src is incorrectly initialized"); \ 203 \ 204 } while (false) 205 206 CHECK_VALUEMAP_FPEXT(32, 16); 207 CHECK_VALUEMAP_FPEXT(64, 16); 208 CHECK_VALUEMAP_FPEXT(64, 32); 209 CHECK_VALUEMAP_FPEXT(128, 64); 210 211 assert(verify(TRI) && "Invalid register bank information"); 212 }; 213 214 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce); 215 } 216 217 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A, 218 const RegisterBank &B, 219 unsigned Size) const { 220 // What do we do with different size? 221 // copy are same size. 222 // Will introduce other hooks for different size: 223 // * extract cost. 224 // * build_sequence cost. 225 226 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV. 227 // FIXME: This should be deduced from the scheduling model. 228 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank) 229 // FMOVXDr or FMOVWSr. 230 return 5; 231 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank) 232 // FMOVDXr or FMOVSWr. 233 return 4; 234 235 return RegisterBankInfo::copyCost(A, B, Size); 236 } 237 238 const RegisterBank & 239 AArch64RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 240 LLT) const { 241 switch (RC.getID()) { 242 case AArch64::FPR8RegClassID: 243 case AArch64::FPR16RegClassID: 244 case AArch64::FPR16_loRegClassID: 245 case AArch64::FPR32_with_hsub_in_FPR16_loRegClassID: 246 case AArch64::FPR32RegClassID: 247 case AArch64::FPR64RegClassID: 248 case AArch64::FPR64_loRegClassID: 249 case AArch64::FPR128RegClassID: 250 case AArch64::FPR128_loRegClassID: 251 case AArch64::DDRegClassID: 252 case AArch64::DDDRegClassID: 253 case AArch64::DDDDRegClassID: 254 case AArch64::QQRegClassID: 255 case AArch64::QQQRegClassID: 256 case AArch64::QQQQRegClassID: 257 return getRegBank(AArch64::FPRRegBankID); 258 case AArch64::GPR32commonRegClassID: 259 case AArch64::GPR32RegClassID: 260 case AArch64::GPR32spRegClassID: 261 case AArch64::GPR32sponlyRegClassID: 262 case AArch64::GPR32argRegClassID: 263 case AArch64::GPR32allRegClassID: 264 case AArch64::GPR64commonRegClassID: 265 case AArch64::GPR64RegClassID: 266 case AArch64::GPR64spRegClassID: 267 case AArch64::GPR64sponlyRegClassID: 268 case AArch64::GPR64argRegClassID: 269 case AArch64::GPR64allRegClassID: 270 case AArch64::GPR64noipRegClassID: 271 case AArch64::GPR64common_and_GPR64noipRegClassID: 272 case AArch64::GPR64noip_and_tcGPR64RegClassID: 273 case AArch64::tcGPR64RegClassID: 274 case AArch64::rtcGPR64RegClassID: 275 case AArch64::WSeqPairsClassRegClassID: 276 case AArch64::XSeqPairsClassRegClassID: 277 case AArch64::MatrixIndexGPR32_8_11RegClassID: 278 case AArch64::MatrixIndexGPR32_12_15RegClassID: 279 case AArch64::GPR64_with_sub_32_in_MatrixIndexGPR32_8_11RegClassID: 280 case AArch64::GPR64_with_sub_32_in_MatrixIndexGPR32_12_15RegClassID: 281 return getRegBank(AArch64::GPRRegBankID); 282 case AArch64::CCRRegClassID: 283 return getRegBank(AArch64::CCRegBankID); 284 default: 285 llvm_unreachable("Register class not supported"); 286 } 287 } 288 289 RegisterBankInfo::InstructionMappings 290 AArch64RegisterBankInfo::getInstrAlternativeMappings( 291 const MachineInstr &MI) const { 292 const MachineFunction &MF = *MI.getParent()->getParent(); 293 const TargetSubtargetInfo &STI = MF.getSubtarget(); 294 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 295 const MachineRegisterInfo &MRI = MF.getRegInfo(); 296 297 switch (MI.getOpcode()) { 298 case TargetOpcode::G_OR: { 299 // 32 and 64-bit or can be mapped on either FPR or 300 // GPR for the same cost. 301 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 302 if (Size != 32 && Size != 64) 303 break; 304 305 // If the instruction has any implicit-defs or uses, 306 // do not mess with it. 307 if (MI.getNumOperands() != 3) 308 break; 309 InstructionMappings AltMappings; 310 const InstructionMapping &GPRMapping = getInstructionMapping( 311 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size), 312 /*NumOperands*/ 3); 313 const InstructionMapping &FPRMapping = getInstructionMapping( 314 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size), 315 /*NumOperands*/ 3); 316 317 AltMappings.push_back(&GPRMapping); 318 AltMappings.push_back(&FPRMapping); 319 return AltMappings; 320 } 321 case TargetOpcode::G_BITCAST: { 322 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 323 if (Size != 32 && Size != 64) 324 break; 325 326 // If the instruction has any implicit-defs or uses, 327 // do not mess with it. 328 if (MI.getNumOperands() != 2) 329 break; 330 331 InstructionMappings AltMappings; 332 const InstructionMapping &GPRMapping = getInstructionMapping( 333 /*ID*/ 1, /*Cost*/ 1, 334 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size), 335 /*NumOperands*/ 2); 336 const InstructionMapping &FPRMapping = getInstructionMapping( 337 /*ID*/ 2, /*Cost*/ 1, 338 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size), 339 /*NumOperands*/ 2); 340 const InstructionMapping &GPRToFPRMapping = getInstructionMapping( 341 /*ID*/ 3, 342 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size), 343 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size), 344 /*NumOperands*/ 2); 345 const InstructionMapping &FPRToGPRMapping = getInstructionMapping( 346 /*ID*/ 3, 347 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size), 348 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size), 349 /*NumOperands*/ 2); 350 351 AltMappings.push_back(&GPRMapping); 352 AltMappings.push_back(&FPRMapping); 353 AltMappings.push_back(&GPRToFPRMapping); 354 AltMappings.push_back(&FPRToGPRMapping); 355 return AltMappings; 356 } 357 case TargetOpcode::G_LOAD: { 358 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 359 if (Size != 64) 360 break; 361 362 // If the instruction has any implicit-defs or uses, 363 // do not mess with it. 364 if (MI.getNumOperands() != 2) 365 break; 366 367 InstructionMappings AltMappings; 368 const InstructionMapping &GPRMapping = getInstructionMapping( 369 /*ID*/ 1, /*Cost*/ 1, 370 getOperandsMapping({getValueMapping(PMI_FirstGPR, Size), 371 // Addresses are GPR 64-bit. 372 getValueMapping(PMI_FirstGPR, 64)}), 373 /*NumOperands*/ 2); 374 const InstructionMapping &FPRMapping = getInstructionMapping( 375 /*ID*/ 2, /*Cost*/ 1, 376 getOperandsMapping({getValueMapping(PMI_FirstFPR, Size), 377 // Addresses are GPR 64-bit. 378 getValueMapping(PMI_FirstGPR, 64)}), 379 /*NumOperands*/ 2); 380 381 AltMappings.push_back(&GPRMapping); 382 AltMappings.push_back(&FPRMapping); 383 return AltMappings; 384 } 385 default: 386 break; 387 } 388 return RegisterBankInfo::getInstrAlternativeMappings(MI); 389 } 390 391 void AArch64RegisterBankInfo::applyMappingImpl( 392 const OperandsMapper &OpdMapper) const { 393 switch (OpdMapper.getMI().getOpcode()) { 394 case TargetOpcode::G_OR: 395 case TargetOpcode::G_BITCAST: 396 case TargetOpcode::G_LOAD: 397 // Those ID must match getInstrAlternativeMappings. 398 assert((OpdMapper.getInstrMapping().getID() >= 1 && 399 OpdMapper.getInstrMapping().getID() <= 4) && 400 "Don't know how to handle that ID"); 401 return applyDefaultMapping(OpdMapper); 402 default: 403 llvm_unreachable("Don't know how to handle that operation"); 404 } 405 } 406 407 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode, 408 /// having only floating-point operands. 409 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) { 410 switch (Opc) { 411 case TargetOpcode::G_FADD: 412 case TargetOpcode::G_FSUB: 413 case TargetOpcode::G_FMUL: 414 case TargetOpcode::G_FMA: 415 case TargetOpcode::G_FDIV: 416 case TargetOpcode::G_FCONSTANT: 417 case TargetOpcode::G_FPEXT: 418 case TargetOpcode::G_FPTRUNC: 419 case TargetOpcode::G_FCEIL: 420 case TargetOpcode::G_FFLOOR: 421 case TargetOpcode::G_FNEARBYINT: 422 case TargetOpcode::G_FNEG: 423 case TargetOpcode::G_FCOS: 424 case TargetOpcode::G_FSIN: 425 case TargetOpcode::G_FLOG10: 426 case TargetOpcode::G_FLOG: 427 case TargetOpcode::G_FLOG2: 428 case TargetOpcode::G_FSQRT: 429 case TargetOpcode::G_FABS: 430 case TargetOpcode::G_FEXP: 431 case TargetOpcode::G_FRINT: 432 case TargetOpcode::G_INTRINSIC_TRUNC: 433 case TargetOpcode::G_INTRINSIC_ROUND: 434 case TargetOpcode::G_FMAXNUM: 435 case TargetOpcode::G_FMINNUM: 436 case TargetOpcode::G_FMAXIMUM: 437 case TargetOpcode::G_FMINIMUM: 438 return true; 439 } 440 return false; 441 } 442 443 const RegisterBankInfo::InstructionMapping & 444 AArch64RegisterBankInfo::getSameKindOfOperandsMapping( 445 const MachineInstr &MI) const { 446 const unsigned Opc = MI.getOpcode(); 447 const MachineFunction &MF = *MI.getParent()->getParent(); 448 const MachineRegisterInfo &MRI = MF.getRegInfo(); 449 450 unsigned NumOperands = MI.getNumOperands(); 451 assert(NumOperands <= 3 && 452 "This code is for instructions with 3 or less operands"); 453 454 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 455 unsigned Size = Ty.getSizeInBits(); 456 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc); 457 458 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR; 459 460 #ifndef NDEBUG 461 // Make sure all the operands are using similar size and type. 462 // Should probably be checked by the machine verifier. 463 // This code won't catch cases where the number of lanes is 464 // different between the operands. 465 // If we want to go to that level of details, it is probably 466 // best to check that the types are the same, period. 467 // Currently, we just check that the register banks are the same 468 // for each types. 469 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) { 470 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg()); 471 assert( 472 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset( 473 RBIdx, OpTy.getSizeInBits()) == 474 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) && 475 "Operand has incompatible size"); 476 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc); 477 (void)OpIsFPR; 478 assert(IsFPR == OpIsFPR && "Operand has incompatible type"); 479 } 480 #endif // End NDEBUG. 481 482 return getInstructionMapping(DefaultMappingID, 1, 483 getValueMapping(RBIdx, Size), NumOperands); 484 } 485 486 /// \returns true if a given intrinsic only uses and defines FPRs. 487 static bool isFPIntrinsic(const MachineRegisterInfo &MRI, 488 const MachineInstr &MI) { 489 assert(MI.getOpcode() == TargetOpcode::G_INTRINSIC); 490 // TODO: Add more intrinsics. 491 switch (MI.getIntrinsicID()) { 492 default: 493 return false; 494 case Intrinsic::aarch64_neon_uaddlv: 495 case Intrinsic::aarch64_neon_uaddv: 496 case Intrinsic::aarch64_neon_umaxv: 497 case Intrinsic::aarch64_neon_uminv: 498 case Intrinsic::aarch64_neon_fmaxv: 499 case Intrinsic::aarch64_neon_fminv: 500 case Intrinsic::aarch64_neon_fmaxnmv: 501 case Intrinsic::aarch64_neon_fminnmv: 502 return true; 503 case Intrinsic::aarch64_neon_saddlv: { 504 const LLT SrcTy = MRI.getType(MI.getOperand(2).getReg()); 505 return SrcTy.getElementType().getSizeInBits() >= 16 && 506 SrcTy.getElementCount().getFixedValue() >= 4; 507 } 508 case Intrinsic::aarch64_neon_saddv: 509 case Intrinsic::aarch64_neon_smaxv: 510 case Intrinsic::aarch64_neon_sminv: { 511 const LLT SrcTy = MRI.getType(MI.getOperand(2).getReg()); 512 return SrcTy.getElementType().getSizeInBits() >= 32 && 513 SrcTy.getElementCount().getFixedValue() >= 2; 514 } 515 } 516 } 517 518 bool AArch64RegisterBankInfo::hasFPConstraints(const MachineInstr &MI, 519 const MachineRegisterInfo &MRI, 520 const TargetRegisterInfo &TRI, 521 unsigned Depth) const { 522 unsigned Op = MI.getOpcode(); 523 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI)) 524 return true; 525 526 // Do we have an explicit floating point instruction? 527 if (isPreISelGenericFloatingPointOpcode(Op)) 528 return true; 529 530 // No. Check if we have a copy-like instruction. If we do, then we could 531 // still be fed by floating point instructions. 532 if (Op != TargetOpcode::COPY && !MI.isPHI() && 533 !isPreISelGenericOptimizationHint(Op)) 534 return false; 535 536 // Check if we already know the register bank. 537 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI); 538 if (RB == &AArch64::FPRRegBank) 539 return true; 540 if (RB == &AArch64::GPRRegBank) 541 return false; 542 543 // We don't know anything. 544 // 545 // If we have a phi, we may be able to infer that it will be assigned a FPR 546 // based off of its inputs. 547 if (!MI.isPHI() || Depth > MaxFPRSearchDepth) 548 return false; 549 550 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) { 551 return Op.isReg() && 552 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1); 553 }); 554 } 555 556 bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI, 557 const MachineRegisterInfo &MRI, 558 const TargetRegisterInfo &TRI, 559 unsigned Depth) const { 560 switch (MI.getOpcode()) { 561 case TargetOpcode::G_FPTOSI: 562 case TargetOpcode::G_FPTOUI: 563 case TargetOpcode::G_FCMP: 564 case TargetOpcode::G_LROUND: 565 case TargetOpcode::G_LLROUND: 566 return true; 567 default: 568 break; 569 } 570 return hasFPConstraints(MI, MRI, TRI, Depth); 571 } 572 573 bool AArch64RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, 574 const MachineRegisterInfo &MRI, 575 const TargetRegisterInfo &TRI, 576 unsigned Depth) const { 577 switch (MI.getOpcode()) { 578 case AArch64::G_DUP: 579 case TargetOpcode::G_SITOFP: 580 case TargetOpcode::G_UITOFP: 581 case TargetOpcode::G_EXTRACT_VECTOR_ELT: 582 case TargetOpcode::G_INSERT_VECTOR_ELT: 583 case TargetOpcode::G_BUILD_VECTOR: 584 case TargetOpcode::G_BUILD_VECTOR_TRUNC: 585 return true; 586 default: 587 break; 588 } 589 return hasFPConstraints(MI, MRI, TRI, Depth); 590 } 591 592 const RegisterBankInfo::InstructionMapping & 593 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 594 const unsigned Opc = MI.getOpcode(); 595 596 // Try the default logic for non-generic instructions that are either copies 597 // or already have some operands assigned to banks. 598 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) || 599 Opc == TargetOpcode::G_PHI) { 600 const RegisterBankInfo::InstructionMapping &Mapping = 601 getInstrMappingImpl(MI); 602 if (Mapping.isValid()) 603 return Mapping; 604 } 605 606 const MachineFunction &MF = *MI.getParent()->getParent(); 607 const MachineRegisterInfo &MRI = MF.getRegInfo(); 608 const TargetSubtargetInfo &STI = MF.getSubtarget(); 609 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 610 611 switch (Opc) { 612 // G_{F|S|U}REM are not listed because they are not legal. 613 // Arithmetic ops. 614 case TargetOpcode::G_ADD: 615 case TargetOpcode::G_SUB: 616 case TargetOpcode::G_PTR_ADD: 617 case TargetOpcode::G_MUL: 618 case TargetOpcode::G_SDIV: 619 case TargetOpcode::G_UDIV: 620 // Bitwise ops. 621 case TargetOpcode::G_AND: 622 case TargetOpcode::G_OR: 623 case TargetOpcode::G_XOR: 624 // Floating point ops. 625 case TargetOpcode::G_FADD: 626 case TargetOpcode::G_FSUB: 627 case TargetOpcode::G_FMUL: 628 case TargetOpcode::G_FDIV: 629 case TargetOpcode::G_FMAXIMUM: 630 case TargetOpcode::G_FMINIMUM: 631 return getSameKindOfOperandsMapping(MI); 632 case TargetOpcode::G_FPEXT: { 633 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 634 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 635 return getInstructionMapping( 636 DefaultMappingID, /*Cost*/ 1, 637 getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()), 638 /*NumOperands*/ 2); 639 } 640 // Shifts. 641 case TargetOpcode::G_SHL: 642 case TargetOpcode::G_LSHR: 643 case TargetOpcode::G_ASHR: { 644 LLT ShiftAmtTy = MRI.getType(MI.getOperand(2).getReg()); 645 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 646 if (ShiftAmtTy.getSizeInBits() == 64 && SrcTy.getSizeInBits() == 32) 647 return getInstructionMapping(DefaultMappingID, 1, 648 &ValMappings[Shift64Imm], 3); 649 return getSameKindOfOperandsMapping(MI); 650 } 651 case TargetOpcode::COPY: { 652 Register DstReg = MI.getOperand(0).getReg(); 653 Register SrcReg = MI.getOperand(1).getReg(); 654 // Check if one of the register is not a generic register. 655 if ((DstReg.isPhysical() || !MRI.getType(DstReg).isValid()) || 656 (SrcReg.isPhysical() || !MRI.getType(SrcReg).isValid())) { 657 const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI); 658 const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI); 659 if (!DstRB) 660 DstRB = SrcRB; 661 else if (!SrcRB) 662 SrcRB = DstRB; 663 // If both RB are null that means both registers are generic. 664 // We shouldn't be here. 665 assert(DstRB && SrcRB && "Both RegBank were nullptr"); 666 unsigned Size = getSizeInBits(DstReg, MRI, TRI); 667 return getInstructionMapping( 668 DefaultMappingID, copyCost(*DstRB, *SrcRB, Size), 669 getCopyMapping(DstRB->getID(), SrcRB->getID(), Size), 670 // We only care about the mapping of the destination. 671 /*NumOperands*/ 1); 672 } 673 // Both registers are generic, use G_BITCAST. 674 [[fallthrough]]; 675 } 676 case TargetOpcode::G_BITCAST: { 677 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 678 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 679 unsigned Size = DstTy.getSizeInBits(); 680 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64; 681 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64; 682 const RegisterBank &DstRB = 683 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank; 684 const RegisterBank &SrcRB = 685 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank; 686 return getInstructionMapping( 687 DefaultMappingID, copyCost(DstRB, SrcRB, Size), 688 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size), 689 // We only care about the mapping of the destination for COPY. 690 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1); 691 } 692 default: 693 break; 694 } 695 696 unsigned NumOperands = MI.getNumOperands(); 697 698 // Track the size and bank of each register. We don't do partial mappings. 699 SmallVector<unsigned, 4> OpSize(NumOperands); 700 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 701 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 702 auto &MO = MI.getOperand(Idx); 703 if (!MO.isReg() || !MO.getReg()) 704 continue; 705 706 LLT Ty = MRI.getType(MO.getReg()); 707 if (!Ty.isValid()) 708 continue; 709 OpSize[Idx] = Ty.getSizeInBits(); 710 711 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs. 712 // For floating-point instructions, scalars go in FPRs. 713 if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc) || 714 Ty.getSizeInBits() > 64) 715 OpRegBankIdx[Idx] = PMI_FirstFPR; 716 else 717 OpRegBankIdx[Idx] = PMI_FirstGPR; 718 } 719 720 unsigned Cost = 1; 721 // Some of the floating-point instructions have mixed GPR and FPR operands: 722 // fine-tune the computed mapping. 723 switch (Opc) { 724 case AArch64::G_DUP: { 725 Register ScalarReg = MI.getOperand(1).getReg(); 726 LLT ScalarTy = MRI.getType(ScalarReg); 727 auto ScalarDef = MRI.getVRegDef(ScalarReg); 728 // s8 is an exception for G_DUP, which we always want on gpr. 729 if (ScalarTy.getSizeInBits() != 8 && 730 (getRegBank(ScalarReg, MRI, TRI) == &AArch64::FPRRegBank || 731 onlyDefinesFP(*ScalarDef, MRI, TRI))) 732 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR}; 733 else 734 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR}; 735 break; 736 } 737 case TargetOpcode::G_TRUNC: { 738 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 739 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128) 740 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR}; 741 break; 742 } 743 case TargetOpcode::G_SITOFP: 744 case TargetOpcode::G_UITOFP: { 745 if (MRI.getType(MI.getOperand(0).getReg()).isVector()) 746 break; 747 // Integer to FP conversions don't necessarily happen between GPR -> FPR 748 // regbanks. They can also be done within an FPR register. 749 Register SrcReg = MI.getOperand(1).getReg(); 750 if (getRegBank(SrcReg, MRI, TRI) == &AArch64::FPRRegBank) 751 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR}; 752 else 753 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR}; 754 break; 755 } 756 case TargetOpcode::G_FPTOSI: 757 case TargetOpcode::G_FPTOUI: 758 if (MRI.getType(MI.getOperand(0).getReg()).isVector()) 759 break; 760 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR}; 761 break; 762 case TargetOpcode::G_FCMP: { 763 // If the result is a vector, it must use a FPR. 764 AArch64GenRegisterBankInfo::PartialMappingIdx Idx0 = 765 MRI.getType(MI.getOperand(0).getReg()).isVector() ? PMI_FirstFPR 766 : PMI_FirstGPR; 767 OpRegBankIdx = {Idx0, 768 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR}; 769 break; 770 } 771 case TargetOpcode::G_BITCAST: 772 // This is going to be a cross register bank copy and this is expensive. 773 if (OpRegBankIdx[0] != OpRegBankIdx[1]) 774 Cost = copyCost( 775 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank, 776 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank, 777 OpSize[0]); 778 break; 779 case TargetOpcode::G_LOAD: { 780 // Loading in vector unit is slightly more expensive. 781 // This is actually only true for the LD1R and co instructions, 782 // but anyway for the fast mode this number does not matter and 783 // for the greedy mode the cost of the cross bank copy will 784 // offset this number. 785 // FIXME: Should be derived from the scheduling model. 786 if (OpRegBankIdx[0] != PMI_FirstGPR) { 787 Cost = 2; 788 break; 789 } 790 791 if (cast<GLoad>(MI).isAtomic()) { 792 // Atomics always use GPR destinations. Don't refine any further. 793 OpRegBankIdx[0] = PMI_FirstGPR; 794 break; 795 } 796 797 // Try to guess the type of the load from the MMO. 798 const auto &MMO = **MI.memoperands_begin(); 799 const Value *LdVal = MMO.getValue(); 800 if (LdVal) { 801 Type *EltTy = nullptr; 802 if (const GlobalValue *GV = dyn_cast<GlobalValue>(LdVal)) { 803 EltTy = GV->getValueType(); 804 } else { 805 // FIXME: grubbing around uses is pretty ugly, but with no more 806 // `getPointerElementType` there's not much else we can do. 807 for (const auto *LdUser : LdVal->users()) { 808 if (isa<LoadInst>(LdUser)) { 809 EltTy = LdUser->getType(); 810 break; 811 } 812 if (isa<StoreInst>(LdUser) && LdUser->getOperand(1) == LdVal) { 813 EltTy = LdUser->getOperand(0)->getType(); 814 break; 815 } 816 } 817 } 818 if (EltTy && EltTy->isFPOrFPVectorTy()) { 819 OpRegBankIdx[0] = PMI_FirstFPR; 820 break; 821 } 822 } 823 824 // Check if that load feeds fp instructions. 825 // In that case, we want the default mapping to be on FPR 826 // instead of blind map every scalar to GPR. 827 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 828 [&](const MachineInstr &UseMI) { 829 // If we have at least one direct use in a FP instruction, 830 // assume this was a floating point load in the IR. If it was 831 // not, we would have had a bitcast before reaching that 832 // instruction. 833 // 834 // Int->FP conversion operations are also captured in 835 // onlyDefinesFP(). 836 return onlyUsesFP(UseMI, MRI, TRI) || 837 onlyDefinesFP(UseMI, MRI, TRI); 838 })) 839 OpRegBankIdx[0] = PMI_FirstFPR; 840 break; 841 } 842 case TargetOpcode::G_STORE: 843 // Check if that store is fed by fp instructions. 844 if (OpRegBankIdx[0] == PMI_FirstGPR) { 845 Register VReg = MI.getOperand(0).getReg(); 846 if (!VReg) 847 break; 848 MachineInstr *DefMI = MRI.getVRegDef(VReg); 849 if (onlyDefinesFP(*DefMI, MRI, TRI)) 850 OpRegBankIdx[0] = PMI_FirstFPR; 851 break; 852 } 853 break; 854 case TargetOpcode::G_SELECT: { 855 // If the destination is FPR, preserve that. 856 if (OpRegBankIdx[0] != PMI_FirstGPR) 857 break; 858 859 // If we're taking in vectors, we have no choice but to put everything on 860 // FPRs, except for the condition. The condition must always be on a GPR. 861 LLT SrcTy = MRI.getType(MI.getOperand(2).getReg()); 862 if (SrcTy.isVector()) { 863 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR}; 864 break; 865 } 866 867 // Try to minimize the number of copies. If we have more floating point 868 // constrained values than not, then we'll put everything on FPR. Otherwise, 869 // everything has to be on GPR. 870 unsigned NumFP = 0; 871 872 // Check if the uses of the result always produce floating point values. 873 // 874 // For example: 875 // 876 // %z = G_SELECT %cond %x %y 877 // fpr = G_FOO %z ... 878 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 879 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) 880 ++NumFP; 881 882 // Check if the defs of the source values always produce floating point 883 // values. 884 // 885 // For example: 886 // 887 // %x = G_SOMETHING_ALWAYS_FLOAT %a ... 888 // %z = G_SELECT %cond %x %y 889 // 890 // Also check whether or not the sources have already been decided to be 891 // FPR. Keep track of this. 892 // 893 // This doesn't check the condition, since it's just whatever is in NZCV. 894 // This isn't passed explicitly in a register to fcsel/csel. 895 for (unsigned Idx = 2; Idx < 4; ++Idx) { 896 Register VReg = MI.getOperand(Idx).getReg(); 897 MachineInstr *DefMI = MRI.getVRegDef(VReg); 898 if (getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank || 899 onlyDefinesFP(*DefMI, MRI, TRI)) 900 ++NumFP; 901 } 902 903 // If we have more FP constraints than not, then move everything over to 904 // FPR. 905 if (NumFP >= 2) 906 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR}; 907 908 break; 909 } 910 case TargetOpcode::G_UNMERGE_VALUES: { 911 // If the first operand belongs to a FPR register bank, then make sure that 912 // we preserve that. 913 if (OpRegBankIdx[0] != PMI_FirstGPR) 914 break; 915 916 LLT SrcTy = MRI.getType(MI.getOperand(MI.getNumOperands()-1).getReg()); 917 // UNMERGE into scalars from a vector should always use FPR. 918 // Likewise if any of the uses are FP instructions. 919 if (SrcTy.isVector() || SrcTy == LLT::scalar(128) || 920 any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 921 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) { 922 // Set the register bank of every operand to FPR. 923 for (unsigned Idx = 0, NumOperands = MI.getNumOperands(); 924 Idx < NumOperands; ++Idx) 925 OpRegBankIdx[Idx] = PMI_FirstFPR; 926 } 927 break; 928 } 929 case TargetOpcode::G_EXTRACT_VECTOR_ELT: 930 // Destination and source need to be FPRs. 931 OpRegBankIdx[0] = PMI_FirstFPR; 932 OpRegBankIdx[1] = PMI_FirstFPR; 933 934 // Index needs to be a GPR. 935 OpRegBankIdx[2] = PMI_FirstGPR; 936 break; 937 case TargetOpcode::G_INSERT_VECTOR_ELT: 938 OpRegBankIdx[0] = PMI_FirstFPR; 939 OpRegBankIdx[1] = PMI_FirstFPR; 940 941 // The element may be either a GPR or FPR. Preserve that behaviour. 942 if (getRegBank(MI.getOperand(2).getReg(), MRI, TRI) == &AArch64::FPRRegBank) 943 OpRegBankIdx[2] = PMI_FirstFPR; 944 else 945 OpRegBankIdx[2] = PMI_FirstGPR; 946 947 // Index needs to be a GPR. 948 OpRegBankIdx[3] = PMI_FirstGPR; 949 break; 950 case TargetOpcode::G_EXTRACT: { 951 // For s128 sources we have to use fpr unless we know otherwise. 952 auto Src = MI.getOperand(1).getReg(); 953 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 954 if (SrcTy.getSizeInBits() != 128) 955 break; 956 auto Idx = MRI.getRegClassOrNull(Src) == &AArch64::XSeqPairsClassRegClass 957 ? PMI_FirstGPR 958 : PMI_FirstFPR; 959 OpRegBankIdx[0] = Idx; 960 OpRegBankIdx[1] = Idx; 961 break; 962 } 963 case TargetOpcode::G_BUILD_VECTOR: { 964 // If the first source operand belongs to a FPR register bank, then make 965 // sure that we preserve that. 966 if (OpRegBankIdx[1] != PMI_FirstGPR) 967 break; 968 Register VReg = MI.getOperand(1).getReg(); 969 if (!VReg) 970 break; 971 972 // Get the instruction that defined the source operand reg, and check if 973 // it's a floating point operation. Or, if it's a type like s16 which 974 // doesn't have a exact size gpr register class. The exception is if the 975 // build_vector has all constant operands, which may be better to leave as 976 // gpr without copies, so it can be matched in imported patterns. 977 MachineInstr *DefMI = MRI.getVRegDef(VReg); 978 unsigned DefOpc = DefMI->getOpcode(); 979 const LLT SrcTy = MRI.getType(VReg); 980 if (all_of(MI.operands(), [&](const MachineOperand &Op) { 981 return Op.isDef() || MRI.getVRegDef(Op.getReg())->getOpcode() == 982 TargetOpcode::G_CONSTANT; 983 })) 984 break; 985 if (isPreISelGenericFloatingPointOpcode(DefOpc) || 986 SrcTy.getSizeInBits() < 32 || 987 getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank) { 988 // Have a floating point op. 989 // Make sure every operand gets mapped to a FPR register class. 990 unsigned NumOperands = MI.getNumOperands(); 991 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) 992 OpRegBankIdx[Idx] = PMI_FirstFPR; 993 } 994 break; 995 } 996 case TargetOpcode::G_VECREDUCE_FADD: 997 case TargetOpcode::G_VECREDUCE_FMUL: 998 case TargetOpcode::G_VECREDUCE_FMAX: 999 case TargetOpcode::G_VECREDUCE_FMIN: 1000 case TargetOpcode::G_VECREDUCE_ADD: 1001 case TargetOpcode::G_VECREDUCE_MUL: 1002 case TargetOpcode::G_VECREDUCE_AND: 1003 case TargetOpcode::G_VECREDUCE_OR: 1004 case TargetOpcode::G_VECREDUCE_XOR: 1005 case TargetOpcode::G_VECREDUCE_SMAX: 1006 case TargetOpcode::G_VECREDUCE_SMIN: 1007 case TargetOpcode::G_VECREDUCE_UMAX: 1008 case TargetOpcode::G_VECREDUCE_UMIN: 1009 // Reductions produce a scalar value from a vector, the scalar should be on 1010 // FPR bank. 1011 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR}; 1012 break; 1013 case TargetOpcode::G_VECREDUCE_SEQ_FADD: 1014 case TargetOpcode::G_VECREDUCE_SEQ_FMUL: 1015 // These reductions also take a scalar accumulator input. 1016 // Assign them FPR for now. 1017 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR, PMI_FirstFPR}; 1018 break; 1019 case TargetOpcode::G_INTRINSIC: { 1020 // Check if we know that the intrinsic has any constraints on its register 1021 // banks. If it does, then update the mapping accordingly. 1022 unsigned Idx = 0; 1023 if (!isFPIntrinsic(MRI, MI)) 1024 break; 1025 for (const auto &Op : MI.explicit_operands()) { 1026 if (Op.isReg()) 1027 OpRegBankIdx[Idx] = PMI_FirstFPR; 1028 ++Idx; 1029 } 1030 break; 1031 } 1032 case TargetOpcode::G_LROUND: 1033 case TargetOpcode::G_LLROUND: { 1034 // Source is always floating point and destination is always integer. 1035 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR}; 1036 break; 1037 } 1038 } 1039 1040 // Finally construct the computed mapping. 1041 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 1042 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 1043 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) { 1044 LLT Ty = MRI.getType(MI.getOperand(Idx).getReg()); 1045 if (!Ty.isValid()) 1046 continue; 1047 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]); 1048 if (!Mapping->isValid()) 1049 return getInvalidInstructionMapping(); 1050 1051 OpdsMapping[Idx] = Mapping; 1052 } 1053 } 1054 1055 return getInstructionMapping(DefaultMappingID, Cost, 1056 getOperandsMapping(OpdsMapping), NumOperands); 1057 } 1058