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 case G_MUL: 233 case G_AND: 234 case G_OR: 235 case G_XOR: 236 case G_LSHR: 237 case G_ASHR: 238 case G_SHL: 239 case G_SDIV: 240 case G_UDIV: 241 case G_SEXT: 242 case G_ZEXT: 243 case G_ANYEXT: 244 case G_GEP: 245 case G_INTTOPTR: 246 case G_PTRTOINT: 247 case G_CTLZ: 248 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 249 // the real world we would use different mappings. 250 OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 251 break; 252 case G_TRUNC: { 253 // In some cases we may end up with a G_TRUNC from a 64-bit value to a 254 // 32-bit value. This isn't a real floating point trunc (that would be a 255 // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear 256 // because the legalizer doesn't distinguish between integer and floating 257 // point values so it may leave some 64-bit integers un-narrowed. Until we 258 // have a more principled solution that doesn't let such things sneak all 259 // the way to this point, just map the source to a DPR and the destination 260 // to a GPR. 261 LLT LargeTy = MRI.getType(MI.getOperand(1).getReg()); 262 OperandsMapping = 263 LargeTy.getSizeInBits() <= 32 264 ? &ARM::ValueMappings[ARM::GPR3OpsIdx] 265 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 266 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 267 break; 268 } 269 case G_LOAD: 270 case G_STORE: { 271 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 272 OperandsMapping = 273 Ty.getSizeInBits() == 64 274 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 275 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 276 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 277 break; 278 } 279 case G_FADD: 280 case G_FSUB: 281 case G_FMUL: 282 case G_FDIV: 283 case G_FNEG: { 284 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 285 OperandsMapping =Ty.getSizeInBits() == 64 286 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 287 : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 288 break; 289 } 290 case G_FMA: { 291 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 292 OperandsMapping = 293 Ty.getSizeInBits() == 64 294 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 295 &ARM::ValueMappings[ARM::DPR3OpsIdx], 296 &ARM::ValueMappings[ARM::DPR3OpsIdx], 297 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 298 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 299 &ARM::ValueMappings[ARM::SPR3OpsIdx], 300 &ARM::ValueMappings[ARM::SPR3OpsIdx], 301 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 302 break; 303 } 304 case G_FPEXT: { 305 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 306 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 307 if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32) 308 OperandsMapping = 309 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 310 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 311 break; 312 } 313 case G_FPTRUNC: { 314 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 315 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 316 if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64) 317 OperandsMapping = 318 getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 319 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 320 break; 321 } 322 case G_FPTOSI: 323 case G_FPTOUI: { 324 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 325 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 326 if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) && 327 ToTy.getSizeInBits() == 32) 328 OperandsMapping = 329 FromTy.getSizeInBits() == 64 330 ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 331 &ARM::ValueMappings[ARM::DPR3OpsIdx]}) 332 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 333 &ARM::ValueMappings[ARM::SPR3OpsIdx]}); 334 break; 335 } 336 case G_SITOFP: 337 case G_UITOFP: { 338 LLT ToTy = MRI.getType(MI.getOperand(0).getReg()); 339 LLT FromTy = MRI.getType(MI.getOperand(1).getReg()); 340 if (FromTy.getSizeInBits() == 32 && 341 (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64)) 342 OperandsMapping = 343 ToTy.getSizeInBits() == 64 344 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 345 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 346 : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx], 347 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 348 break; 349 } 350 case G_FCONSTANT: { 351 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 352 OperandsMapping = getOperandsMapping( 353 {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 354 : &ARM::ValueMappings[ARM::SPR3OpsIdx], 355 nullptr}); 356 break; 357 } 358 case G_CONSTANT: 359 case G_FRAME_INDEX: 360 case G_GLOBAL_VALUE: 361 OperandsMapping = 362 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 363 break; 364 case G_SELECT: { 365 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 366 (void)Ty; 367 LLT Ty2 = MRI.getType(MI.getOperand(1).getReg()); 368 (void)Ty2; 369 assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT"); 370 assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT"); 371 OperandsMapping = 372 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 373 &ARM::ValueMappings[ARM::GPR3OpsIdx], 374 &ARM::ValueMappings[ARM::GPR3OpsIdx], 375 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 376 break; 377 } 378 case G_ICMP: { 379 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 380 (void)Ty2; 381 assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP"); 382 OperandsMapping = 383 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 384 &ARM::ValueMappings[ARM::GPR3OpsIdx], 385 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 386 break; 387 } 388 case G_FCMP: { 389 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 390 (void)Ty; 391 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 392 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 393 (void)Ty2; 394 assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP"); 395 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 396 "Mismatched operand sizes for G_FCMP"); 397 398 unsigned Size = Ty1.getSizeInBits(); 399 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 400 401 auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx] 402 : &ARM::ValueMappings[ARM::DPR3OpsIdx]; 403 OperandsMapping = 404 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 405 FPRValueMapping, FPRValueMapping}); 406 break; 407 } 408 case G_MERGE_VALUES: { 409 // We only support G_MERGE_VALUES for creating a double precision floating 410 // point value out of two GPRs. 411 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 412 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 413 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 414 if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 415 Ty2.getSizeInBits() != 32) 416 return getInvalidInstructionMapping(); 417 OperandsMapping = 418 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 419 &ARM::ValueMappings[ARM::GPR3OpsIdx], 420 &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 421 break; 422 } 423 case G_UNMERGE_VALUES: { 424 // We only support G_UNMERGE_VALUES for splitting a double precision 425 // floating point value into two GPRs. 426 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 427 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 428 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 429 if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 430 Ty2.getSizeInBits() != 64) 431 return getInvalidInstructionMapping(); 432 OperandsMapping = 433 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 434 &ARM::ValueMappings[ARM::GPR3OpsIdx], 435 &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 436 break; 437 } 438 case G_BR: 439 OperandsMapping = getOperandsMapping({nullptr}); 440 break; 441 case G_BRCOND: 442 OperandsMapping = 443 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 444 break; 445 case DBG_VALUE: { 446 SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands); 447 const MachineOperand &MaybeReg = MI.getOperand(0); 448 if (MaybeReg.isReg() && MaybeReg.getReg()) { 449 unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits(); 450 if (Size > 32 && Size != 64) 451 return getInvalidInstructionMapping(); 452 OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 453 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 454 } 455 OperandsMapping = getOperandsMapping(OperandBanks); 456 break; 457 } 458 default: 459 return getInvalidInstructionMapping(); 460 } 461 462 #ifndef NDEBUG 463 for (unsigned i = 0; i < NumOperands; i++) { 464 for (const auto &Mapping : OperandsMapping[i]) { 465 assert( 466 (Mapping.RegBank->getID() != ARM::FPRRegBankID || 467 MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) && 468 "Trying to use floating point register bank on target without vfp"); 469 } 470 } 471 #endif 472 473 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 474 NumOperands); 475 } 476