1 //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// This file implements the targeting of the RegisterBankInfo class for ARM. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMRegisterBankInfo.h" 15 #include "ARMInstrInfo.h" // For the register classes 16 #include "ARMSubtarget.h" 17 #include "llvm/CodeGen/GlobalISel/RegisterBank.h" 18 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/Target/TargetRegisterInfo.h" 21 22 #define GET_TARGET_REGBANK_IMPL 23 #include "ARMGenRegisterBank.inc" 24 25 using namespace llvm; 26 27 #ifndef LLVM_BUILD_GLOBAL_ISEL 28 #error "You shouldn't build this" 29 #endif 30 31 // FIXME: TableGen this. 32 // If it grows too much and TableGen still isn't ready to do the job, extract it 33 // into an ARMGenRegisterBankInfo.def (similar to AArch64). 34 namespace llvm { 35 namespace ARM { 36 enum PartialMappingIdx { 37 PMI_GPR, 38 PMI_SPR, 39 PMI_DPR, 40 PMI_Min = PMI_GPR, 41 }; 42 43 RegisterBankInfo::PartialMapping PartMappings[]{ 44 // GPR Partial Mapping 45 {0, 32, GPRRegBank}, 46 // SPR Partial Mapping 47 {0, 32, FPRRegBank}, 48 // DPR Partial Mapping 49 {0, 64, FPRRegBank}, 50 }; 51 52 #ifndef NDEBUG 53 static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM, 54 unsigned Start, unsigned Length, 55 unsigned RegBankID) { 56 return PM.StartIdx == Start && PM.Length == Length && 57 PM.RegBank->getID() == RegBankID; 58 } 59 60 static void checkPartialMappings() { 61 assert( 62 checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) && 63 "Wrong mapping for GPR"); 64 assert( 65 checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) && 66 "Wrong mapping for SPR"); 67 assert( 68 checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) && 69 "Wrong mapping for DPR"); 70 } 71 #endif 72 73 enum ValueMappingIdx { 74 InvalidIdx = 0, 75 GPR3OpsIdx = 1, 76 SPR3OpsIdx = 4, 77 DPR3OpsIdx = 7, 78 }; 79 80 RegisterBankInfo::ValueMapping ValueMappings[] = { 81 // invalid 82 {nullptr, 0}, 83 // 3 ops in GPRs 84 {&PartMappings[PMI_GPR - PMI_Min], 1}, 85 {&PartMappings[PMI_GPR - PMI_Min], 1}, 86 {&PartMappings[PMI_GPR - PMI_Min], 1}, 87 // 3 ops in SPRs 88 {&PartMappings[PMI_SPR - PMI_Min], 1}, 89 {&PartMappings[PMI_SPR - PMI_Min], 1}, 90 {&PartMappings[PMI_SPR - PMI_Min], 1}, 91 // 3 ops in DPRs 92 {&PartMappings[PMI_DPR - PMI_Min], 1}, 93 {&PartMappings[PMI_DPR - PMI_Min], 1}, 94 {&PartMappings[PMI_DPR - PMI_Min], 1}}; 95 96 #ifndef NDEBUG 97 static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM, 98 RegisterBankInfo::PartialMapping *BreakDown) { 99 return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown; 100 } 101 102 static void checkValueMappings() { 103 assert(checkValueMapping(ValueMappings[GPR3OpsIdx], 104 &PartMappings[PMI_GPR - PMI_Min]) && 105 "Wrong value mapping for 3 GPR ops instruction"); 106 assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1], 107 &PartMappings[PMI_GPR - PMI_Min]) && 108 "Wrong value mapping for 3 GPR ops instruction"); 109 assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2], 110 &PartMappings[PMI_GPR - PMI_Min]) && 111 "Wrong value mapping for 3 GPR ops instruction"); 112 113 assert(checkValueMapping(ValueMappings[SPR3OpsIdx], 114 &PartMappings[PMI_SPR - PMI_Min]) && 115 "Wrong value mapping for 3 SPR ops instruction"); 116 assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1], 117 &PartMappings[PMI_SPR - PMI_Min]) && 118 "Wrong value mapping for 3 SPR ops instruction"); 119 assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2], 120 &PartMappings[PMI_SPR - PMI_Min]) && 121 "Wrong value mapping for 3 SPR ops instruction"); 122 123 assert(checkValueMapping(ValueMappings[DPR3OpsIdx], 124 &PartMappings[PMI_DPR - PMI_Min]) && 125 "Wrong value mapping for 3 DPR ops instruction"); 126 assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1], 127 &PartMappings[PMI_DPR - PMI_Min]) && 128 "Wrong value mapping for 3 DPR ops instruction"); 129 assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2], 130 &PartMappings[PMI_DPR - PMI_Min]) && 131 "Wrong value mapping for 3 DPR ops instruction"); 132 } 133 #endif 134 } // end namespace arm 135 } // end namespace llvm 136 137 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 138 : ARMGenRegisterBankInfo() { 139 static bool AlreadyInit = false; 140 // We have only one set of register banks, whatever the subtarget 141 // is. Therefore, the initialization of the RegBanks table should be 142 // done only once. Indeed the table of all register banks 143 // (ARM::RegBanks) is unique in the compiler. At some point, it 144 // will get tablegen'ed and the whole constructor becomes empty. 145 if (AlreadyInit) 146 return; 147 AlreadyInit = true; 148 149 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 150 (void)RBGPR; 151 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 152 153 // Initialize the GPR bank. 154 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 155 "Subclass not added?"); 156 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 157 "Subclass not added?"); 158 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 159 "Subclass not added?"); 160 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 161 "Subclass not added?"); 162 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 163 "Subclass not added?"); 164 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 165 "Subclass not added?"); 166 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 167 "Subclass not added?"); 168 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 169 170 #ifndef NDEBUG 171 ARM::checkPartialMappings(); 172 ARM::checkValueMappings(); 173 #endif 174 } 175 176 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 177 const TargetRegisterClass &RC) const { 178 using namespace ARM; 179 180 switch (RC.getID()) { 181 case GPRRegClassID: 182 case GPRnopcRegClassID: 183 case GPRspRegClassID: 184 case tGPR_and_tcGPRRegClassID: 185 case tGPRRegClassID: 186 return getRegBank(ARM::GPRRegBankID); 187 case SPR_8RegClassID: 188 case SPRRegClassID: 189 case DPR_8RegClassID: 190 case DPRRegClassID: 191 return getRegBank(ARM::FPRRegBankID); 192 default: 193 llvm_unreachable("Unsupported register kind"); 194 } 195 196 llvm_unreachable("Switch should handle all register classes"); 197 } 198 199 const RegisterBankInfo::InstructionMapping & 200 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 201 auto Opc = MI.getOpcode(); 202 203 // Try the default logic for non-generic instructions that are either copies 204 // or already have some operands assigned to banks. 205 if (!isPreISelGenericOpcode(Opc)) { 206 const InstructionMapping &Mapping = getInstrMappingImpl(MI); 207 if (Mapping.isValid()) 208 return Mapping; 209 } 210 211 using namespace TargetOpcode; 212 213 const MachineFunction &MF = *MI.getParent()->getParent(); 214 const MachineRegisterInfo &MRI = MF.getRegInfo(); 215 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 216 217 unsigned NumOperands = MI.getNumOperands(); 218 const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 219 220 switch (Opc) { 221 case G_ADD: 222 case G_SUB: 223 case G_MUL: 224 case G_AND: 225 case G_OR: 226 case G_SDIV: 227 case G_UDIV: 228 case G_SEXT: 229 case G_ZEXT: 230 case G_ANYEXT: 231 case G_TRUNC: 232 case G_GEP: 233 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 234 // the real world we would use different mappings. 235 OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx]; 236 break; 237 case G_LOAD: 238 case G_STORE: 239 OperandsMapping = 240 Ty.getSizeInBits() == 64 241 ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 242 &ARM::ValueMappings[ARM::GPR3OpsIdx]}) 243 : &ARM::ValueMappings[ARM::GPR3OpsIdx]; 244 break; 245 case G_FADD: 246 assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) && 247 "Unsupported size for G_FADD"); 248 OperandsMapping = Ty.getSizeInBits() == 64 249 ? &ARM::ValueMappings[ARM::DPR3OpsIdx] 250 : &ARM::ValueMappings[ARM::SPR3OpsIdx]; 251 break; 252 case G_CONSTANT: 253 case G_FRAME_INDEX: 254 OperandsMapping = 255 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 256 break; 257 case G_SEQUENCE: { 258 // We only support G_SEQUENCE for creating a double precision floating point 259 // value out of two GPRs. 260 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 261 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 262 if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 263 Ty2.getSizeInBits() != 32) 264 return getInvalidInstructionMapping(); 265 OperandsMapping = 266 getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx], 267 &ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr, 268 &ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); 269 break; 270 } 271 case G_EXTRACT: { 272 // We only support G_EXTRACT for splitting a double precision floating point 273 // value into two GPRs. 274 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 275 if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 64 || 276 MI.getOperand(2).getImm() % 32 != 0) 277 return getInvalidInstructionMapping(); 278 OperandsMapping = getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], 279 &ARM::ValueMappings[ARM::DPR3OpsIdx], 280 nullptr, nullptr}); 281 break; 282 } 283 default: 284 return getInvalidInstructionMapping(); 285 } 286 287 #ifndef NDEBUG 288 for (unsigned i = 0; i < NumOperands; i++) { 289 for (const auto &Mapping : OperandsMapping[i]) { 290 assert( 291 (Mapping.RegBank->getID() != ARM::FPRRegBankID || 292 MF.getSubtarget<ARMSubtarget>().hasVFP2()) && 293 "Trying to use floating point register bank on target without vfp"); 294 } 295 } 296 #endif 297 298 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, 299 NumOperands); 300 } 301