457 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// 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 classes15#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_IMPL22#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 it28// 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 38const RegisterBankInfo::PartialMapping PartMappings[]{39 // GPR Partial Mapping40 {0, 32, GPRRegBank},41 // SPR Partial Mapping42 {0, 32, FPRRegBank},43 // DPR Partial Mapping44 {0, 64, FPRRegBank},45};46 47#ifndef NDEBUG48static 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#endif67 68enum ValueMappingIdx {69 InvalidIdx = 0,70 GPR3OpsIdx = 1,71 SPR3OpsIdx = 4,72 DPR3OpsIdx = 7,73};74 75const RegisterBankInfo::ValueMapping ValueMappings[] = {76 // invalid77 {nullptr, 0},78 // 3 ops in GPRs79 {&PartMappings[PMI_GPR - PMI_Min], 1},80 {&PartMappings[PMI_GPR - PMI_Min], 1},81 {&PartMappings[PMI_GPR - PMI_Min], 1},82 // 3 ops in SPRs83 {&PartMappings[PMI_SPR - PMI_Min], 1},84 {&PartMappings[PMI_SPR - PMI_Min], 1},85 {&PartMappings[PMI_SPR - PMI_Min], 1},86 // 3 ops in DPRs87 {&PartMappings[PMI_DPR - PMI_Min], 1},88 {&PartMappings[PMI_DPR - PMI_Min], 1},89 {&PartMappings[PMI_DPR - PMI_Min], 1}};90 91#ifndef NDEBUG92static bool93checkValueMapping(const RegisterBankInfo::ValueMapping &VM,94 const RegisterBankInfo::PartialMapping *BreakDown) {95 return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;96}97 98static 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#endif130} // end namespace arm131} // end namespace llvm132 133ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) {134 // We have only one set of register banks, whatever the subtarget135 // is. Therefore, the initialization of the RegBanks table should be136 // done only once. Indeed the table of all register banks137 // (ARM::RegBanks) is unique in the compiler. At some point, it138 // 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 NDEBUG165 ARM::checkPartialMappings();166 ARM::checkValueMappings();167#endif168 };169 170 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);171}172 173const RegisterBankInfo::InstructionMapping &174ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {175 auto Opc = MI.getOpcode();176 177 // Try the default logic for non-generic instructions that are either copies178 // 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 the196 // same register class.197 LLT Ty = MRI.getType(MI.getOperand(0).getReg());198 OperandsMapping = Ty.getSizeInBits() == 64199 ? &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; in220 // 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 a225 // 32-bit value. This isn't a real floating point trunc (that would be a226 // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear227 // because the legalizer doesn't distinguish between integer and floating228 // point values so it may leave some 64-bit integers un-narrowed. Until we229 // have a more principled solution that doesn't let such things sneak all230 // the way to this point, just map the source to a DPR and the destination231 // to a GPR.232 LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());233 OperandsMapping =234 LargeTy.getSizeInBits() <= 32235 ? &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() == 64245 ? 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() == 64257 ? &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() == 64265 ? 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() == 64301 ? 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() == 64315 ? 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 floating382 // 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 precision397 // 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 NDEBUG444 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#endif453 454 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,455 NumOperands);456}457