1009cd4e4SKit Barton //===- PPCRegisterBankInfo.cpp --------------------------------------------===// 2009cd4e4SKit Barton // 3009cd4e4SKit Barton // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4009cd4e4SKit Barton // See https://llvm.org/LICENSE.txt for license information. 5009cd4e4SKit Barton // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6009cd4e4SKit Barton // 7009cd4e4SKit Barton //===----------------------------------------------------------------------===// 8009cd4e4SKit Barton /// \file 9009cd4e4SKit Barton /// This file implements the targeting of the RegisterBankInfo class for 10009cd4e4SKit Barton /// PowerPC. 11009cd4e4SKit Barton //===----------------------------------------------------------------------===// 12009cd4e4SKit Barton 13009cd4e4SKit Barton #include "PPCRegisterBankInfo.h" 14009cd4e4SKit Barton #include "PPCRegisterInfo.h" 157c760b22SSameer Sahasrabuddhe #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 1692e96c7bSMalay Sanghi #include "llvm/CodeGen/GlobalISel/Utils.h" 17009cd4e4SKit Barton #include "llvm/CodeGen/MachineFunction.h" 18009cd4e4SKit Barton #include "llvm/CodeGen/MachineRegisterInfo.h" 19009cd4e4SKit Barton 20009cd4e4SKit Barton #define DEBUG_TYPE "ppc-reg-bank-info" 21009cd4e4SKit Barton 22009cd4e4SKit Barton #define GET_TARGET_REGBANK_IMPL 23009cd4e4SKit Barton #include "PPCGenRegisterBank.inc" 24009cd4e4SKit Barton 25be4a1dfbSKai Nacke // This file will be TableGen'ed at some point. 26be4a1dfbSKai Nacke #include "PPCGenRegisterBankInfo.def" 27be4a1dfbSKai Nacke 28009cd4e4SKit Barton using namespace llvm; 29009cd4e4SKit Barton 3062128719SKazu Hirata PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {} 31be4a1dfbSKai Nacke 32be4a1dfbSKai Nacke const RegisterBank & 33be4a1dfbSKai Nacke PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 34be4a1dfbSKai Nacke LLT Ty) const { 35be4a1dfbSKai Nacke switch (RC.getID()) { 36d9143ce3SChen Zheng case PPC::VSFRCRegClassID: 37d9143ce3SChen Zheng case PPC::SPILLTOVSRRC_and_VSFRCRegClassID: 38d9143ce3SChen Zheng case PPC::SPILLTOVSRRC_and_VFRCRegClassID: 39d9143ce3SChen Zheng case PPC::SPILLTOVSRRC_and_F4RCRegClassID: 40d9143ce3SChen Zheng case PPC::F8RCRegClassID: 41d9143ce3SChen Zheng case PPC::VFRCRegClassID: 42d9143ce3SChen Zheng case PPC::VSSRCRegClassID: 43d9143ce3SChen Zheng case PPC::F4RCRegClassID: 44d9143ce3SChen Zheng return getRegBank(PPC::FPRRegBankID); 45be4a1dfbSKai Nacke default: 46*a79db96eSKai Nacke return PPCGenRegisterBankInfo::getRegBankFromRegClass(RC, Ty); 47be4a1dfbSKai Nacke } 48be4a1dfbSKai Nacke } 49be4a1dfbSKai Nacke 50be4a1dfbSKai Nacke const RegisterBankInfo::InstructionMapping & 51be4a1dfbSKai Nacke PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 52be4a1dfbSKai Nacke const unsigned Opc = MI.getOpcode(); 53be4a1dfbSKai Nacke 54be4a1dfbSKai Nacke // Try the default logic for non-generic instructions that are either copies 55be4a1dfbSKai Nacke // or already have some operands assigned to banks. 56be4a1dfbSKai Nacke if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 57be4a1dfbSKai Nacke const RegisterBankInfo::InstructionMapping &Mapping = 58be4a1dfbSKai Nacke getInstrMappingImpl(MI); 59be4a1dfbSKai Nacke if (Mapping.isValid()) 60be4a1dfbSKai Nacke return Mapping; 61be4a1dfbSKai Nacke } 62be4a1dfbSKai Nacke 63d9143ce3SChen Zheng const MachineFunction &MF = *MI.getParent()->getParent(); 64d9143ce3SChen Zheng const MachineRegisterInfo &MRI = MF.getRegInfo(); 65d9143ce3SChen Zheng const TargetSubtargetInfo &STI = MF.getSubtarget(); 66d9143ce3SChen Zheng const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 67d9143ce3SChen Zheng 68be4a1dfbSKai Nacke unsigned NumOperands = MI.getNumOperands(); 69be4a1dfbSKai Nacke const ValueMapping *OperandsMapping = nullptr; 70be4a1dfbSKai Nacke unsigned Cost = 1; 71be4a1dfbSKai Nacke unsigned MappingID = DefaultMappingID; 72be4a1dfbSKai Nacke 73be4a1dfbSKai Nacke switch (Opc) { 742b1e895aSKai Nacke // Arithmetic ops. 752b1e895aSKai Nacke case TargetOpcode::G_ADD: 762b1e895aSKai Nacke case TargetOpcode::G_SUB: 77be4a1dfbSKai Nacke // Bitwise ops. 78be4a1dfbSKai Nacke case TargetOpcode::G_AND: 79be4a1dfbSKai Nacke case TargetOpcode::G_OR: 80be4a1dfbSKai Nacke case TargetOpcode::G_XOR: 81b41d22dbSChen Zheng // Extension ops. 82b41d22dbSChen Zheng case TargetOpcode::G_SEXT: 83b41d22dbSChen Zheng case TargetOpcode::G_ZEXT: 843508f123SAmy Kwan case TargetOpcode::G_ANYEXT: { 85be4a1dfbSKai Nacke assert(NumOperands <= 3 && 86be4a1dfbSKai Nacke "This code is for instructions with 3 or less operands"); 873508f123SAmy Kwan LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 883508f123SAmy Kwan unsigned Size = Ty.getSizeInBits(); 893508f123SAmy Kwan switch (Size) { 903508f123SAmy Kwan case 128: 913508f123SAmy Kwan OperandsMapping = getValueMapping(PMI_VEC128); 923508f123SAmy Kwan break; 933508f123SAmy Kwan default: 94be4a1dfbSKai Nacke OperandsMapping = getValueMapping(PMI_GPR64); 95be4a1dfbSKai Nacke break; 963508f123SAmy Kwan } 973508f123SAmy Kwan break; 983508f123SAmy Kwan } 99d9143ce3SChen Zheng case TargetOpcode::G_FADD: 100d9143ce3SChen Zheng case TargetOpcode::G_FSUB: 101d9143ce3SChen Zheng case TargetOpcode::G_FMUL: 102d9143ce3SChen Zheng case TargetOpcode::G_FDIV: { 103d9143ce3SChen Zheng Register SrcReg = MI.getOperand(1).getReg(); 104d9143ce3SChen Zheng unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 105d9143ce3SChen Zheng 1063508f123SAmy Kwan assert((Size == 32 || Size == 64 || Size == 128) && 1073508f123SAmy Kwan "Unsupported floating point types!\n"); 1083508f123SAmy Kwan switch (Size) { 1093508f123SAmy Kwan case 32: 1103508f123SAmy Kwan OperandsMapping = getValueMapping(PMI_FPR32); 1113508f123SAmy Kwan break; 1123508f123SAmy Kwan case 64: 1133508f123SAmy Kwan OperandsMapping = getValueMapping(PMI_FPR64); 1143508f123SAmy Kwan break; 1153508f123SAmy Kwan case 128: 1163508f123SAmy Kwan OperandsMapping = getValueMapping(PMI_VEC128); 1173508f123SAmy Kwan break; 1183508f123SAmy Kwan } 119d9143ce3SChen Zheng break; 120d9143ce3SChen Zheng } 121ac93a4e7SChen Zheng case TargetOpcode::G_FCMP: { 122ac93a4e7SChen Zheng unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits(); 123ac93a4e7SChen Zheng 124ac93a4e7SChen Zheng OperandsMapping = getOperandsMapping( 125ac93a4e7SChen Zheng {getValueMapping(PMI_CR), nullptr, 126ac93a4e7SChen Zheng getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64), 127ac93a4e7SChen Zheng getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)}); 128ac93a4e7SChen Zheng break; 129ac93a4e7SChen Zheng } 130be4a1dfbSKai Nacke case TargetOpcode::G_CONSTANT: 131be4a1dfbSKai Nacke OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); 132be4a1dfbSKai Nacke break; 1336ee2f770SChen Zheng case TargetOpcode::G_CONSTANT_POOL: 1346ee2f770SChen Zheng OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr}); 1356ee2f770SChen Zheng break; 1360a9b1c59SChen Zheng case TargetOpcode::G_FPTOUI: 1370a9b1c59SChen Zheng case TargetOpcode::G_FPTOSI: { 1380a9b1c59SChen Zheng Register SrcReg = MI.getOperand(1).getReg(); 1390a9b1c59SChen Zheng unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 1400a9b1c59SChen Zheng 1410a9b1c59SChen Zheng OperandsMapping = getOperandsMapping( 1420a9b1c59SChen Zheng {getValueMapping(PMI_GPR64), 1430a9b1c59SChen Zheng getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)}); 1440a9b1c59SChen Zheng break; 1450a9b1c59SChen Zheng } 1460a9b1c59SChen Zheng case TargetOpcode::G_UITOFP: 1470a9b1c59SChen Zheng case TargetOpcode::G_SITOFP: { 1480a9b1c59SChen Zheng Register SrcReg = MI.getOperand(0).getReg(); 1490a9b1c59SChen Zheng unsigned Size = getSizeInBits(SrcReg, MRI, TRI); 1500a9b1c59SChen Zheng 1510a9b1c59SChen Zheng OperandsMapping = 1520a9b1c59SChen Zheng getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64), 1530a9b1c59SChen Zheng getValueMapping(PMI_GPR64)}); 1540a9b1c59SChen Zheng break; 1550a9b1c59SChen Zheng } 156503a935dSChen Zheng case TargetOpcode::G_LOAD: { 157b41d22dbSChen Zheng unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 158503a935dSChen Zheng // Check if that load feeds fp instructions. 159503a935dSChen Zheng if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()), 160503a935dSChen Zheng [&](const MachineInstr &UseMI) { 161503a935dSChen Zheng // If we have at least one direct use in a FP instruction, 162503a935dSChen Zheng // assume this was a floating point load in the IR. If it was 163503a935dSChen Zheng // not, we would have had a bitcast before reaching that 164503a935dSChen Zheng // instruction. 165503a935dSChen Zheng // 166503a935dSChen Zheng // Int->FP conversion operations are also captured in 167503a935dSChen Zheng // onlyDefinesFP(). 168503a935dSChen Zheng return onlyUsesFP(UseMI, MRI, TRI); 169503a935dSChen Zheng })) 170503a935dSChen Zheng OperandsMapping = getOperandsMapping( 171b41d22dbSChen Zheng {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), 172b41d22dbSChen Zheng getValueMapping(PMI_GPR64)}); 173503a935dSChen Zheng else 174503a935dSChen Zheng OperandsMapping = getOperandsMapping( 175b41d22dbSChen Zheng {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), 176b41d22dbSChen Zheng getValueMapping(PMI_GPR64)}); 177503a935dSChen Zheng break; 178503a935dSChen Zheng } 179503a935dSChen Zheng case TargetOpcode::G_STORE: { 180503a935dSChen Zheng // Check if the store is fed by fp instructions. 181503a935dSChen Zheng MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg()); 182b41d22dbSChen Zheng unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); 183503a935dSChen Zheng if (onlyDefinesFP(*DefMI, MRI, TRI)) 184503a935dSChen Zheng OperandsMapping = getOperandsMapping( 185b41d22dbSChen Zheng {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32), 186b41d22dbSChen Zheng getValueMapping(PMI_GPR64)}); 187503a935dSChen Zheng else 188503a935dSChen Zheng OperandsMapping = getOperandsMapping( 189b41d22dbSChen Zheng {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32), 190b41d22dbSChen Zheng getValueMapping(PMI_GPR64)}); 191503a935dSChen Zheng break; 192503a935dSChen Zheng } 193d9630c34SKai Luo case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: { 194d9630c34SKai Luo // FIXME: We have to check every operand in this MI and compute value 195d9630c34SKai Luo // mapping accordingly. 196d9630c34SKai Luo SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 197d9630c34SKai Luo OperandsMapping = getOperandsMapping(OpdsMapping); 198d9630c34SKai Luo break; 199d9630c34SKai Luo } 2003508f123SAmy Kwan case TargetOpcode::G_BITCAST: { 2013508f123SAmy Kwan LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); 2023508f123SAmy Kwan LLT SrcTy = MRI.getType(MI.getOperand(1).getReg()); 2033508f123SAmy Kwan unsigned DstSize = DstTy.getSizeInBits(); 2043508f123SAmy Kwan 2053508f123SAmy Kwan bool DstIsGPR = !DstTy.isVector(); 2063508f123SAmy Kwan bool SrcIsGPR = !SrcTy.isVector(); 2073508f123SAmy Kwan // TODO: Currently, only vector and GPR register banks are handled. 2083508f123SAmy Kwan // This needs to be extended to handle floating point register 2093508f123SAmy Kwan // banks in the future. 2103508f123SAmy Kwan const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank; 2113508f123SAmy Kwan const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank; 2123508f123SAmy Kwan 2133508f123SAmy Kwan return getInstructionMapping( 2143508f123SAmy Kwan MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize), 2153508f123SAmy Kwan NumOperands); 2163508f123SAmy Kwan } 217be4a1dfbSKai Nacke default: 218be4a1dfbSKai Nacke return getInvalidInstructionMapping(); 219be4a1dfbSKai Nacke } 220be4a1dfbSKai Nacke 221be4a1dfbSKai Nacke return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands); 222be4a1dfbSKai Nacke } 223be4a1dfbSKai Nacke 224503a935dSChen Zheng /// \returns true if a given intrinsic \p ID only uses and defines FPRs. 225503a935dSChen Zheng static bool isFPIntrinsic(unsigned ID) { 226503a935dSChen Zheng // TODO: Add more intrinsics. 227503a935dSChen Zheng return false; 228503a935dSChen Zheng } 229503a935dSChen Zheng 230503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to 231503a935dSChen Zheng /// put this function in class RegisterBankInfo. 232503a935dSChen Zheng bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI, 233503a935dSChen Zheng const MachineRegisterInfo &MRI, 234503a935dSChen Zheng const TargetRegisterInfo &TRI, 235503a935dSChen Zheng unsigned Depth) const { 236503a935dSChen Zheng unsigned Op = MI.getOpcode(); 2377c760b22SSameer Sahasrabuddhe 2387c760b22SSameer Sahasrabuddhe if (auto *GI = dyn_cast<GIntrinsic>(&MI)) { 2397c760b22SSameer Sahasrabuddhe if (isFPIntrinsic(GI->getIntrinsicID())) 240503a935dSChen Zheng return true; 2417c760b22SSameer Sahasrabuddhe } 242503a935dSChen Zheng 243503a935dSChen Zheng // Do we have an explicit floating point instruction? 244503a935dSChen Zheng if (isPreISelGenericFloatingPointOpcode(Op)) 245503a935dSChen Zheng return true; 246503a935dSChen Zheng 247503a935dSChen Zheng // No. Check if we have a copy-like instruction. If we do, then we could 248503a935dSChen Zheng // still be fed by floating point instructions. 249503a935dSChen Zheng if (Op != TargetOpcode::COPY && !MI.isPHI() && 250503a935dSChen Zheng !isPreISelGenericOptimizationHint(Op)) 251503a935dSChen Zheng return false; 252503a935dSChen Zheng 253503a935dSChen Zheng // Check if we already know the register bank. 254503a935dSChen Zheng auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI); 255503a935dSChen Zheng if (RB == &PPC::FPRRegBank) 256503a935dSChen Zheng return true; 257503a935dSChen Zheng if (RB == &PPC::GPRRegBank) 258503a935dSChen Zheng return false; 259503a935dSChen Zheng 260503a935dSChen Zheng // We don't know anything. 261503a935dSChen Zheng // 262503a935dSChen Zheng // If we have a phi, we may be able to infer that it will be assigned a FPR 263503a935dSChen Zheng // based off of its inputs. 264503a935dSChen Zheng if (!MI.isPHI() || Depth > MaxFPRSearchDepth) 265503a935dSChen Zheng return false; 266503a935dSChen Zheng 267503a935dSChen Zheng return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) { 268503a935dSChen Zheng return Op.isReg() && 269503a935dSChen Zheng onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1); 270503a935dSChen Zheng }); 271503a935dSChen Zheng } 272503a935dSChen Zheng 273503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to 274503a935dSChen Zheng /// put this function in class RegisterBankInfo. 275503a935dSChen Zheng bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI, 276503a935dSChen Zheng const MachineRegisterInfo &MRI, 277503a935dSChen Zheng const TargetRegisterInfo &TRI, 278503a935dSChen Zheng unsigned Depth) const { 279503a935dSChen Zheng switch (MI.getOpcode()) { 280503a935dSChen Zheng case TargetOpcode::G_FPTOSI: 281503a935dSChen Zheng case TargetOpcode::G_FPTOUI: 282503a935dSChen Zheng case TargetOpcode::G_FCMP: 283503a935dSChen Zheng case TargetOpcode::G_LROUND: 284503a935dSChen Zheng case TargetOpcode::G_LLROUND: 285503a935dSChen Zheng return true; 286503a935dSChen Zheng default: 287503a935dSChen Zheng break; 288503a935dSChen Zheng } 289503a935dSChen Zheng return hasFPConstraints(MI, MRI, TRI, Depth); 290503a935dSChen Zheng } 291503a935dSChen Zheng 292503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to 293503a935dSChen Zheng /// put this function in class RegisterBankInfo. 294503a935dSChen Zheng bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, 295503a935dSChen Zheng const MachineRegisterInfo &MRI, 296503a935dSChen Zheng const TargetRegisterInfo &TRI, 297503a935dSChen Zheng unsigned Depth) const { 298503a935dSChen Zheng switch (MI.getOpcode()) { 299503a935dSChen Zheng case TargetOpcode::G_SITOFP: 300503a935dSChen Zheng case TargetOpcode::G_UITOFP: 301503a935dSChen Zheng return true; 302503a935dSChen Zheng default: 303503a935dSChen Zheng break; 304503a935dSChen Zheng } 305503a935dSChen Zheng return hasFPConstraints(MI, MRI, TRI, Depth); 306503a935dSChen Zheng } 307503a935dSChen Zheng 308be4a1dfbSKai Nacke RegisterBankInfo::InstructionMappings 309be4a1dfbSKai Nacke PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 310be4a1dfbSKai Nacke // TODO Implement. 311be4a1dfbSKai Nacke return RegisterBankInfo::getInstrAlternativeMappings(MI); 312be4a1dfbSKai Nacke } 313