LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMRegisterBankInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 78 84 92.9 %
Date: 2017-09-14 15:23:50 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : /// \file
      10             : /// This file implements the targeting of the RegisterBankInfo class for ARM.
      11             : /// \todo This should be generated by TableGen.
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "ARMRegisterBankInfo.h"
      15             : #include "ARMInstrInfo.h" // For the register classes
      16             : #include "ARMSubtarget.h"
      17             : #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
      18             : #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
      19             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      20             : #include "llvm/Target/TargetRegisterInfo.h"
      21             : 
      22             : #define GET_TARGET_REGBANK_IMPL
      23             : #include "ARMGenRegisterBank.inc"
      24             : 
      25             : using namespace llvm;
      26             : 
      27             : // FIXME: TableGen this.
      28             : // If it grows too much and TableGen still isn't ready to do the job, extract it
      29             : // into an ARMGenRegisterBankInfo.def (similar to AArch64).
      30             : namespace llvm {
      31             : namespace ARM {
      32             : enum PartialMappingIdx {
      33             :   PMI_GPR,
      34             :   PMI_SPR,
      35             :   PMI_DPR,
      36             :   PMI_Min = PMI_GPR,
      37             : };
      38             : 
      39             : RegisterBankInfo::PartialMapping PartMappings[]{
      40             :     // GPR Partial Mapping
      41             :     {0, 32, GPRRegBank},
      42             :     // SPR Partial Mapping
      43             :     {0, 32, FPRRegBank},
      44             :     // DPR Partial Mapping
      45             :     {0, 64, FPRRegBank},
      46      289224 : };
      47             : 
      48             : #ifndef NDEBUG
      49             : static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,
      50             :                              unsigned Start, unsigned Length,
      51             :                              unsigned RegBankID) {
      52             :   return PM.StartIdx == Start && PM.Length == Length &&
      53             :          PM.RegBank->getID() == RegBankID;
      54             : }
      55             : 
      56             : static void checkPartialMappings() {
      57             :   assert(
      58             :       checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
      59             :       "Wrong mapping for GPR");
      60             :   assert(
      61             :       checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
      62             :       "Wrong mapping for SPR");
      63             :   assert(
      64             :       checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
      65             :       "Wrong mapping for DPR");
      66             : }
      67             : #endif
      68             : 
      69             : enum ValueMappingIdx {
      70             :   InvalidIdx = 0,
      71             :   GPR3OpsIdx = 1,
      72             :   SPR3OpsIdx = 4,
      73             :   DPR3OpsIdx = 7,
      74             : };
      75             : 
      76             : RegisterBankInfo::ValueMapping ValueMappings[] = {
      77             :     // invalid
      78             :     {nullptr, 0},
      79             :     // 3 ops in GPRs
      80             :     {&PartMappings[PMI_GPR - PMI_Min], 1},
      81             :     {&PartMappings[PMI_GPR - PMI_Min], 1},
      82             :     {&PartMappings[PMI_GPR - PMI_Min], 1},
      83             :     // 3 ops in SPRs
      84             :     {&PartMappings[PMI_SPR - PMI_Min], 1},
      85             :     {&PartMappings[PMI_SPR - PMI_Min], 1},
      86             :     {&PartMappings[PMI_SPR - PMI_Min], 1},
      87             :     // 3 ops in DPRs
      88             :     {&PartMappings[PMI_DPR - PMI_Min], 1},
      89             :     {&PartMappings[PMI_DPR - PMI_Min], 1},
      90      795366 :     {&PartMappings[PMI_DPR - PMI_Min], 1}};
      91             : 
      92             : #ifndef NDEBUG
      93             : static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
      94             :                               RegisterBankInfo::PartialMapping *BreakDown) {
      95             :   return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
      96             : }
      97             : 
      98             : static 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             : #endif
     130             : } // end namespace arm
     131             : } // end namespace llvm
     132             : 
     133        4487 : ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
     134        4487 :     : ARMGenRegisterBankInfo() {
     135             :   static bool AlreadyInit = false;
     136             :   // We have only one set of register banks, whatever the subtarget
     137             :   // is. Therefore, the initialization of the RegBanks table should be
     138             :   // done only once. Indeed the table of all register banks
     139             :   // (ARM::RegBanks) is unique in the compiler. At some point, it
     140             :   // will get tablegen'ed and the whole constructor becomes empty.
     141        4487 :   if (AlreadyInit)
     142             :     return;
     143        2706 :   AlreadyInit = true;
     144             : 
     145        2706 :   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
     146             :   (void)RBGPR;
     147             :   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
     148             : 
     149             :   // Initialize the GPR bank.
     150             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
     151             :          "Subclass not added?");
     152             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
     153             :          "Subclass not added?");
     154             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
     155             :          "Subclass not added?");
     156             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
     157             :          "Subclass not added?");
     158             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
     159             :          "Subclass not added?");
     160             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
     161             :          "Subclass not added?");
     162             :   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
     163             :          "Subclass not added?");
     164             :   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
     165             : 
     166             : #ifndef NDEBUG
     167             :   ARM::checkPartialMappings();
     168             :   ARM::checkValueMappings();
     169             : #endif
     170             : }
     171             : 
     172        1904 : const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
     173             :     const TargetRegisterClass &RC) const {
     174             :   using namespace ARM;
     175             : 
     176        1904 :   switch (RC.getID()) {
     177        1749 :   case GPRRegClassID:
     178             :   case GPRnopcRegClassID:
     179             :   case GPRspRegClassID:
     180             :   case tGPR_and_tcGPRRegClassID:
     181             :   case tGPRRegClassID:
     182        3498 :     return getRegBank(ARM::GPRRegBankID);
     183         155 :   case SPR_8RegClassID:
     184             :   case SPRRegClassID:
     185             :   case DPR_8RegClassID:
     186             :   case DPRRegClassID:
     187         310 :     return getRegBank(ARM::FPRRegBankID);
     188           0 :   default:
     189           0 :     llvm_unreachable("Unsupported register kind");
     190             :   }
     191             : 
     192             :   llvm_unreachable("Switch should handle all register classes");
     193             : }
     194             : 
     195             : const RegisterBankInfo::InstructionMapping &
     196        1159 : ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     197        2318 :   auto Opc = MI.getOpcode();
     198             : 
     199             :   // Try the default logic for non-generic instructions that are either copies
     200             :   // or already have some operands assigned to banks.
     201        1159 :   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
     202         685 :     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
     203             :     if (Mapping.isValid())
     204             :       return Mapping;
     205             :   }
     206             : 
     207             :   using namespace TargetOpcode;
     208             : 
     209         474 :   const MachineFunction &MF = *MI.getParent()->getParent();
     210         474 :   const MachineRegisterInfo &MRI = MF.getRegInfo();
     211         474 :   unsigned NumOperands = MI.getNumOperands();
     212         474 :   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
     213             : 
     214         474 :   switch (Opc) {
     215             :   case G_ADD:
     216             :   case G_SUB:
     217             :   case G_MUL:
     218             :   case G_AND:
     219             :   case G_OR:
     220             :   case G_XOR:
     221             :   case G_SDIV:
     222             :   case G_UDIV:
     223             :   case G_SEXT:
     224             :   case G_ZEXT:
     225             :   case G_ANYEXT:
     226             :   case G_TRUNC:
     227             :   case G_GEP:
     228             :     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
     229             :     // the real world we would use different mappings.
     230             :     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
     231             :     break;
     232          80 :   case G_LOAD:
     233             :   case G_STORE: {
     234          80 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     235          80 :     OperandsMapping =
     236          80 :         Ty.getSizeInBits() == 64
     237          80 :             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
     238             :                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
     239             :             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
     240             :     break;
     241             :   }
     242           8 :   case G_FADD: {
     243           8 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     244             :     assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) &&
     245             :            "Unsupported size for G_FADD");
     246           8 :     OperandsMapping = Ty.getSizeInBits() == 64
     247             :                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
     248             :                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
     249             :     break;
     250             :   }
     251          70 :   case G_CONSTANT:
     252             :   case G_FRAME_INDEX:
     253             :   case G_GLOBAL_VALUE:
     254          70 :     OperandsMapping =
     255          70 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
     256          70 :     break;
     257           3 :   case G_SELECT: {
     258           3 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     259             :     (void)Ty;
     260           3 :     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
     261             :     (void)Ty2;
     262             :     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
     263             :     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
     264           3 :     OperandsMapping =
     265           3 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
     266             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
     267             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
     268             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
     269             :     break;
     270             :   }
     271           8 :   case G_ICMP: {
     272           8 :     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
     273             :     (void)Ty2;
     274             :     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
     275           8 :     OperandsMapping =
     276           8 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
     277             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
     278             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
     279             :     break;
     280             :   }
     281           4 :   case G_FCMP: {
     282           4 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     283             :     (void)Ty;
     284           4 :     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
     285           4 :     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
     286             :     (void)Ty2;
     287             :     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
     288             :     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
     289             :            "Mismatched operand sizes for G_FCMP");
     290             : 
     291           4 :     unsigned Size = Ty1.getSizeInBits();
     292             :     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
     293             : 
     294           4 :     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
     295             :                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
     296           4 :     OperandsMapping =
     297           8 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
     298             :                             FPRValueMapping, FPRValueMapping});
     299             :     break;
     300             :   }
     301           9 :   case G_MERGE_VALUES: {
     302             :     // We only support G_MERGE_VALUES for creating a double precision floating
     303             :     // point value out of two GPRs.
     304           9 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     305           9 :     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
     306           9 :     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
     307          18 :     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
     308           9 :         Ty2.getSizeInBits() != 32)
     309           0 :       return getInvalidInstructionMapping();
     310           9 :     OperandsMapping =
     311           9 :         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
     312             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
     313             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
     314           9 :     break;
     315             :   }
     316           5 :   case G_UNMERGE_VALUES: {
     317             :     // We only support G_UNMERGE_VALUES for splitting a double precision
     318             :     // floating point value into two GPRs.
     319           5 :     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     320           5 :     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
     321           5 :     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
     322          10 :     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
     323           5 :         Ty2.getSizeInBits() != 64)
     324           0 :       return getInvalidInstructionMapping();
     325           5 :     OperandsMapping =
     326           5 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
     327             :                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
     328             :                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
     329           5 :     break;
     330             :   }
     331           4 :   case G_BR:
     332           4 :     OperandsMapping = getOperandsMapping({nullptr});
     333           4 :     break;
     334           2 :   case G_BRCOND:
     335           2 :     OperandsMapping =
     336           2 :         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
     337           2 :     break;
     338           0 :   default:
     339           0 :     return getInvalidInstructionMapping();
     340             :   }
     341             : 
     342             : #ifndef NDEBUG
     343             :   for (unsigned i = 0; i < NumOperands; i++) {
     344             :     for (const auto &Mapping : OperandsMapping[i]) {
     345             :       assert(
     346             :           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
     347             :            MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
     348             :           "Trying to use floating point register bank on target without vfp");
     349             :     }
     350             :   }
     351             : #endif
     352             : 
     353             :   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
     354         948 :                                NumOperands);
     355      216918 : }

Generated by: LCOV version 1.13