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