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