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/GlobalISel/RegisterBank.h" 17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.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 : ARMGenRegisterBankInfo() { 134 static bool AlreadyInit = false; 135 // We have only one set of register banks, whatever the subtarget 136 // is. Therefore, the initialization of the RegBanks table should be 137 // done only once. Indeed the table of all register banks 138 // (ARM::RegBanks) is unique in the compiler. At some point, it 139 // will get tablegen'ed and the whole constructor becomes empty. 140 if (AlreadyInit) 141 return; 142 AlreadyInit = true; 143 144 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 145 (void)RBGPR; 146 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 147 148 // Initialize the GPR bank. 149 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 150 "Subclass not added?"); 151 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 152 "Subclass not added?"); 153 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 154 "Subclass not added?"); 155 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 156 "Subclass not added?"); 157 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 158 "Subclass not added?"); 159 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 160 "Subclass not added?"); 161 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 162 "Subclass not added?"); 163 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPREven_and_tGPR_and_tcGPRRegClassID)) && 164 "Subclass not added?"); 165 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) && 166 "Subclass not added?"); 167 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 168 169 #ifndef NDEBUG 170 ARM::checkPartialMappings(); 171 ARM::checkValueMappings(); 172 #endif 173 } 174 175 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 176 const TargetRegisterClass &RC) const { 177 using namespace ARM; 178 179 switch (RC.getID()) { 180 case GPRRegClassID: 181 case GPRwithAPSRRegClassID: 182 case GPRnopcRegClassID: 183 case rGPRRegClassID: 184 case GPRspRegClassID: 185 case tGPR_and_tcGPRRegClassID: 186 case tcGPRRegClassID: 187 case tGPRRegClassID: 188 case tGPREvenRegClassID: 189 case tGPROddRegClassID: 190 case tGPR_and_tGPREvenRegClassID: 191 case tGPR_and_tGPROddRegClassID: 192 case tGPREven_and_tcGPRRegClassID: 193 case tGPREven_and_tGPR_and_tcGPRRegClassID: 194 case tGPROdd_and_tcGPRRegClassID: 195 return getRegBank(ARM::GPRRegBankID); 196 case HPRRegClassID: 197 case SPR_8RegClassID: 198 case SPRRegClassID: 199 case DPR_8RegClassID: 200 case DPRRegClassID: 201 case QPRRegClassID: 202 return getRegBank(ARM::FPRRegBankID); 203 default: 204 llvm_unreachable("Unsupported register kind"); 205 } 206 207 llvm_unreachable("Switch should handle all register classes"); 208 } 209 210 const RegisterBankInfo::InstructionMapping & 211 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 212 auto Opc = MI.getOpcode(); 213 214 // Try the default logic for non-generic instructions that are either copies 215 // or already have some operands assigned to banks. 216 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 217 const InstructionMapping &Mapping = getInstrMappingImpl(MI); 218 if (Mapping.isValid()) 219 return Mapping; 220 } 221 222 using namespace TargetOpcode; 223 224 const MachineFunction &MF = *MI.getParent()->getParent(); 225 const MachineRegisterInfo &MRI = MF.getRegInfo(); 226 unsigned NumOperands = MI.getNumOperands(); 227 const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 228 229 switch (Opc) { 230 case G_ADD: 231 case G_SUB: { 232 // Integer operations where the source and destination are in the 233 // same register class. 234 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 235 OperandsMapping = Ty.getSizeInBits() == 64 236 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 237 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 238 break; 239 } 240 case G_MUL: 241 case G_AND: 242 case G_OR: 243 case G_XOR: 244 case G_LSHR: 245 case G_ASHR: 246 case G_SHL: 247 case G_SDIV: 248 case G_UDIV: 249 case G_SEXT: 250 case G_ZEXT: 251 case G_ANYEXT: 252 case G_GEP: 253 case G_INTTOPTR: 254 case G_PTRTOINT: 255 case G_CTLZ: 256 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 257 // the real world we would use different mappings. 258 OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 259 break; 260 case G_TRUNC: { 261 // In some cases we may end up with a G_TRUNC from a 64-bit value to a 262 // 32-bit value. This isn't a real floating point trunc (that would be a 263 // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear 264 // because the legalizer doesn't distinguish between integer and floating 265 // point values so it may leave some 64-bit integers un-narrowed. Until we 266 // have a more principled solution that doesn't let such things sneak all 267 // the way to this point, just map the source to a DPR and the destination 268 // to a GPR. 269 LLT LargeTy = MRI.getType(MI.getOperand(1).getReg()); 270 OperandsMapping = 271 LargeTy.getSizeInBits() <= 32 272 ? &ARM::ValueMappings[ARM::GPR3OpsIdx] 273 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 274 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 275 break; 276 } 277 case G_LOAD: 278 case G_STORE: { 279 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 280 OperandsMapping = 281 Ty.getSizeInBits() == 64 282 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 283 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 284 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 285 break; 286 } 287 case G_FADD: 288 case G_FSUB: 289 case G_FMUL: 290 case G_FDIV: 291 case G_FNEG: { 292 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 293 OperandsMapping =Ty.getSizeInBits() == 64 294 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 295 : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 296 break; 297 } 298 case G_FMA: { 299 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 300 OperandsMapping = 301 Ty.getSizeInBits() == 64 302 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 303 &ARM::ValueMappings[ARM::DPR3OpsIdx], 304 &ARM::ValueMappings[ARM::DPR3OpsIdx], 305 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 306 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 307 &ARM::ValueMappings[ARM::SPR3OpsIdx], 308 &ARM::ValueMappings[ARM::SPR3OpsIdx], 309 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 310 break; 311 } 312 case G_FPEXT: { 313 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 314 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 315 if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32) 316 OperandsMapping = 317 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 318 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 319 break; 320 } 321 case G_FPTRUNC: { 322 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 323 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 324 if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64) 325 OperandsMapping = 326 getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 327 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 328 break; 329 } 330 case G_FPTOSI: 331 case G_FPTOUI: { 332 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 333 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 334 if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) && 335 ToTy.getSizeInBits() == 32) 336 OperandsMapping = 337 FromTy.getSizeInBits() == 64 338 ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 339 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 340 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 341 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 342 break; 343 } 344 case G_SITOFP: 345 case G_UITOFP: { 346 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 347 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 348 if (FromTy.getSizeInBits() == 32 && 349 (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64)) 350 OperandsMapping = 351 ToTy.getSizeInBits() == 64 352 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 353 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 354 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 355 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 356 break; 357 } 358 case G_FCONSTANT: { 359 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 360 OperandsMapping = getOperandsMapping( 361 {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 362 : &ARM::ValueMappings[ARM::SPR3OpsIdx], 363 nullptr}); 364 break; 365 } 366 case G_CONSTANT: 367 case G_FRAME_INDEX: 368 case G_GLOBAL_VALUE: 369 OperandsMapping = 370 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 371 break; 372 case G_SELECT: { 373 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 374 (void)Ty; 375 LLT Ty2 = MRI.getType(MI.getOperand(1).getReg()); 376 (void)Ty2; 377 assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT"); 378 assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT"); 379 OperandsMapping = 380 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 381 &ARM::ValueMappings[ARM::GPR3OpsIdx], 382 &ARM::ValueMappings[ARM::GPR3OpsIdx], 383 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 384 break; 385 } 386 case G_ICMP: { 387 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 388 (void)Ty2; 389 assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP"); 390 OperandsMapping = 391 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 392 &ARM::ValueMappings[ARM::GPR3OpsIdx], 393 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 394 break; 395 } 396 case G_FCMP: { 397 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 398 (void)Ty; 399 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 400 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 401 (void)Ty2; 402 assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP"); 403 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 404 "Mismatched operand sizes for G_FCMP"); 405 406 unsigned Size = Ty1.getSizeInBits(); 407 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 408 409 auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx] 410 : &ARM::ValueMappings[ARM::DPR3OpsIdx]; 411 OperandsMapping = 412 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 413 FPRValueMapping, FPRValueMapping}); 414 break; 415 } 416 case G_MERGE_VALUES: { 417 // We only support G_MERGE_VALUES for creating a double precision floating 418 // point value out of two GPRs. 419 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 420 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 421 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 422 if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 423 Ty2.getSizeInBits() != 32) 424 return getInvalidInstructionMapping(); 425 OperandsMapping = 426 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 427 &ARM::ValueMappings[ARM::GPR3OpsIdx], 428 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 429 break; 430 } 431 case G_UNMERGE_VALUES: { 432 // We only support G_UNMERGE_VALUES for splitting a double precision 433 // floating point value into two GPRs. 434 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 435 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 436 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 437 if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 438 Ty2.getSizeInBits() != 64) 439 return getInvalidInstructionMapping(); 440 OperandsMapping = 441 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 442 &ARM::ValueMappings[ARM::GPR3OpsIdx], 443 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 444 break; 445 } 446 case G_BR: 447 OperandsMapping = getOperandsMapping({nullptr}); 448 break; 449 case G_BRCOND: 450 OperandsMapping = 451 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 452 break; 453 case DBG_VALUE: { 454 SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands); 455 const MachineOperand &MaybeReg = MI.getOperand(0); 456 if (MaybeReg.isReg() && MaybeReg.getReg()) { 457 unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits(); 458 if (Size > 32 && Size != 64) 459 return getInvalidInstructionMapping(); 460 OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 461 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 462 } 463 OperandsMapping = getOperandsMapping(OperandBanks); 464 break; 465 } 466 default: 467 return getInvalidInstructionMapping(); 468 } 469 470 #ifndef NDEBUG 471 for (unsigned i = 0; i < NumOperands; i++) { 472 for (const auto &Mapping : OperandsMapping[i]) { 473 assert( 474 (Mapping.RegBank->getID() != ARM::FPRRegBankID || 475 MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) && 476 "Trying to use floating point register bank on target without vfp"); 477 } 478 } 479 #endif 480 481 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 482 NumOperands); 483 } 484