Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
96382 views
//===- PPCRegisterBankInfo.cpp --------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8/// This file implements the targeting of the RegisterBankInfo class for9/// PowerPC.10//===----------------------------------------------------------------------===//1112#include "PPCRegisterBankInfo.h"13#include "PPCRegisterInfo.h"14#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"15#include "llvm/CodeGen/GlobalISel/Utils.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/MachineRegisterInfo.h"18#include "llvm/Support/Debug.h"1920#define DEBUG_TYPE "ppc-reg-bank-info"2122#define GET_TARGET_REGBANK_IMPL23#include "PPCGenRegisterBank.inc"2425// This file will be TableGen'ed at some point.26#include "PPCGenRegisterBankInfo.def"2728using namespace llvm;2930PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}3132const RegisterBank &33PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,34LLT Ty) const {35switch (RC.getID()) {36case PPC::G8RCRegClassID:37case PPC::G8RC_NOX0RegClassID:38case PPC::G8RC_and_G8RC_NOX0RegClassID:39case PPC::GPRCRegClassID:40case PPC::GPRC_NOR0RegClassID:41case PPC::GPRC_and_GPRC_NOR0RegClassID:42return getRegBank(PPC::GPRRegBankID);43case PPC::VSFRCRegClassID:44case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:45case PPC::SPILLTOVSRRC_and_VFRCRegClassID:46case PPC::SPILLTOVSRRC_and_F4RCRegClassID:47case PPC::F8RCRegClassID:48case PPC::VFRCRegClassID:49case PPC::VSSRCRegClassID:50case PPC::F4RCRegClassID:51return getRegBank(PPC::FPRRegBankID);52case PPC::VSRCRegClassID:53case PPC::VRRCRegClassID:54case PPC::VRRC_with_sub_64_in_SPILLTOVSRRCRegClassID:55case PPC::VSRC_with_sub_64_in_SPILLTOVSRRCRegClassID:56case PPC::SPILLTOVSRRCRegClassID:57case PPC::VSLRCRegClassID:58case PPC::VSLRC_with_sub_64_in_SPILLTOVSRRCRegClassID:59return getRegBank(PPC::VECRegBankID);60case PPC::CRRCRegClassID:61case PPC::CRBITRCRegClassID:62return getRegBank(PPC::CRRegBankID);63default:64llvm_unreachable("Unexpected register class");65}66}6768const RegisterBankInfo::InstructionMapping &69PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {70const unsigned Opc = MI.getOpcode();7172// Try the default logic for non-generic instructions that are either copies73// or already have some operands assigned to banks.74if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {75const RegisterBankInfo::InstructionMapping &Mapping =76getInstrMappingImpl(MI);77if (Mapping.isValid())78return Mapping;79}8081const MachineFunction &MF = *MI.getParent()->getParent();82const MachineRegisterInfo &MRI = MF.getRegInfo();83const TargetSubtargetInfo &STI = MF.getSubtarget();84const TargetRegisterInfo &TRI = *STI.getRegisterInfo();8586unsigned NumOperands = MI.getNumOperands();87const ValueMapping *OperandsMapping = nullptr;88unsigned Cost = 1;89unsigned MappingID = DefaultMappingID;9091switch (Opc) {92// Arithmetic ops.93case TargetOpcode::G_ADD:94case TargetOpcode::G_SUB:95// Bitwise ops.96case TargetOpcode::G_AND:97case TargetOpcode::G_OR:98case TargetOpcode::G_XOR:99// Extension ops.100case TargetOpcode::G_SEXT:101case TargetOpcode::G_ZEXT:102case TargetOpcode::G_ANYEXT: {103assert(NumOperands <= 3 &&104"This code is for instructions with 3 or less operands");105LLT Ty = MRI.getType(MI.getOperand(0).getReg());106unsigned Size = Ty.getSizeInBits();107switch (Size) {108case 128:109OperandsMapping = getValueMapping(PMI_VEC128);110break;111default:112OperandsMapping = getValueMapping(PMI_GPR64);113break;114}115break;116}117case TargetOpcode::G_FADD:118case TargetOpcode::G_FSUB:119case TargetOpcode::G_FMUL:120case TargetOpcode::G_FDIV: {121Register SrcReg = MI.getOperand(1).getReg();122unsigned Size = getSizeInBits(SrcReg, MRI, TRI);123124assert((Size == 32 || Size == 64 || Size == 128) &&125"Unsupported floating point types!\n");126switch (Size) {127case 32:128OperandsMapping = getValueMapping(PMI_FPR32);129break;130case 64:131OperandsMapping = getValueMapping(PMI_FPR64);132break;133case 128:134OperandsMapping = getValueMapping(PMI_VEC128);135break;136}137break;138}139case TargetOpcode::G_FCMP: {140unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();141142OperandsMapping = getOperandsMapping(143{getValueMapping(PMI_CR), nullptr,144getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),145getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});146break;147}148case TargetOpcode::G_CONSTANT:149OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});150break;151case TargetOpcode::G_CONSTANT_POOL:152OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});153break;154case TargetOpcode::G_FPTOUI:155case TargetOpcode::G_FPTOSI: {156Register SrcReg = MI.getOperand(1).getReg();157unsigned Size = getSizeInBits(SrcReg, MRI, TRI);158159OperandsMapping = getOperandsMapping(160{getValueMapping(PMI_GPR64),161getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});162break;163}164case TargetOpcode::G_UITOFP:165case TargetOpcode::G_SITOFP: {166Register SrcReg = MI.getOperand(0).getReg();167unsigned Size = getSizeInBits(SrcReg, MRI, TRI);168169OperandsMapping =170getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),171getValueMapping(PMI_GPR64)});172break;173}174case TargetOpcode::G_LOAD: {175unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();176// Check if that load feeds fp instructions.177if (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 was181// not, we would have had a bitcast before reaching that182// instruction.183//184// Int->FP conversion operations are also captured in185// onlyDefinesFP().186return onlyUsesFP(UseMI, MRI, TRI);187}))188OperandsMapping = getOperandsMapping(189{getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),190getValueMapping(PMI_GPR64)});191else192OperandsMapping = getOperandsMapping(193{getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),194getValueMapping(PMI_GPR64)});195break;196}197case TargetOpcode::G_STORE: {198// Check if the store is fed by fp instructions.199MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());200unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();201if (onlyDefinesFP(*DefMI, MRI, TRI))202OperandsMapping = getOperandsMapping(203{getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),204getValueMapping(PMI_GPR64)});205else206OperandsMapping = getOperandsMapping(207{getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),208getValueMapping(PMI_GPR64)});209break;210}211case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {212// FIXME: We have to check every operand in this MI and compute value213// mapping accordingly.214SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);215OperandsMapping = getOperandsMapping(OpdsMapping);216break;217}218case TargetOpcode::G_BITCAST: {219LLT DstTy = MRI.getType(MI.getOperand(0).getReg());220LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());221unsigned DstSize = DstTy.getSizeInBits();222223bool DstIsGPR = !DstTy.isVector();224bool SrcIsGPR = !SrcTy.isVector();225// TODO: Currently, only vector and GPR register banks are handled.226// This needs to be extended to handle floating point register227// banks in the future.228const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;229const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;230231return getInstructionMapping(232MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),233NumOperands);234}235default:236return getInvalidInstructionMapping();237}238239return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);240}241242/// \returns true if a given intrinsic \p ID only uses and defines FPRs.243static bool isFPIntrinsic(unsigned ID) {244// TODO: Add more intrinsics.245return false;246}247248/// FIXME: this is copied from target AArch64. Needs some code refactor here to249/// put this function in class RegisterBankInfo.250bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,251const MachineRegisterInfo &MRI,252const TargetRegisterInfo &TRI,253unsigned Depth) const {254unsigned Op = MI.getOpcode();255256if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {257if (isFPIntrinsic(GI->getIntrinsicID()))258return true;259}260261// Do we have an explicit floating point instruction?262if (isPreISelGenericFloatingPointOpcode(Op))263return true;264265// No. Check if we have a copy-like instruction. If we do, then we could266// still be fed by floating point instructions.267if (Op != TargetOpcode::COPY && !MI.isPHI() &&268!isPreISelGenericOptimizationHint(Op))269return false;270271// Check if we already know the register bank.272auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);273if (RB == &PPC::FPRRegBank)274return true;275if (RB == &PPC::GPRRegBank)276return false;277278// We don't know anything.279//280// If we have a phi, we may be able to infer that it will be assigned a FPR281// based off of its inputs.282if (!MI.isPHI() || Depth > MaxFPRSearchDepth)283return false;284285return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {286return Op.isReg() &&287onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);288});289}290291/// FIXME: this is copied from target AArch64. Needs some code refactor here to292/// put this function in class RegisterBankInfo.293bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,294const MachineRegisterInfo &MRI,295const TargetRegisterInfo &TRI,296unsigned Depth) const {297switch (MI.getOpcode()) {298case TargetOpcode::G_FPTOSI:299case TargetOpcode::G_FPTOUI:300case TargetOpcode::G_FCMP:301case TargetOpcode::G_LROUND:302case TargetOpcode::G_LLROUND:303return true;304default:305break;306}307return hasFPConstraints(MI, MRI, TRI, Depth);308}309310/// FIXME: this is copied from target AArch64. Needs some code refactor here to311/// put this function in class RegisterBankInfo.312bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,313const MachineRegisterInfo &MRI,314const TargetRegisterInfo &TRI,315unsigned Depth) const {316switch (MI.getOpcode()) {317case TargetOpcode::G_SITOFP:318case TargetOpcode::G_UITOFP:319return true;320default:321break;322}323return hasFPConstraints(MI, MRI, TRI, Depth);324}325326RegisterBankInfo::InstructionMappings327PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {328// TODO Implement.329return RegisterBankInfo::getInstrAlternativeMappings(MI);330}331332333