brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.2 KiB · 0493fd9 Raw
457 lines · cpp
1//===- ARMRegisterBankInfo.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 ARM.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//12 13#include "ARMRegisterBankInfo.h"14#include "ARMInstrInfo.h" // For the register classes15#include "ARMSubtarget.h"16#include "llvm/CodeGen/MachineRegisterInfo.h"17#include "llvm/CodeGen/RegisterBank.h"18#include "llvm/CodeGen/RegisterBankInfo.h"19#include "llvm/CodeGen/TargetRegisterInfo.h"20 21#define GET_TARGET_REGBANK_IMPL22#include "ARMGenRegisterBank.inc"23 24using namespace llvm;25 26// FIXME: TableGen this.27// If it grows too much and TableGen still isn't ready to do the job, extract it28// into an ARMGenRegisterBankInfo.def (similar to AArch64).29namespace llvm {30namespace ARM {31enum PartialMappingIdx {32  PMI_GPR,33  PMI_SPR,34  PMI_DPR,35  PMI_Min = PMI_GPR,36};37 38const RegisterBankInfo::PartialMapping PartMappings[]{39    // GPR Partial Mapping40    {0, 32, GPRRegBank},41    // SPR Partial Mapping42    {0, 32, FPRRegBank},43    // DPR Partial Mapping44    {0, 64, FPRRegBank},45};46 47#ifndef NDEBUG48static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,49                             unsigned Start, unsigned Length,50                             unsigned RegBankID) {51  return PM.StartIdx == Start && PM.Length == Length &&52         PM.RegBank->getID() == RegBankID;53}54 55static void checkPartialMappings() {56  assert(57      checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&58      "Wrong mapping for GPR");59  assert(60      checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&61      "Wrong mapping for SPR");62  assert(63      checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&64      "Wrong mapping for DPR");65}66#endif67 68enum ValueMappingIdx {69  InvalidIdx = 0,70  GPR3OpsIdx = 1,71  SPR3OpsIdx = 4,72  DPR3OpsIdx = 7,73};74 75const RegisterBankInfo::ValueMapping ValueMappings[] = {76    // invalid77    {nullptr, 0},78    // 3 ops in GPRs79    {&PartMappings[PMI_GPR - PMI_Min], 1},80    {&PartMappings[PMI_GPR - PMI_Min], 1},81    {&PartMappings[PMI_GPR - PMI_Min], 1},82    // 3 ops in SPRs83    {&PartMappings[PMI_SPR - PMI_Min], 1},84    {&PartMappings[PMI_SPR - PMI_Min], 1},85    {&PartMappings[PMI_SPR - PMI_Min], 1},86    // 3 ops in DPRs87    {&PartMappings[PMI_DPR - PMI_Min], 1},88    {&PartMappings[PMI_DPR - PMI_Min], 1},89    {&PartMappings[PMI_DPR - PMI_Min], 1}};90 91#ifndef NDEBUG92static bool93checkValueMapping(const RegisterBankInfo::ValueMapping &VM,94                  const RegisterBankInfo::PartialMapping *BreakDown) {95  return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;96}97 98static void checkValueMappings() {99  assert(checkValueMapping(ValueMappings[GPR3OpsIdx],100                           &PartMappings[PMI_GPR - PMI_Min]) &&101         "Wrong value mapping for 3 GPR ops instruction");102  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],103                           &PartMappings[PMI_GPR - PMI_Min]) &&104         "Wrong value mapping for 3 GPR ops instruction");105  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],106                           &PartMappings[PMI_GPR - PMI_Min]) &&107         "Wrong value mapping for 3 GPR ops instruction");108 109  assert(checkValueMapping(ValueMappings[SPR3OpsIdx],110                           &PartMappings[PMI_SPR - PMI_Min]) &&111         "Wrong value mapping for 3 SPR ops instruction");112  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],113                           &PartMappings[PMI_SPR - PMI_Min]) &&114         "Wrong value mapping for 3 SPR ops instruction");115  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],116                           &PartMappings[PMI_SPR - PMI_Min]) &&117         "Wrong value mapping for 3 SPR ops instruction");118 119  assert(checkValueMapping(ValueMappings[DPR3OpsIdx],120                           &PartMappings[PMI_DPR - PMI_Min]) &&121         "Wrong value mapping for 3 DPR ops instruction");122  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],123                           &PartMappings[PMI_DPR - PMI_Min]) &&124         "Wrong value mapping for 3 DPR ops instruction");125  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],126                           &PartMappings[PMI_DPR - PMI_Min]) &&127         "Wrong value mapping for 3 DPR ops instruction");128}129#endif130} // end namespace arm131} // end namespace llvm132 133ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) {134  // We have only one set of register banks, whatever the subtarget135  // is. Therefore, the initialization of the RegBanks table should be136  // done only once. Indeed the table of all register banks137  // (ARM::RegBanks) is unique in the compiler. At some point, it138  // will get tablegen'ed and the whole constructor becomes empty.139  static llvm::once_flag InitializeRegisterBankFlag;140 141  static auto InitializeRegisterBankOnce = [&]() {142    const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);143    (void)RBGPR;144    assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");145 146    // Initialize the GPR bank.147    assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&148           "Subclass not added?");149    assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&150           "Subclass not added?");151    assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&152           "Subclass not added?");153    assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&154           "Subclass not added?");155    assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&156           "Subclass not added?");157    assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&158           "Subclass not added?");159    assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&160           "Subclass not added?");161    assert(getMaximumSize(RBGPR.getID()) == 32 &&162           "GPRs should hold up to 32-bit");163 164#ifndef NDEBUG165    ARM::checkPartialMappings();166    ARM::checkValueMappings();167#endif168  };169 170  llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);171}172 173const RegisterBankInfo::InstructionMapping &174ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {175  auto Opc = MI.getOpcode();176 177  // Try the default logic for non-generic instructions that are either copies178  // or already have some operands assigned to banks.179  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {180    const InstructionMapping &Mapping = getInstrMappingImpl(MI);181    if (Mapping.isValid())182      return Mapping;183  }184 185  using namespace TargetOpcode;186 187  const MachineFunction &MF = *MI.getParent()->getParent();188  const MachineRegisterInfo &MRI = MF.getRegInfo();189  unsigned NumOperands = MI.getNumOperands();190  const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];191 192  switch (Opc) {193  case G_ADD:194  case G_SUB: {195    // Integer operations where the source and destination are in the196    // same register class.197    LLT Ty = MRI.getType(MI.getOperand(0).getReg());198    OperandsMapping = Ty.getSizeInBits() == 64199                          ? &ARM::ValueMappings[ARM::DPR3OpsIdx]200                          : &ARM::ValueMappings[ARM::GPR3OpsIdx];201    break;202  }203  case G_MUL:204  case G_AND:205  case G_OR:206  case G_XOR:207  case G_LSHR:208  case G_ASHR:209  case G_SHL:210  case G_SDIV:211  case G_UDIV:212  case G_SEXT:213  case G_ZEXT:214  case G_ANYEXT:215  case G_PTR_ADD:216  case G_INTTOPTR:217  case G_PTRTOINT:218  case G_CTLZ:219    // FIXME: We're abusing the fact that everything lives in a GPR for now; in220    // the real world we would use different mappings.221    OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];222    break;223  case G_TRUNC: {224    // In some cases we may end up with a G_TRUNC from a 64-bit value to a225    // 32-bit value. This isn't a real floating point trunc (that would be a226    // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear227    // because the legalizer doesn't distinguish between integer and floating228    // point values so it may leave some 64-bit integers un-narrowed. Until we229    // have a more principled solution that doesn't let such things sneak all230    // the way to this point, just map the source to a DPR and the destination231    // to a GPR.232    LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());233    OperandsMapping =234        LargeTy.getSizeInBits() <= 32235            ? &ARM::ValueMappings[ARM::GPR3OpsIdx]236            : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],237                                  &ARM::ValueMappings[ARM::DPR3OpsIdx]});238    break;239  }240  case G_LOAD:241  case G_STORE: {242    LLT Ty = MRI.getType(MI.getOperand(0).getReg());243    OperandsMapping =244        Ty.getSizeInBits() == 64245            ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],246                                  &ARM::ValueMappings[ARM::GPR3OpsIdx]})247            : &ARM::ValueMappings[ARM::GPR3OpsIdx];248    break;249  }250  case G_FADD:251  case G_FSUB:252  case G_FMUL:253  case G_FDIV:254  case G_FNEG: {255    LLT Ty = MRI.getType(MI.getOperand(0).getReg());256    OperandsMapping =Ty.getSizeInBits() == 64257                          ? &ARM::ValueMappings[ARM::DPR3OpsIdx]258                          : &ARM::ValueMappings[ARM::SPR3OpsIdx];259    break;260  }261  case G_FMA: {262    LLT Ty = MRI.getType(MI.getOperand(0).getReg());263    OperandsMapping =264        Ty.getSizeInBits() == 64265            ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],266                                  &ARM::ValueMappings[ARM::DPR3OpsIdx],267                                  &ARM::ValueMappings[ARM::DPR3OpsIdx],268                                  &ARM::ValueMappings[ARM::DPR3OpsIdx]})269            : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],270                                  &ARM::ValueMappings[ARM::SPR3OpsIdx],271                                  &ARM::ValueMappings[ARM::SPR3OpsIdx],272                                  &ARM::ValueMappings[ARM::SPR3OpsIdx]});273    break;274  }275  case G_FPEXT: {276    LLT ToTy = MRI.getType(MI.getOperand(0).getReg());277    LLT FromTy = MRI.getType(MI.getOperand(1).getReg());278    if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)279      OperandsMapping =280          getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],281                              &ARM::ValueMappings[ARM::SPR3OpsIdx]});282    break;283  }284  case G_FPTRUNC: {285    LLT ToTy = MRI.getType(MI.getOperand(0).getReg());286    LLT FromTy = MRI.getType(MI.getOperand(1).getReg());287    if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)288      OperandsMapping =289          getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],290                              &ARM::ValueMappings[ARM::DPR3OpsIdx]});291    break;292  }293  case G_FPTOSI:294  case G_FPTOUI: {295    LLT ToTy = MRI.getType(MI.getOperand(0).getReg());296    LLT FromTy = MRI.getType(MI.getOperand(1).getReg());297    if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&298        ToTy.getSizeInBits() == 32)299      OperandsMapping =300          FromTy.getSizeInBits() == 64301              ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],302                                    &ARM::ValueMappings[ARM::DPR3OpsIdx]})303              : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],304                                    &ARM::ValueMappings[ARM::SPR3OpsIdx]});305    break;306  }307  case G_SITOFP:308  case G_UITOFP: {309    LLT ToTy = MRI.getType(MI.getOperand(0).getReg());310    LLT FromTy = MRI.getType(MI.getOperand(1).getReg());311    if (FromTy.getSizeInBits() == 32 &&312        (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))313      OperandsMapping =314          ToTy.getSizeInBits() == 64315              ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],316                                    &ARM::ValueMappings[ARM::GPR3OpsIdx]})317              : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],318                                    &ARM::ValueMappings[ARM::GPR3OpsIdx]});319    break;320  }321  case G_FCONSTANT: {322    LLT Ty = MRI.getType(MI.getOperand(0).getReg());323    OperandsMapping = getOperandsMapping(324        {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]325                                  : &ARM::ValueMappings[ARM::SPR3OpsIdx],326         nullptr});327    break;328  }329  case G_CONSTANT:330  case G_FRAME_INDEX:331  case G_GLOBAL_VALUE:332  case G_CONSTANT_POOL:333    OperandsMapping =334        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});335    break;336  case G_SELECT: {337    LLT Ty = MRI.getType(MI.getOperand(0).getReg());338    (void)Ty;339    LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());340    (void)Ty2;341    assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");342    assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");343    OperandsMapping =344        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],345                            &ARM::ValueMappings[ARM::GPR3OpsIdx],346                            &ARM::ValueMappings[ARM::GPR3OpsIdx],347                            &ARM::ValueMappings[ARM::GPR3OpsIdx]});348    break;349  }350  case G_ICMP: {351    LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());352    (void)Ty2;353    assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");354    OperandsMapping =355        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,356                            &ARM::ValueMappings[ARM::GPR3OpsIdx],357                            &ARM::ValueMappings[ARM::GPR3OpsIdx]});358    break;359  }360  case G_FCMP: {361    LLT Ty = MRI.getType(MI.getOperand(0).getReg());362    (void)Ty;363    LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());364    LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());365    (void)Ty2;366    assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");367    assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&368           "Mismatched operand sizes for G_FCMP");369 370    unsigned Size = Ty1.getSizeInBits();371    assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");372 373    auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]374                                      : &ARM::ValueMappings[ARM::DPR3OpsIdx];375    OperandsMapping =376        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,377                            FPRValueMapping, FPRValueMapping});378    break;379  }380  case G_MERGE_VALUES: {381    // We only support G_MERGE_VALUES for creating a double precision floating382    // point value out of two GPRs.383    LLT Ty = MRI.getType(MI.getOperand(0).getReg());384    LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());385    LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());386    if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||387        Ty2.getSizeInBits() != 32)388      return getInvalidInstructionMapping();389    OperandsMapping =390        getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],391                            &ARM::ValueMappings[ARM::GPR3OpsIdx],392                            &ARM::ValueMappings[ARM::GPR3OpsIdx]});393    break;394  }395  case G_UNMERGE_VALUES: {396    // We only support G_UNMERGE_VALUES for splitting a double precision397    // floating point value into two GPRs.398    LLT Ty = MRI.getType(MI.getOperand(0).getReg());399    LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());400    LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());401    if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||402        Ty2.getSizeInBits() != 64)403      return getInvalidInstructionMapping();404    OperandsMapping =405        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],406                            &ARM::ValueMappings[ARM::GPR3OpsIdx],407                            &ARM::ValueMappings[ARM::DPR3OpsIdx]});408    break;409  }410  case G_BR:411    OperandsMapping = getOperandsMapping({nullptr});412    break;413  case G_BRCOND:414    OperandsMapping =415        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});416    break;417  case DBG_VALUE: {418    SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);419    const MachineOperand &MaybeReg = MI.getOperand(0);420    if (MaybeReg.isReg() && MaybeReg.getReg()) {421      unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();422      if (Size > 32 && Size != 64)423        return getInvalidInstructionMapping();424      OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]425                                   : &ARM::ValueMappings[ARM::GPR3OpsIdx];426    }427    OperandsMapping = getOperandsMapping(OperandBanks);428    break;429  }430  case G_GET_FPENV:431  case G_SET_FPENV:432  case G_GET_FPMODE:433    OperandsMapping =434        getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});435    break;436  case G_RESET_FPENV:437    OperandsMapping = getOperandsMapping({nullptr});438    break;439  default:440    return getInvalidInstructionMapping();441  }442 443#ifndef NDEBUG444  for (unsigned i = 0; i < NumOperands; i++) {445    for (const auto &Mapping : OperandsMapping[i]) {446      assert(447          (Mapping.RegBank->getID() != ARM::FPRRegBankID ||448           MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&449          "Trying to use floating point register bank on target without vfp");450    }451  }452#endif453 454  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,455                               NumOperands);456}457