1d88c1a5aSDimitry Andric //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==// 2d88c1a5aSDimitry Andric // 3d88c1a5aSDimitry Andric // The LLVM Compiler Infrastructure 4d88c1a5aSDimitry Andric // 5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source 6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details. 7d88c1a5aSDimitry Andric // 8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===// 9d88c1a5aSDimitry Andric /// \file 10d88c1a5aSDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for ARM. 11d88c1a5aSDimitry Andric /// \todo This should be generated by TableGen. 12d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===// 13d88c1a5aSDimitry Andric 14d88c1a5aSDimitry Andric #include "ARMRegisterBankInfo.h" 15d88c1a5aSDimitry Andric #include "ARMInstrInfo.h" // For the register classes 167a7e6055SDimitry Andric #include "ARMSubtarget.h" 17d88c1a5aSDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBank.h" 18d88c1a5aSDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 19d88c1a5aSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 20d88c1a5aSDimitry Andric #include "llvm/Target/TargetRegisterInfo.h" 21d88c1a5aSDimitry Andric 227a7e6055SDimitry Andric #define GET_TARGET_REGBANK_IMPL 237a7e6055SDimitry Andric #include "ARMGenRegisterBank.inc" 247a7e6055SDimitry Andric 25d88c1a5aSDimitry Andric using namespace llvm; 26d88c1a5aSDimitry Andric 27d88c1a5aSDimitry Andric #ifndef LLVM_BUILD_GLOBAL_ISEL 28d88c1a5aSDimitry Andric #error "You shouldn't build this" 29d88c1a5aSDimitry Andric #endif 30d88c1a5aSDimitry Andric 31d88c1a5aSDimitry Andric // FIXME: TableGen this. 32d88c1a5aSDimitry Andric // If it grows too much and TableGen still isn't ready to do the job, extract it 33d88c1a5aSDimitry Andric // into an ARMGenRegisterBankInfo.def (similar to AArch64). 34d88c1a5aSDimitry Andric namespace llvm { 35d88c1a5aSDimitry Andric namespace ARM { 367a7e6055SDimitry Andric enum PartialMappingIdx { 377a7e6055SDimitry Andric PMI_GPR, 387a7e6055SDimitry Andric PMI_SPR, 397a7e6055SDimitry Andric PMI_DPR, 407a7e6055SDimitry Andric PMI_Min = PMI_GPR, 41f1a29dd3SDimitry Andric }; 42f1a29dd3SDimitry Andric 437a7e6055SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{ 447a7e6055SDimitry Andric // GPR Partial Mapping 457a7e6055SDimitry Andric {0, 32, GPRRegBank}, 467a7e6055SDimitry Andric // SPR Partial Mapping 477a7e6055SDimitry Andric {0, 32, FPRRegBank}, 487a7e6055SDimitry Andric // DPR Partial Mapping 497a7e6055SDimitry Andric {0, 64, FPRRegBank}, 507a7e6055SDimitry Andric }; 51d88c1a5aSDimitry Andric 527a7e6055SDimitry Andric #ifndef NDEBUG 537a7e6055SDimitry Andric static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM, 547a7e6055SDimitry Andric unsigned Start, unsigned Length, 557a7e6055SDimitry Andric unsigned RegBankID) { 567a7e6055SDimitry Andric return PM.StartIdx == Start && PM.Length == Length && 577a7e6055SDimitry Andric PM.RegBank->getID() == RegBankID; 587a7e6055SDimitry Andric } 597a7e6055SDimitry Andric 607a7e6055SDimitry Andric static void checkPartialMappings() { 617a7e6055SDimitry Andric assert( 627a7e6055SDimitry Andric checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) && 637a7e6055SDimitry Andric "Wrong mapping for GPR"); 647a7e6055SDimitry Andric assert( 657a7e6055SDimitry Andric checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) && 667a7e6055SDimitry Andric "Wrong mapping for SPR"); 677a7e6055SDimitry Andric assert( 687a7e6055SDimitry Andric checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) && 697a7e6055SDimitry Andric "Wrong mapping for DPR"); 707a7e6055SDimitry Andric } 717a7e6055SDimitry Andric #endif 727a7e6055SDimitry Andric 737a7e6055SDimitry Andric enum ValueMappingIdx { 747a7e6055SDimitry Andric InvalidIdx = 0, 757a7e6055SDimitry Andric GPR3OpsIdx = 1, 767a7e6055SDimitry Andric SPR3OpsIdx = 4, 777a7e6055SDimitry Andric DPR3OpsIdx = 7, 787a7e6055SDimitry Andric }; 79d88c1a5aSDimitry Andric 80d88c1a5aSDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = { 817a7e6055SDimitry Andric // invalid 827a7e6055SDimitry Andric {nullptr, 0}, 837a7e6055SDimitry Andric // 3 ops in GPRs 847a7e6055SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 857a7e6055SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 867a7e6055SDimitry Andric {&PartMappings[PMI_GPR - PMI_Min], 1}, 877a7e6055SDimitry Andric // 3 ops in SPRs 887a7e6055SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 897a7e6055SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 907a7e6055SDimitry Andric {&PartMappings[PMI_SPR - PMI_Min], 1}, 917a7e6055SDimitry Andric // 3 ops in DPRs 927a7e6055SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}, 937a7e6055SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}, 947a7e6055SDimitry Andric {&PartMappings[PMI_DPR - PMI_Min], 1}}; 957a7e6055SDimitry Andric 967a7e6055SDimitry Andric #ifndef NDEBUG 977a7e6055SDimitry Andric static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM, 987a7e6055SDimitry Andric RegisterBankInfo::PartialMapping *BreakDown) { 997a7e6055SDimitry Andric return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown; 1007a7e6055SDimitry Andric } 1017a7e6055SDimitry Andric 1027a7e6055SDimitry Andric static void checkValueMappings() { 1037a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx], 1047a7e6055SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 1057a7e6055SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 1067a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1], 1077a7e6055SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 1087a7e6055SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 1097a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2], 1107a7e6055SDimitry Andric &PartMappings[PMI_GPR - PMI_Min]) && 1117a7e6055SDimitry Andric "Wrong value mapping for 3 GPR ops instruction"); 1127a7e6055SDimitry Andric 1137a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx], 1147a7e6055SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 1157a7e6055SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 1167a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1], 1177a7e6055SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 1187a7e6055SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 1197a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2], 1207a7e6055SDimitry Andric &PartMappings[PMI_SPR - PMI_Min]) && 1217a7e6055SDimitry Andric "Wrong value mapping for 3 SPR ops instruction"); 1227a7e6055SDimitry Andric 1237a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx], 1247a7e6055SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 1257a7e6055SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 1267a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1], 1277a7e6055SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 1287a7e6055SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 1297a7e6055SDimitry Andric assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2], 1307a7e6055SDimitry Andric &PartMappings[PMI_DPR - PMI_Min]) && 1317a7e6055SDimitry Andric "Wrong value mapping for 3 DPR ops instruction"); 1327a7e6055SDimitry Andric } 1337a7e6055SDimitry Andric #endif 134d88c1a5aSDimitry Andric } // end namespace arm 135d88c1a5aSDimitry Andric } // end namespace llvm 136d88c1a5aSDimitry Andric 137d88c1a5aSDimitry Andric ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 1387a7e6055SDimitry Andric : ARMGenRegisterBankInfo() { 139d88c1a5aSDimitry Andric static bool AlreadyInit = false; 140d88c1a5aSDimitry Andric // We have only one set of register banks, whatever the subtarget 141d88c1a5aSDimitry Andric // is. Therefore, the initialization of the RegBanks table should be 142d88c1a5aSDimitry Andric // done only once. Indeed the table of all register banks 143d88c1a5aSDimitry Andric // (ARM::RegBanks) is unique in the compiler. At some point, it 144d88c1a5aSDimitry Andric // will get tablegen'ed and the whole constructor becomes empty. 145d88c1a5aSDimitry Andric if (AlreadyInit) 146d88c1a5aSDimitry Andric return; 147d88c1a5aSDimitry Andric AlreadyInit = true; 148d88c1a5aSDimitry Andric 149d88c1a5aSDimitry Andric const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 150d88c1a5aSDimitry Andric (void)RBGPR; 151d88c1a5aSDimitry Andric assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 152f1a29dd3SDimitry Andric 153f1a29dd3SDimitry Andric // Initialize the GPR bank. 154d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 155d88c1a5aSDimitry Andric "Subclass not added?"); 156d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 157d88c1a5aSDimitry Andric "Subclass not added?"); 158d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 159d88c1a5aSDimitry Andric "Subclass not added?"); 160d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 161d88c1a5aSDimitry Andric "Subclass not added?"); 162d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 163d88c1a5aSDimitry Andric "Subclass not added?"); 164d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 165d88c1a5aSDimitry Andric "Subclass not added?"); 166d88c1a5aSDimitry Andric assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 167d88c1a5aSDimitry Andric "Subclass not added?"); 168d88c1a5aSDimitry Andric assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 1697a7e6055SDimitry Andric 1707a7e6055SDimitry Andric #ifndef NDEBUG 1717a7e6055SDimitry Andric ARM::checkPartialMappings(); 1727a7e6055SDimitry Andric ARM::checkValueMappings(); 1737a7e6055SDimitry Andric #endif 174d88c1a5aSDimitry Andric } 175d88c1a5aSDimitry Andric 176d88c1a5aSDimitry Andric const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 177d88c1a5aSDimitry Andric const TargetRegisterClass &RC) const { 178d88c1a5aSDimitry Andric using namespace ARM; 179d88c1a5aSDimitry Andric 180d88c1a5aSDimitry Andric switch (RC.getID()) { 181d88c1a5aSDimitry Andric case GPRRegClassID: 1827a7e6055SDimitry Andric case GPRnopcRegClassID: 1837a7e6055SDimitry Andric case GPRspRegClassID: 184d88c1a5aSDimitry Andric case tGPR_and_tcGPRRegClassID: 1857a7e6055SDimitry Andric case tGPRRegClassID: 186d88c1a5aSDimitry Andric return getRegBank(ARM::GPRRegBankID); 1877a7e6055SDimitry Andric case SPR_8RegClassID: 1887a7e6055SDimitry Andric case SPRRegClassID: 1897a7e6055SDimitry Andric case DPR_8RegClassID: 1907a7e6055SDimitry Andric case DPRRegClassID: 1917a7e6055SDimitry Andric return getRegBank(ARM::FPRRegBankID); 192d88c1a5aSDimitry Andric default: 193d88c1a5aSDimitry Andric llvm_unreachable("Unsupported register kind"); 194d88c1a5aSDimitry Andric } 195d88c1a5aSDimitry Andric 196d88c1a5aSDimitry Andric llvm_unreachable("Switch should handle all register classes"); 197d88c1a5aSDimitry Andric } 198d88c1a5aSDimitry Andric 1990f5676f4SDimitry Andric const RegisterBankInfo::InstructionMapping & 200d88c1a5aSDimitry Andric ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 201d88c1a5aSDimitry Andric auto Opc = MI.getOpcode(); 202d88c1a5aSDimitry Andric 203d88c1a5aSDimitry Andric // Try the default logic for non-generic instructions that are either copies 204d88c1a5aSDimitry Andric // or already have some operands assigned to banks. 205d88c1a5aSDimitry Andric if (!isPreISelGenericOpcode(Opc)) { 2060f5676f4SDimitry Andric const InstructionMapping &Mapping = getInstrMappingImpl(MI); 207d88c1a5aSDimitry Andric if (Mapping.isValid()) 208d88c1a5aSDimitry Andric return Mapping; 209d88c1a5aSDimitry Andric } 210d88c1a5aSDimitry Andric 211d88c1a5aSDimitry Andric using namespace TargetOpcode; 212d88c1a5aSDimitry Andric 2137a7e6055SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 2147a7e6055SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 2157a7e6055SDimitry Andric LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 2167a7e6055SDimitry Andric 217d88c1a5aSDimitry Andric unsigned NumOperands = MI.getNumOperands(); 2187a7e6055SDimitry Andric const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 219d88c1a5aSDimitry Andric 220d88c1a5aSDimitry Andric switch (Opc) { 221d88c1a5aSDimitry Andric case G_ADD: 2226bc11b14SDimitry Andric case G_SUB: 2236bc11b14SDimitry Andric case G_MUL: 224db17bf38SDimitry Andric case G_AND: 225db17bf38SDimitry Andric case G_OR: 226db17bf38SDimitry Andric case G_XOR: 22751690af2SDimitry Andric case G_SDIV: 22851690af2SDimitry Andric case G_UDIV: 2297a7e6055SDimitry Andric case G_SEXT: 2307a7e6055SDimitry Andric case G_ZEXT: 2315517e702SDimitry Andric case G_ANYEXT: 23251690af2SDimitry Andric case G_TRUNC: 2337a7e6055SDimitry Andric case G_GEP: 234d88c1a5aSDimitry Andric // FIXME: We're abusing the fact that everything lives in a GPR for now; in 235d88c1a5aSDimitry Andric // the real world we would use different mappings. 2367a7e6055SDimitry Andric OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 237d88c1a5aSDimitry Andric break; 2387a7e6055SDimitry Andric case G_LOAD: 2397a7e6055SDimitry Andric case G_STORE: 2407a7e6055SDimitry Andric OperandsMapping = 2417a7e6055SDimitry Andric Ty.getSizeInBits() == 64 2427a7e6055SDimitry Andric ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 2437a7e6055SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 2447a7e6055SDimitry Andric : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 2457a7e6055SDimitry Andric break; 2467a7e6055SDimitry Andric case G_FADD: 2477a7e6055SDimitry Andric assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) && 2487a7e6055SDimitry Andric "Unsupported size for G_FADD"); 2497a7e6055SDimitry Andric OperandsMapping = Ty.getSizeInBits() == 64 2507a7e6055SDimitry Andric ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 2517a7e6055SDimitry Andric : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 2527a7e6055SDimitry Andric break; 2537a7e6055SDimitry Andric case G_CONSTANT: 254d88c1a5aSDimitry Andric case G_FRAME_INDEX: 2557a7e6055SDimitry Andric OperandsMapping = 2567a7e6055SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 257d88c1a5aSDimitry Andric break; 258edd7eaddSDimitry Andric case G_ICMP: { 259edd7eaddSDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 260edd7eaddSDimitry Andric (void)Ty2; 261edd7eaddSDimitry Andric assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP"); 262edd7eaddSDimitry Andric OperandsMapping = 263edd7eaddSDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 264edd7eaddSDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 265edd7eaddSDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 266edd7eaddSDimitry Andric break; 267edd7eaddSDimitry Andric } 268db17bf38SDimitry Andric case G_MERGE_VALUES: { 269db17bf38SDimitry Andric // We only support G_MERGE_VALUES for creating a double precision floating 270db17bf38SDimitry Andric // point value out of two GPRs. 2717a7e6055SDimitry Andric LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 272db17bf38SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 2737a7e6055SDimitry Andric if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 2747a7e6055SDimitry Andric Ty2.getSizeInBits() != 32) 2750f5676f4SDimitry Andric return getInvalidInstructionMapping(); 2767a7e6055SDimitry Andric OperandsMapping = 2777a7e6055SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 278db17bf38SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 279db17bf38SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx]}); 2807a7e6055SDimitry Andric break; 2817a7e6055SDimitry Andric } 282db17bf38SDimitry Andric case G_UNMERGE_VALUES: { 283db17bf38SDimitry Andric // We only support G_UNMERGE_VALUES for splitting a double precision 284db17bf38SDimitry Andric // floating point value into two GPRs. 2857a7e6055SDimitry Andric LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 286db17bf38SDimitry Andric LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 287db17bf38SDimitry Andric if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 288db17bf38SDimitry Andric Ty2.getSizeInBits() != 64) 2890f5676f4SDimitry Andric return getInvalidInstructionMapping(); 290db17bf38SDimitry Andric OperandsMapping = 291db17bf38SDimitry Andric getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 292db17bf38SDimitry Andric &ARM::ValueMappings[ARM::GPR3OpsIdx], 293db17bf38SDimitry Andric &ARM::ValueMappings[ARM::DPR3OpsIdx]}); 2947a7e6055SDimitry Andric break; 2957a7e6055SDimitry Andric } 296d88c1a5aSDimitry Andric default: 2970f5676f4SDimitry Andric return getInvalidInstructionMapping(); 298d88c1a5aSDimitry Andric } 299d88c1a5aSDimitry Andric 3007a7e6055SDimitry Andric #ifndef NDEBUG 3017a7e6055SDimitry Andric for (unsigned i = 0; i < NumOperands; i++) { 3027a7e6055SDimitry Andric for (const auto &Mapping : OperandsMapping[i]) { 3037a7e6055SDimitry Andric assert( 3047a7e6055SDimitry Andric (Mapping.RegBank->getID() != ARM::FPRRegBankID || 3057a7e6055SDimitry Andric MF.getSubtarget<ARMSubtarget>().hasVFP2()) && 3067a7e6055SDimitry Andric "Trying to use floating point register bank on target without vfp"); 3077a7e6055SDimitry Andric } 3087a7e6055SDimitry Andric } 3097a7e6055SDimitry Andric #endif 3107a7e6055SDimitry Andric 3110f5676f4SDimitry Andric return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 3120f5676f4SDimitry Andric NumOperands); 313d88c1a5aSDimitry Andric } 314