brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.2 KiB · b23d791 Raw
448 lines · cpp
1//===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//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 for X86.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//12 13#include "X86RegisterBankInfo.h"14#include "X86InstrInfo.h"15#include "X86Subtarget.h"16#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"17#include "llvm/CodeGen/GlobalISel/Utils.h"18#include "llvm/CodeGen/MachineRegisterInfo.h"19#include "llvm/CodeGen/RegisterBank.h"20#include "llvm/CodeGen/RegisterBankInfo.h"21#include "llvm/CodeGen/TargetRegisterInfo.h"22#include "llvm/IR/IntrinsicsX86.h"23 24#define GET_TARGET_REGBANK_IMPL25#include "X86GenRegisterBank.inc"26 27using namespace llvm;28// This file will be TableGen'ed at some point.29#define GET_TARGET_REGBANK_INFO_IMPL30#include "X86GenRegisterBankInfo.def"31 32X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) {33 34  // validate RegBank initialization.35  const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);36  (void)RBGPR;37  assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");38 39  // The GPR register bank is fully defined by all the registers in40  // GR64 + its subclasses.41  assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&42         "Subclass not added?");43  assert(getMaximumSize(RBGPR.getID()) == 64 &&44         "GPRs should hold up to 64-bit");45}46 47// \returns true if a given intrinsic only uses and defines FPRs.48static bool isFPIntrinsic(const MachineRegisterInfo &MRI,49                          const MachineInstr &MI) {50  // TODO: Add more intrinsics.51  switch (cast<GIntrinsic>(MI).getIntrinsicID()) {52  default:53    return false;54  // SSE155  case Intrinsic::x86_sse_rcp_ss:56  case Intrinsic::x86_sse_rcp_ps:57  case Intrinsic::x86_sse_rsqrt_ss:58  case Intrinsic::x86_sse_rsqrt_ps:59  case Intrinsic::x86_sse_min_ss:60  case Intrinsic::x86_sse_min_ps:61  case Intrinsic::x86_sse_max_ss:62  case Intrinsic::x86_sse_max_ps:63    return true;64  }65  return false;66}67 68bool X86RegisterBankInfo::hasFPConstraints(const MachineInstr &MI,69                                           const MachineRegisterInfo &MRI,70                                           const TargetRegisterInfo &TRI,71                                           unsigned Depth) const {72  unsigned Op = MI.getOpcode();73  if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI))74    return true;75 76  // Do we have an explicit floating point instruction?77  if (isPreISelGenericFloatingPointOpcode(Op))78    return true;79 80  // No. Check if we have a copy-like instruction. If we do, then we could81  // still be fed by floating point instructions.82  if (Op != TargetOpcode::COPY && !MI.isPHI() &&83      !isPreISelGenericOptimizationHint(Op))84    return false;85 86  // Check if we already know the register bank.87  auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);88  if (RB == &getRegBank(X86::PSRRegBankID))89    return true;90  if (RB == &getRegBank(X86::GPRRegBankID))91    return false;92 93  // We don't know anything.94  //95  // If we have a phi, we may be able to infer that it will be assigned a fp96  // type based off of its inputs.97  if (!MI.isPHI() || Depth > MaxFPRSearchDepth)98    return false;99 100  return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {101    return Op.isReg() &&102           onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);103  });104}105 106bool X86RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,107                                     const MachineRegisterInfo &MRI,108                                     const TargetRegisterInfo &TRI,109                                     unsigned Depth) const {110  switch (MI.getOpcode()) {111  case TargetOpcode::G_FPTOSI:112  case TargetOpcode::G_FPTOUI:113  case TargetOpcode::G_FCMP:114  case X86::G_FIST:115  case TargetOpcode::G_LROUND:116  case TargetOpcode::G_LLROUND:117  case TargetOpcode::G_INTRINSIC_TRUNC:118  case TargetOpcode::G_INTRINSIC_ROUND:119    return true;120  default:121    break;122  }123  return hasFPConstraints(MI, MRI, TRI, Depth);124}125 126bool X86RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,127                                        const MachineRegisterInfo &MRI,128                                        const TargetRegisterInfo &TRI,129                                        unsigned Depth) const {130  switch (MI.getOpcode()) {131  case TargetOpcode::G_SITOFP:132  case TargetOpcode::G_UITOFP:133  case X86::G_FILD:134    return true;135  default:136    break;137  }138  return hasFPConstraints(MI, MRI, TRI, Depth);139}140 141X86GenRegisterBankInfo::PartialMappingIdx142X86GenRegisterBankInfo::getPartialMappingIdx(const MachineInstr &MI,143                                             const LLT &Ty, bool isFP) {144  const MachineFunction *MF = MI.getMF();145  const X86Subtarget *ST = &MF->getSubtarget<X86Subtarget>();146  bool HasSSE1 = ST->hasSSE1();147  bool HasSSE2 = ST->hasSSE2();148  // 80 bits is only generated for X87 floating points.149  if (Ty.getSizeInBits() == 80)150    isFP = true;151  if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {152    switch (Ty.getSizeInBits()) {153    case 1:154    case 8:155      return PMI_GPR8;156    case 16:157      return PMI_GPR16;158    case 32:159      return PMI_GPR32;160    case 64:161      return PMI_GPR64;162    case 128:163      return PMI_VEC128;164      break;165    default:166      llvm_unreachable("Unsupported register size.");167    }168  } else if (Ty.isScalar()) {169    switch (Ty.getSizeInBits()) {170    case 32:171      return HasSSE1 ? PMI_FP32 : PMI_PSR32;172    case 64:173      return HasSSE2 ? PMI_FP64 : PMI_PSR64;174    case 128:175      return PMI_VEC128;176    case 80:177      return PMI_PSR80;178    default:179      llvm_unreachable("Unsupported register size.");180    }181  } else {182    switch (Ty.getSizeInBits()) {183    case 128:184      return PMI_VEC128;185    case 256:186      return PMI_VEC256;187    case 512:188      return PMI_VEC512;189    default:190      llvm_unreachable("Unsupported register size.");191    }192  }193 194  return PMI_None;195}196 197void X86RegisterBankInfo::getInstrPartialMappingIdxs(198    const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,199    SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {200 201  unsigned NumOperands = MI.getNumOperands();202  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {203    auto &MO = MI.getOperand(Idx);204    if (!MO.isReg() || !MO.getReg())205      OpRegBankIdx[Idx] = PMI_None;206    else207      OpRegBankIdx[Idx] =208          getPartialMappingIdx(MI, MRI.getType(MO.getReg()), isFP);209  }210}211 212bool X86RegisterBankInfo::getInstrValueMapping(213    const MachineInstr &MI,214    const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,215    SmallVectorImpl<const ValueMapping *> &OpdsMapping) {216 217  unsigned NumOperands = MI.getNumOperands();218  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {219    if (!MI.getOperand(Idx).isReg())220      continue;221    if (!MI.getOperand(Idx).getReg())222      continue;223 224    auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);225    if (!Mapping->isValid())226      return false;227 228    OpdsMapping[Idx] = Mapping;229  }230  return true;231}232 233const RegisterBankInfo::InstructionMapping &234X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,235                                            bool isFP) const {236  const MachineFunction &MF = *MI.getParent()->getParent();237  const MachineRegisterInfo &MRI = MF.getRegInfo();238 239  unsigned NumOperands = MI.getNumOperands();240  LLT Ty = MRI.getType(MI.getOperand(0).getReg());241 242  if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||243      (Ty != MRI.getType(MI.getOperand(2).getReg())))244    llvm_unreachable("Unsupported operand mapping yet.");245 246  auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, isFP), 3);247  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);248}249 250const RegisterBankInfo::InstructionMapping &251X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {252  const MachineFunction &MF = *MI.getParent()->getParent();253  const TargetSubtargetInfo &STI = MF.getSubtarget();254  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();255  const MachineRegisterInfo &MRI = MF.getRegInfo();256  unsigned Opc = MI.getOpcode();257 258  // Try the default logic for non-generic instructions that are either259  // copies or already have some operands assigned to banks.260  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {261    const InstructionMapping &Mapping = getInstrMappingImpl(MI);262    if (Mapping.isValid())263      return Mapping;264  }265 266  switch (Opc) {267  case TargetOpcode::G_ADD:268  case TargetOpcode::G_SUB:269  case TargetOpcode::G_MUL:270    return getSameOperandsMapping(MI, false);271  case TargetOpcode::G_FADD:272  case TargetOpcode::G_FSUB:273  case TargetOpcode::G_FMUL:274  case TargetOpcode::G_FDIV:275    return getSameOperandsMapping(MI, true);276  case TargetOpcode::G_SHL:277  case TargetOpcode::G_LSHR:278  case TargetOpcode::G_ASHR: {279    unsigned NumOperands = MI.getNumOperands();280    LLT Ty = MRI.getType(MI.getOperand(0).getReg());281 282    auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, false), 3);283    return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);284  }285  default:286    break;287  }288 289  unsigned NumOperands = MI.getNumOperands();290  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);291 292  switch (Opc) {293  case TargetOpcode::G_FSQRT:294  case TargetOpcode::G_FPEXT:295  case TargetOpcode::G_FPTRUNC:296  case TargetOpcode::G_FCONSTANT:297    // Instruction having only floating-point operands (all scalars in298    // VECRReg)299    getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);300    break;301  case X86::G_FIST:302  case X86::G_FILD: {303    auto &Op0 = MI.getOperand(0);304    auto &Op1 = MI.getOperand(1);305    const LLT Ty0 = MRI.getType(Op0.getReg());306    const LLT Ty1 = MRI.getType(Op1.getReg());307    OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ true);308    OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ false);309    break;310  }311  case TargetOpcode::G_SITOFP:312  case TargetOpcode::G_FPTOSI:313  case TargetOpcode::G_UITOFP:314  case TargetOpcode::G_FPTOUI: {315    // Some of the floating-point instructions have mixed GPR and FP316    // operands: fine-tune the computed mapping.317    auto &Op0 = MI.getOperand(0);318    auto &Op1 = MI.getOperand(1);319    const LLT Ty0 = MRI.getType(Op0.getReg());320    const LLT Ty1 = MRI.getType(Op1.getReg());321 322    bool FirstArgIsFP =323        Opc == TargetOpcode::G_SITOFP || Opc == TargetOpcode::G_UITOFP;324    OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);325    OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ !FirstArgIsFP);326    break;327  }328  case TargetOpcode::G_FCMP: {329    LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());330    LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());331    (void)Ty2;332    assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&333           "Mismatched operand sizes for G_FCMP");334 335    unsigned Size = Ty1.getSizeInBits();336    (void)Size;337    assert((Size == 32 || Size == 64 || Size == 80) &&338           "Unsupported size for G_FCMP");339    auto FpRegBank = getPartialMappingIdx(MI, Ty1, /* isFP= */ true);340    OpRegBankIdx = {PMI_GPR8,341                    /* Predicate */ PMI_None, FpRegBank, FpRegBank};342    break;343  }344  case TargetOpcode::G_FABS:345  case TargetOpcode::G_TRUNC:346  case TargetOpcode::G_ANYEXT: {347    auto &Op0 = MI.getOperand(0);348    auto &Op1 = MI.getOperand(1);349    const LLT Ty0 = MRI.getType(Op0.getReg());350    const LLT Ty1 = MRI.getType(Op1.getReg());351 352    bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&353                     Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;354    bool isFPAnyExt =355        Ty0.getSizeInBits() == 128 &&356        (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&357        Opc == TargetOpcode::G_ANYEXT;358    bool isFAbs = (Opc == TargetOpcode::G_FABS);359    getInstrPartialMappingIdxs(360        MI, MRI, /* isFP= */ isFPTrunc || isFPAnyExt || isFAbs, OpRegBankIdx);361    break;362  }363  case TargetOpcode::G_LOAD: {364    // Check if that load feeds fp instructions.365    // In that case, we want the default mapping to be on FPR366    // instead of blind map every scalar to GPR.367    bool IsFP = any_of(MRI.use_nodbg_instructions(cast<GLoad>(MI).getDstReg()),368                       [&](const MachineInstr &UseMI) {369                         // If we have at least one direct use in a FP370                         // instruction, assume this was a floating point load371                         // in the IR. If it was not, we would have had a372                         // bitcast before reaching that instruction.373                         return onlyUsesFP(UseMI, MRI, TRI);374                       });375    getInstrPartialMappingIdxs(MI, MRI, IsFP, OpRegBankIdx);376    break;377  }378  case TargetOpcode::G_STORE: {379    // Check if that store is fed by fp instructions.380    Register VReg = cast<GStore>(MI).getValueReg();381    if (!VReg)382      break;383    MachineInstr *DefMI = MRI.getVRegDef(VReg);384    bool IsFP = onlyDefinesFP(*DefMI, MRI, TRI);385    getInstrPartialMappingIdxs(MI, MRI, IsFP, OpRegBankIdx);386    break;387  }388  default:389    // Track the bank of each register, use NotFP mapping (all scalars in390    // GPRs)391    getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ false, OpRegBankIdx);392    break;393  }394 395  // Finally construct the computed mapping.396  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);397  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))398    return getInvalidInstructionMapping();399 400  return getInstructionMapping(DefaultMappingID, /* Cost */ 1,401                               getOperandsMapping(OpdsMapping), NumOperands);402}403 404void X86RegisterBankInfo::applyMappingImpl(405    MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {406  return applyDefaultMapping(OpdMapper);407}408 409RegisterBankInfo::InstructionMappings410X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {411 412  const MachineFunction &MF = *MI.getParent()->getParent();413  const TargetSubtargetInfo &STI = MF.getSubtarget();414  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();415  const MachineRegisterInfo &MRI = MF.getRegInfo();416 417  switch (MI.getOpcode()) {418  case TargetOpcode::G_LOAD:419  case TargetOpcode::G_STORE:420  case TargetOpcode::G_IMPLICIT_DEF: {421    // we going to try to map 32/64/80 bit to PMI_FP32/PMI_FP64/PMI_FP80422    unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);423    if (Size != 32 && Size != 64 && Size != 80)424      break;425 426    unsigned NumOperands = MI.getNumOperands();427 428    // Track the bank of each register, use FP mapping (all scalars in VEC)429    SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);430    getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);431 432    // Finally construct the computed mapping.433    SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);434    if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))435      break;436 437    const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(438        /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);439    InstructionMappings AltMappings;440    AltMappings.push_back(&Mapping);441    return AltMappings;442  }443  default:444    break;445  }446  return RegisterBankInfo::getInstrAlternativeMappings(MI);447}448