313 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements the targeting of the RegisterBankInfo class for10/// 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_IMPL23#include "PPCGenRegisterBank.inc"24 25// This file will be TableGen'ed at some point.26#include "PPCGenRegisterBankInfo.def"27 28using namespace llvm;29 30PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}31 32const RegisterBank &33PPCRegisterBankInfo::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 50const RegisterBankInfo::InstructionMapping &51PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {52 const unsigned Opc = MI.getOpcode();53 54 // Try the default logic for non-generic instructions that are either copies55 // 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 was163 // not, we would have had a bitcast before reaching that164 // instruction.165 //166 // Int->FP conversion operations are also captured in167 // onlyDefinesFP().168 return onlyUsesFP(UseMI, MRI, TRI);169 }))170 OperandsMapping = getOperandsMapping(171 {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),172 getValueMapping(PMI_GPR64)});173 else174 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 else188 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 value195 // 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 register209 // 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.225static 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 to231/// put this function in class RegisterBankInfo.232bool 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 could248 // 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 FPR263 // 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 to274/// put this function in class RegisterBankInfo.275bool 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 to293/// put this function in class RegisterBankInfo.294bool 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 308RegisterBankInfo::InstructionMappings309PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {310 // TODO Implement.311 return RegisterBankInfo::getInstrAlternativeMappings(MI);312}313