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