1 //===- ARMRegisterBankInfo.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 ARM. 10 /// \todo This should be generated by TableGen. 11 //===----------------------------------------------------------------------===// 12 13 #include "ARMRegisterBankInfo.h" 14 #include "ARMInstrInfo.h" // For the register classes 15 #include "ARMSubtarget.h" 16 #include "llvm/CodeGen/MachineRegisterInfo.h" 17 #include "llvm/CodeGen/RegisterBank.h" 18 #include "llvm/CodeGen/RegisterBankInfo.h" 19 #include "llvm/CodeGen/TargetRegisterInfo.h" 20 21 #define GET_TARGET_REGBANK_IMPL 22 #include "ARMGenRegisterBank.inc" 23 24 using namespace llvm; 25 26 // FIXME: TableGen this. 27 // If it grows too much and TableGen still isn't ready to do the job, extract it 28 // into an ARMGenRegisterBankInfo.def (similar to AArch64). 29 namespace llvm { 30 namespace ARM { 31 enum PartialMappingIdx { 32 PMI_GPR, 33 PMI_SPR, 34 PMI_DPR, 35 PMI_Min = PMI_GPR, 36 }; 37 38 RegisterBankInfo::PartialMapping PartMappings[]{ 39 // GPR Partial Mapping 40 {0, 32, GPRRegBank}, 41 // SPR Partial Mapping 42 {0, 32, FPRRegBank}, 43 // DPR Partial Mapping 44 {0, 64, FPRRegBank}, 45 }; 46 47 #ifndef NDEBUG 48 static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM, 49 unsigned Start, unsigned Length, 50 unsigned RegBankID) { 51 return PM.StartIdx == Start && PM.Length == Length && 52 PM.RegBank->getID() == RegBankID; 53 } 54 55 static void checkPartialMappings() { 56 assert( 57 checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) && 58 "Wrong mapping for GPR"); 59 assert( 60 checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) && 61 "Wrong mapping for SPR"); 62 assert( 63 checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) && 64 "Wrong mapping for DPR"); 65 } 66 #endif 67 68 enum ValueMappingIdx { 69 InvalidIdx = 0, 70 GPR3OpsIdx = 1, 71 SPR3OpsIdx = 4, 72 DPR3OpsIdx = 7, 73 }; 74 75 RegisterBankInfo::ValueMapping ValueMappings[] = { 76 // invalid 77 {nullptr, 0}, 78 // 3 ops in GPRs 79 {&PartMappings[PMI_GPR - PMI_Min], 1}, 80 {&PartMappings[PMI_GPR - PMI_Min], 1}, 81 {&PartMappings[PMI_GPR - PMI_Min], 1}, 82 // 3 ops in SPRs 83 {&PartMappings[PMI_SPR - PMI_Min], 1}, 84 {&PartMappings[PMI_SPR - PMI_Min], 1}, 85 {&PartMappings[PMI_SPR - PMI_Min], 1}, 86 // 3 ops in DPRs 87 {&PartMappings[PMI_DPR - PMI_Min], 1}, 88 {&PartMappings[PMI_DPR - PMI_Min], 1}, 89 {&PartMappings[PMI_DPR - PMI_Min], 1}}; 90 91 #ifndef NDEBUG 92 static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM, 93 RegisterBankInfo::PartialMapping *BreakDown) { 94 return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown; 95 } 96 97 static void checkValueMappings() { 98 assert(checkValueMapping(ValueMappings[GPR3OpsIdx], 99 &PartMappings[PMI_GPR - PMI_Min]) && 100 "Wrong value mapping for 3 GPR ops instruction"); 101 assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1], 102 &PartMappings[PMI_GPR - PMI_Min]) && 103 "Wrong value mapping for 3 GPR ops instruction"); 104 assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2], 105 &PartMappings[PMI_GPR - PMI_Min]) && 106 "Wrong value mapping for 3 GPR ops instruction"); 107 108 assert(checkValueMapping(ValueMappings[SPR3OpsIdx], 109 &PartMappings[PMI_SPR - PMI_Min]) && 110 "Wrong value mapping for 3 SPR ops instruction"); 111 assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1], 112 &PartMappings[PMI_SPR - PMI_Min]) && 113 "Wrong value mapping for 3 SPR ops instruction"); 114 assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2], 115 &PartMappings[PMI_SPR - PMI_Min]) && 116 "Wrong value mapping for 3 SPR ops instruction"); 117 118 assert(checkValueMapping(ValueMappings[DPR3OpsIdx], 119 &PartMappings[PMI_DPR - PMI_Min]) && 120 "Wrong value mapping for 3 DPR ops instruction"); 121 assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1], 122 &PartMappings[PMI_DPR - PMI_Min]) && 123 "Wrong value mapping for 3 DPR ops instruction"); 124 assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2], 125 &PartMappings[PMI_DPR - PMI_Min]) && 126 "Wrong value mapping for 3 DPR ops instruction"); 127 } 128 #endif 129 } // end namespace arm 130 } // end namespace llvm 131 132 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) { 133 // We have only one set of register banks, whatever the subtarget 134 // is. Therefore, the initialization of the RegBanks table should be 135 // done only once. Indeed the table of all register banks 136 // (ARM::RegBanks) is unique in the compiler. At some point, it 137 // will get tablegen'ed and the whole constructor becomes empty. 138 static llvm::once_flag InitializeRegisterBankFlag; 139 140 static auto InitializeRegisterBankOnce = [&]() { 141 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 142 (void)RBGPR; 143 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 144 145 // Initialize the GPR bank. 146 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 147 "Subclass not added?"); 148 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 149 "Subclass not added?"); 150 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 151 "Subclass not added?"); 152 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 153 "Subclass not added?"); 154 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 155 "Subclass not added?"); 156 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 157 "Subclass not added?"); 158 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnoip_and_tcGPRRegClassID)) && 159 "Subclass not added?"); 160 assert(RBGPR.covers(*TRI.getRegClass( 161 ARM::tGPREven_and_GPRnoip_and_tcGPRRegClassID)) && 162 "Subclass not added?"); 163 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) && 164 "Subclass not added?"); 165 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 166 167 #ifndef NDEBUG 168 ARM::checkPartialMappings(); 169 ARM::checkValueMappings(); 170 #endif 171 }; 172 173 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce); 174 } 175 176 const RegisterBank & 177 ARMRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 178 LLT) const { 179 using namespace ARM; 180 181 switch (RC.getID()) { 182 case GPRRegClassID: 183 case GPRwithAPSRRegClassID: 184 case GPRnoipRegClassID: 185 case GPRnopcRegClassID: 186 case GPRnoip_and_GPRnopcRegClassID: 187 case rGPRRegClassID: 188 case GPRspRegClassID: 189 case GPRnoip_and_tcGPRRegClassID: 190 case tcGPRRegClassID: 191 case tGPRRegClassID: 192 case tGPREvenRegClassID: 193 case tGPROddRegClassID: 194 case tGPR_and_tGPREvenRegClassID: 195 case tGPR_and_tGPROddRegClassID: 196 case tGPREven_and_tcGPRRegClassID: 197 case tGPREven_and_GPRnoip_and_tcGPRRegClassID: 198 case tGPROdd_and_tcGPRRegClassID: 199 return getRegBank(ARM::GPRRegBankID); 200 case HPRRegClassID: 201 case SPR_8RegClassID: 202 case SPRRegClassID: 203 case DPR_8RegClassID: 204 case DPRRegClassID: 205 case QPRRegClassID: 206 return getRegBank(ARM::FPRRegBankID); 207 default: 208 llvm_unreachable("Unsupported register kind"); 209 } 210 211 llvm_unreachable("Switch should handle all register classes"); 212 } 213 214 const RegisterBankInfo::InstructionMapping & 215 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 216 auto Opc = MI.getOpcode(); 217 218 // Try the default logic for non-generic instructions that are either copies 219 // or already have some operands assigned to banks. 220 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 221 const InstructionMapping &Mapping = getInstrMappingImpl(MI); 222 if (Mapping.isValid()) 223 return Mapping; 224 } 225 226 using namespace TargetOpcode; 227 228 const MachineFunction &MF = *MI.getParent()->getParent(); 229 const MachineRegisterInfo &MRI = MF.getRegInfo(); 230 unsigned NumOperands = MI.getNumOperands(); 231 const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 232 233 switch (Opc) { 234 case G_ADD: 235 case G_SUB: { 236 // Integer operations where the source and destination are in the 237 // same register class. 238 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 239 OperandsMapping = Ty.getSizeInBits() == 64 240 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 241 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 242 break; 243 } 244 case G_MUL: 245 case G_AND: 246 case G_OR: 247 case G_XOR: 248 case G_LSHR: 249 case G_ASHR: 250 case G_SHL: 251 case G_SDIV: 252 case G_UDIV: 253 case G_SEXT: 254 case G_ZEXT: 255 case G_ANYEXT: 256 case G_PTR_ADD: 257 case G_INTTOPTR: 258 case G_PTRTOINT: 259 case G_CTLZ: 260 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 261 // the real world we would use different mappings. 262 OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 263 break; 264 case G_TRUNC: { 265 // In some cases we may end up with a G_TRUNC from a 64-bit value to a 266 // 32-bit value. This isn't a real floating point trunc (that would be a 267 // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear 268 // because the legalizer doesn't distinguish between integer and floating 269 // point values so it may leave some 64-bit integers un-narrowed. Until we 270 // have a more principled solution that doesn't let such things sneak all 271 // the way to this point, just map the source to a DPR and the destination 272 // to a GPR. 273 LLT LargeTy = MRI.getType(MI.getOperand(1).getReg()); 274 OperandsMapping = 275 LargeTy.getSizeInBits() <= 32 276 ? &ARM::ValueMappings[ARM::GPR3OpsIdx] 277 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 278 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 279 break; 280 } 281 case G_LOAD: 282 case G_STORE: { 283 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 284 OperandsMapping = 285 Ty.getSizeInBits() == 64 286 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 287 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 288 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 289 break; 290 } 291 case G_FADD: 292 case G_FSUB: 293 case G_FMUL: 294 case G_FDIV: 295 case G_FNEG: { 296 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 297 OperandsMapping =Ty.getSizeInBits() == 64 298 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 299 : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 300 break; 301 } 302 case G_FMA: { 303 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 304 OperandsMapping = 305 Ty.getSizeInBits() == 64 306 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 307 &ARM::ValueMappings[ARM::DPR3OpsIdx], 308 &ARM::ValueMappings[ARM::DPR3OpsIdx], 309 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 310 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 311 &ARM::ValueMappings[ARM::SPR3OpsIdx], 312 &ARM::ValueMappings[ARM::SPR3OpsIdx], 313 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 314 break; 315 } 316 case G_FPEXT: { 317 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 318 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 319 if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32) 320 OperandsMapping = 321 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 322 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 323 break; 324 } 325 case G_FPTRUNC: { 326 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 327 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 328 if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64) 329 OperandsMapping = 330 getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 331 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 332 break; 333 } 334 case G_FPTOSI: 335 case G_FPTOUI: { 336 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 337 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 338 if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) && 339 ToTy.getSizeInBits() == 32) 340 OperandsMapping = 341 FromTy.getSizeInBits() == 64 342 ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 343 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 344 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 345 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 346 break; 347 } 348 case G_SITOFP: 349 case G_UITOFP: { 350 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 351 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 352 if (FromTy.getSizeInBits() == 32 && 353 (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64)) 354 OperandsMapping = 355 ToTy.getSizeInBits() == 64 356 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 357 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 358 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 359 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 360 break; 361 } 362 case G_FCONSTANT: { 363 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 364 OperandsMapping = getOperandsMapping( 365 {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 366 : &ARM::ValueMappings[ARM::SPR3OpsIdx], 367 nullptr}); 368 break; 369 } 370 case G_CONSTANT: 371 case G_FRAME_INDEX: 372 case G_GLOBAL_VALUE: 373 OperandsMapping = 374 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 375 break; 376 case G_SELECT: { 377 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 378 (void)Ty; 379 LLT Ty2 = MRI.getType(MI.getOperand(1).getReg()); 380 (void)Ty2; 381 assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT"); 382 assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT"); 383 OperandsMapping = 384 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 385 &ARM::ValueMappings[ARM::GPR3OpsIdx], 386 &ARM::ValueMappings[ARM::GPR3OpsIdx], 387 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 388 break; 389 } 390 case G_ICMP: { 391 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 392 (void)Ty2; 393 assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP"); 394 OperandsMapping = 395 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 396 &ARM::ValueMappings[ARM::GPR3OpsIdx], 397 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 398 break; 399 } 400 case G_FCMP: { 401 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 402 (void)Ty; 403 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 404 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 405 (void)Ty2; 406 assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP"); 407 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 408 "Mismatched operand sizes for G_FCMP"); 409 410 unsigned Size = Ty1.getSizeInBits(); 411 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 412 413 auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx] 414 : &ARM::ValueMappings[ARM::DPR3OpsIdx]; 415 OperandsMapping = 416 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 417 FPRValueMapping, FPRValueMapping}); 418 break; 419 } 420 case G_MERGE_VALUES: { 421 // We only support G_MERGE_VALUES for creating a double precision floating 422 // point value out of two GPRs. 423 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 424 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 425 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 426 if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 427 Ty2.getSizeInBits() != 32) 428 return getInvalidInstructionMapping(); 429 OperandsMapping = 430 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 431 &ARM::ValueMappings[ARM::GPR3OpsIdx], 432 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 433 break; 434 } 435 case G_UNMERGE_VALUES: { 436 // We only support G_UNMERGE_VALUES for splitting a double precision 437 // floating point value into two GPRs. 438 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 439 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 440 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 441 if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 442 Ty2.getSizeInBits() != 64) 443 return getInvalidInstructionMapping(); 444 OperandsMapping = 445 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 446 &ARM::ValueMappings[ARM::GPR3OpsIdx], 447 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 448 break; 449 } 450 case G_BR: 451 OperandsMapping = getOperandsMapping({nullptr}); 452 break; 453 case G_BRCOND: 454 OperandsMapping = 455 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 456 break; 457 case DBG_VALUE: { 458 SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands); 459 const MachineOperand &MaybeReg = MI.getOperand(0); 460 if (MaybeReg.isReg() && MaybeReg.getReg()) { 461 unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits(); 462 if (Size > 32 && Size != 64) 463 return getInvalidInstructionMapping(); 464 OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 465 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 466 } 467 OperandsMapping = getOperandsMapping(OperandBanks); 468 break; 469 } 470 default: 471 return getInvalidInstructionMapping(); 472 } 473 474 #ifndef NDEBUG 475 for (unsigned i = 0; i < NumOperands; i++) { 476 for (const auto &Mapping : OperandsMapping[i]) { 477 assert( 478 (Mapping.RegBank->getID() != ARM::FPRRegBankID || 479 MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) && 480 "Trying to use floating point register bank on target without vfp"); 481 } 482 } 483 #endif 484 485 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 486 NumOperands); 487 } 488