1 //===- PPCRegisterBankInfo.cpp --------------------------------------------===// 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 10 /// PowerPC. 11 //===----------------------------------------------------------------------===// 12 13 #include "PPCRegisterBankInfo.h" 14 #include "PPCRegisterInfo.h" 15 #include "llvm/CodeGen/MachineFunction.h" 16 #include "llvm/CodeGen/MachineRegisterInfo.h" 17 #include "llvm/Support/Debug.h" 18 19 #define DEBUG_TYPE "ppc-reg-bank-info" 20 21 #define GET_TARGET_REGBANK_IMPL 22 #include "PPCGenRegisterBank.inc" 23 24 // This file will be TableGen'ed at some point. 25 #include "PPCGenRegisterBankInfo.def" 26 27 using namespace llvm; 28 29 PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {} 30 31 const RegisterBank & 32 PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 33 LLT Ty) const { 34 switch (RC.getID()) { 35 case PPC::G8RCRegClassID: 36 case PPC::G8RC_NOX0RegClassID: 37 case PPC::G8RC_and_G8RC_NOX0RegClassID: 38 case PPC::GPRCRegClassID: 39 case PPC::GPRC_NOR0RegClassID: 40 case PPC::GPRC_and_GPRC_NOR0RegClassID: 41 return getRegBank(PPC::GPRRegBankID); 42 case PPC::VSFRCRegClassID: 43 case PPC::SPILLTOVSRRC_and_VSFRCRegClassID: 44 case PPC::SPILLTOVSRRC_and_VFRCRegClassID: 45 case PPC::SPILLTOVSRRC_and_F4RCRegClassID: 46 case PPC::F8RCRegClassID: 47 case PPC::VFRCRegClassID: 48 case PPC::VSSRCRegClassID: 49 case PPC::F4RCRegClassID: 50 return getRegBank(PPC::FPRRegBankID); 51 case PPC::VSRCRegClassID: 52 case PPC::VRRCRegClassID: 53 case PPC::VRRC_with_sub_64_in_SPILLTOVSRRCRegClassID: 54 case PPC::VSRC_with_sub_64_in_SPILLTOVSRRCRegClassID: 55 case PPC::SPILLTOVSRRCRegClassID: 56 case PPC::VSLRCRegClassID: 57 case PPC::VSLRC_with_sub_64_in_SPILLTOVSRRCRegClassID: 58 return getRegBank(PPC::VECRegBankID); 59 case PPC::CRRCRegClassID: 60 case PPC::CRBITRCRegClassID: 61 return getRegBank(PPC::CRRegBankID); 62 default: 63 llvm_unreachable("Unexpected register class"); 64 } 65 } 66 67 const RegisterBankInfo::InstructionMapping & 68 PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 69 const unsigned Opc = MI.getOpcode(); 70 71 // Try the default logic for non-generic instructions that are either copies 72 // or already have some operands assigned to banks. 73 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 74 const RegisterBankInfo::InstructionMapping &Mapping = 75 getInstrMappingImpl(MI); 76 if (Mapping.isValid()) 77 return Mapping; 78 } 79 80 const MachineFunction &MF = *MI.getParent()->getParent(); 81 const MachineRegisterInfo &MRI = MF.getRegInfo(); 82 const TargetSubtargetInfo &STI = MF.getSubtarget(); 83 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 84 85 unsigned NumOperands = MI.getNumOperands(); 86 const ValueMapping *OperandsMapping = nullptr; 87 unsigned Cost = 1; 88 unsigned MappingID = DefaultMappingID; 89 90 switch (Opc) { 91 // Arithmetic ops. 92 case TargetOpcode::G_ADD: 93 case TargetOpcode::G_SUB: 94 // Bitwise ops. 95 case TargetOpcode::G_AND: 96 case TargetOpcode::G_OR: 97 case TargetOpcode::G_XOR: 98 // Extension ops. 99 case TargetOpcode::G_SEXT: 100 case TargetOpcode::G_ZEXT: 101 case TargetOpcode::G_ANYEXT: { 102 assert(NumOperands <= 3 && 103 "This code is for instructions with 3 or less operands"); 104 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 105 unsigned Size = Ty.getSizeInBits(); 106 switch (Size) { 107 case 128: 108 OperandsMapping = getValueMapping(PMI_VEC128); 109 break; 110 default: 111 OperandsMapping = getValueMapping(PMI_GPR64); 112 break; 113 } 114 break; 115 } 116 case TargetOpcode::G_FADD: 117 case TargetOpcode::G_FSUB: 118 case TargetOpcode::G_FMUL: 119 case TargetOpcode::G_FDIV: { 120 Register SrcReg = MI.getOperand(1).getReg(); 121 unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 122 123 assert((Size == 32 || Size == 64 || Size == 128) && 124 "Unsupported floating point types!\n"); 125 switch (Size) { 126 case 32: 127 OperandsMapping = getValueMapping(PMI_FPR32); 128 break; 129 case 64: 130 OperandsMapping = getValueMapping(PMI_FPR64); 131 break; 132 case 128: 133 OperandsMapping = getValueMapping(PMI_VEC128); 134 break; 135 } 136 break; 137 } 138 case TargetOpcode::G_FCMP: { 139 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 140 141 OperandsMapping = getOperandsMapping( 142 {getValueMapping(PMI_CR), nullptr, 143 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64), 144 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)}); 145 break; 146 } 147 case TargetOpcode::G_CONSTANT: 148 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); 149 break; 150 case TargetOpcode::G_CONSTANT_POOL: 151 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); 152 break; 153 case TargetOpcode::G_FPTOUI: 154 case TargetOpcode::G_FPTOSI: { 155 Register SrcReg = MI.getOperand(1).getReg(); 156 unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 157 158 OperandsMapping = getOperandsMapping( 159 {getValueMapping(PMI_GPR64), 160 getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)}); 161 break; 162 } 163 case TargetOpcode::G_UITOFP: 164 case TargetOpcode::G_SITOFP: { 165 Register SrcReg = MI.getOperand(0).getReg(); 166 unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 167 168 OperandsMapping = 169 getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64), 170 getValueMapping(PMI_GPR64)}); 171 break; 172 } 173 case TargetOpcode::G_LOAD: { 174 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 175 // Check if that load feeds fp instructions. 176 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 177 [&](const MachineInstr &UseMI) { 178 // If we have at least one direct use in a FP instruction, 179 // assume this was a floating point load in the IR. If it was 180 // not, we would have had a bitcast before reaching that 181 // instruction. 182 // 183 // Int->FP conversion operations are also captured in 184 // onlyDefinesFP(). 185 return onlyUsesFP(UseMI, MRI, TRI); 186 })) 187 OperandsMapping = getOperandsMapping( 188 {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), 189 getValueMapping(PMI_GPR64)}); 190 else 191 OperandsMapping = getOperandsMapping( 192 {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), 193 getValueMapping(PMI_GPR64)}); 194 break; 195 } 196 case TargetOpcode::G_STORE: { 197 // Check if the store is fed by fp instructions. 198 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg()); 199 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 200 if (onlyDefinesFP(*DefMI, MRI, TRI)) 201 OperandsMapping = getOperandsMapping( 202 {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), 203 getValueMapping(PMI_GPR64)}); 204 else 205 OperandsMapping = getOperandsMapping( 206 {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), 207 getValueMapping(PMI_GPR64)}); 208 break; 209 } 210 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: { 211 // FIXME: We have to check every operand in this MI and compute value 212 // mapping accordingly. 213 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 214 OperandsMapping = getOperandsMapping(OpdsMapping); 215 break; 216 } 217 case TargetOpcode::G_BITCAST: { 218 LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 219 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 220 unsigned DstSize = DstTy.getSizeInBits(); 221 222 bool DstIsGPR = !DstTy.isVector(); 223 bool SrcIsGPR = !SrcTy.isVector(); 224 // TODO: Currently, only vector and GPR register banks are handled. 225 // This needs to be extended to handle floating point register 226 // banks in the future. 227 const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank; 228 const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank; 229 230 return getInstructionMapping( 231 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize), 232 NumOperands); 233 } 234 default: 235 return getInvalidInstructionMapping(); 236 } 237 238 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands); 239 } 240 241 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode, 242 /// having only floating-point operands. 243 /// FIXME: this is copied from target AArch64. Needs some code refactor here to 244 /// put this function in GlobalISel/Utils.cpp. 245 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) { 246 switch (Opc) { 247 case TargetOpcode::G_FADD: 248 case TargetOpcode::G_FSUB: 249 case TargetOpcode::G_FMUL: 250 case TargetOpcode::G_FMA: 251 case TargetOpcode::G_FDIV: 252 case TargetOpcode::G_FCONSTANT: 253 case TargetOpcode::G_FPEXT: 254 case TargetOpcode::G_FPTRUNC: 255 case TargetOpcode::G_FCEIL: 256 case TargetOpcode::G_FFLOOR: 257 case TargetOpcode::G_FNEARBYINT: 258 case TargetOpcode::G_FNEG: 259 case TargetOpcode::G_FCOS: 260 case TargetOpcode::G_FSIN: 261 case TargetOpcode::G_FLOG10: 262 case TargetOpcode::G_FLOG: 263 case TargetOpcode::G_FLOG2: 264 case TargetOpcode::G_FSQRT: 265 case TargetOpcode::G_FABS: 266 case TargetOpcode::G_FEXP: 267 case TargetOpcode::G_FRINT: 268 case TargetOpcode::G_INTRINSIC_TRUNC: 269 case TargetOpcode::G_INTRINSIC_ROUND: 270 case TargetOpcode::G_FMAXNUM: 271 case TargetOpcode::G_FMINNUM: 272 case TargetOpcode::G_FMAXIMUM: 273 case TargetOpcode::G_FMINIMUM: 274 return true; 275 } 276 return false; 277 } 278 279 /// \returns true if a given intrinsic \p ID only uses and defines FPRs. 280 static bool isFPIntrinsic(unsigned ID) { 281 // TODO: Add more intrinsics. 282 return false; 283 } 284 285 /// FIXME: this is copied from target AArch64. Needs some code refactor here to 286 /// put this function in class RegisterBankInfo. 287 bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI, 288 const MachineRegisterInfo &MRI, 289 const TargetRegisterInfo &TRI, 290 unsigned Depth) const { 291 unsigned Op = MI.getOpcode(); 292 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MI.getIntrinsicID())) 293 return true; 294 295 // Do we have an explicit floating point instruction? 296 if (isPreISelGenericFloatingPointOpcode(Op)) 297 return true; 298 299 // No. Check if we have a copy-like instruction. If we do, then we could 300 // still be fed by floating point instructions. 301 if (Op != TargetOpcode::COPY && !MI.isPHI() && 302 !isPreISelGenericOptimizationHint(Op)) 303 return false; 304 305 // Check if we already know the register bank. 306 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI); 307 if (RB == &PPC::FPRRegBank) 308 return true; 309 if (RB == &PPC::GPRRegBank) 310 return false; 311 312 // We don't know anything. 313 // 314 // If we have a phi, we may be able to infer that it will be assigned a FPR 315 // based off of its inputs. 316 if (!MI.isPHI() || Depth > MaxFPRSearchDepth) 317 return false; 318 319 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) { 320 return Op.isReg() && 321 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1); 322 }); 323 } 324 325 /// FIXME: this is copied from target AArch64. Needs some code refactor here to 326 /// put this function in class RegisterBankInfo. 327 bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI, 328 const MachineRegisterInfo &MRI, 329 const TargetRegisterInfo &TRI, 330 unsigned Depth) const { 331 switch (MI.getOpcode()) { 332 case TargetOpcode::G_FPTOSI: 333 case TargetOpcode::G_FPTOUI: 334 case TargetOpcode::G_FCMP: 335 case TargetOpcode::G_LROUND: 336 case TargetOpcode::G_LLROUND: 337 return true; 338 default: 339 break; 340 } 341 return hasFPConstraints(MI, MRI, TRI, Depth); 342 } 343 344 /// FIXME: this is copied from target AArch64. Needs some code refactor here to 345 /// put this function in class RegisterBankInfo. 346 bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, 347 const MachineRegisterInfo &MRI, 348 const TargetRegisterInfo &TRI, 349 unsigned Depth) const { 350 switch (MI.getOpcode()) { 351 case TargetOpcode::G_SITOFP: 352 case TargetOpcode::G_UITOFP: 353 return true; 354 default: 355 break; 356 } 357 return hasFPConstraints(MI, MRI, TRI, Depth); 358 } 359 360 RegisterBankInfo::InstructionMappings 361 PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 362 // TODO Implement. 363 return RegisterBankInfo::getInstrAlternativeMappings(MI); 364 } 365