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