LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64RegisterBankInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 145 158 91.8 %
Date: 2017-09-14 15:23:50 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
       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
      11             : /// AArch64.
      12             : /// \todo This should be generated by TableGen.
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "AArch64RegisterBankInfo.h"
      16             : #include "AArch64InstrInfo.h"
      17             : #include "llvm/ADT/SmallVector.h"
      18             : #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
      19             : #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
      20             : #include "llvm/CodeGen/LowLevelType.h"
      21             : #include "llvm/CodeGen/MachineFunction.h"
      22             : #include "llvm/CodeGen/MachineInstr.h"
      23             : #include "llvm/CodeGen/MachineOperand.h"
      24             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      25             : #include "llvm/Support/ErrorHandling.h"
      26             : #include "llvm/Target/TargetOpcodes.h"
      27             : #include "llvm/Target/TargetRegisterInfo.h"
      28             : #include "llvm/Target/TargetSubtargetInfo.h"
      29             : #include <algorithm>
      30             : #include <cassert>
      31             : 
      32             : #define GET_TARGET_REGBANK_IMPL
      33             : #include "AArch64GenRegisterBank.inc"
      34             : 
      35             : // This file will be TableGen'ed at some point.
      36             : #include "AArch64GenRegisterBankInfo.def"
      37             : 
      38             : using namespace llvm;
      39             : 
      40        1214 : AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
      41        1214 :     : AArch64GenRegisterBankInfo() {
      42             :   static bool AlreadyInit = false;
      43             :   // We have only one set of register banks, whatever the subtarget
      44             :   // is. Therefore, the initialization of the RegBanks table should be
      45             :   // done only once. Indeed the table of all register banks
      46             :   // (AArch64::RegBanks) is unique in the compiler. At some point, it
      47             :   // will get tablegen'ed and the whole constructor becomes empty.
      48        1214 :   if (AlreadyInit)
      49             :     return;
      50        1204 :   AlreadyInit = true;
      51             : 
      52        1204 :   const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
      53             :   (void)RBGPR;
      54             :   assert(&AArch64::GPRRegBank == &RBGPR &&
      55             :          "The order in RegBanks is messed up");
      56             : 
      57        1204 :   const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
      58             :   (void)RBFPR;
      59             :   assert(&AArch64::FPRRegBank == &RBFPR &&
      60             :          "The order in RegBanks is messed up");
      61             : 
      62        1204 :   const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID);
      63             :   (void)RBCCR;
      64             :   assert(&AArch64::CCRRegBank == &RBCCR &&
      65             :          "The order in RegBanks is messed up");
      66             : 
      67             :   // The GPR register bank is fully defined by all the registers in
      68             :   // GR64all + its subclasses.
      69             :   assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
      70             :          "Subclass not added?");
      71             :   assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
      72             : 
      73             :   // The FPR register bank is fully defined by all the registers in
      74             :   // GR64all + its subclasses.
      75             :   assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
      76             :          "Subclass not added?");
      77             :   assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
      78             :          "Subclass not added?");
      79             :   assert(RBFPR.getSize() == 512 &&
      80             :          "FPRs should hold up to 512-bit via QQQQ sequence");
      81             : 
      82             :   assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
      83             :          "Class not added?");
      84             :   assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit");
      85             : 
      86             :   // Check that the TableGen'ed like file is in sync we our expectations.
      87             :   // First, the Idx.
      88             :   assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR,
      89             :                                 {PMI_GPR32, PMI_GPR64}) &&
      90             :          "PartialMappingIdx's are incorrectly ordered");
      91             :   assert(checkPartialMappingIdx(
      92             :              PMI_FirstFPR, PMI_LastFPR,
      93             :              {PMI_FPR32, PMI_FPR64, PMI_FPR128, PMI_FPR256, PMI_FPR512}) &&
      94             :          "PartialMappingIdx's are incorrectly ordered");
      95             : // Now, the content.
      96             : // Check partial mapping.
      97             : #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)                      \
      98             :   do {                                                                         \
      99             :     assert(                                                                    \
     100             :         checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
     101             :         #Idx " is incorrectly initialized");                                   \
     102             :   } while (false)
     103             : 
     104             :   CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
     105             :   CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
     106             :   CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
     107             :   CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
     108             :   CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
     109             :   CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
     110             :   CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
     111             : 
     112             : // Check value mapping.
     113             : #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset)                              \
     114             :   do {                                                                         \
     115             :     assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size,            \
     116             :                              PartialMappingIdx::PMI_First##RBName, Size,       \
     117             :                              Offset) &&                                        \
     118             :            #RBName #Size " " #Offset " is incorrectly initialized");           \
     119             :   } while (false)
     120             : 
     121             : #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
     122             : 
     123             :   CHECK_VALUEMAP(GPR, 32);
     124             :   CHECK_VALUEMAP(GPR, 64);
     125             :   CHECK_VALUEMAP(FPR, 32);
     126             :   CHECK_VALUEMAP(FPR, 64);
     127             :   CHECK_VALUEMAP(FPR, 128);
     128             :   CHECK_VALUEMAP(FPR, 256);
     129             :   CHECK_VALUEMAP(FPR, 512);
     130             : 
     131             : // Check the value mapping for 3-operands instructions where all the operands
     132             : // map to the same value mapping.
     133             : #define CHECK_VALUEMAP_3OPS(RBName, Size)                                      \
     134             :   do {                                                                         \
     135             :     CHECK_VALUEMAP_IMPL(RBName, Size, 0);                                      \
     136             :     CHECK_VALUEMAP_IMPL(RBName, Size, 1);                                      \
     137             :     CHECK_VALUEMAP_IMPL(RBName, Size, 2);                                      \
     138             :   } while (false)
     139             : 
     140             :   CHECK_VALUEMAP_3OPS(GPR, 32);
     141             :   CHECK_VALUEMAP_3OPS(GPR, 64);
     142             :   CHECK_VALUEMAP_3OPS(FPR, 32);
     143             :   CHECK_VALUEMAP_3OPS(FPR, 64);
     144             :   CHECK_VALUEMAP_3OPS(FPR, 128);
     145             :   CHECK_VALUEMAP_3OPS(FPR, 256);
     146             :   CHECK_VALUEMAP_3OPS(FPR, 512);
     147             : 
     148             : #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)                 \
     149             :   do {                                                                         \
     150             :     unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min;               \
     151             :     unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min;               \
     152             :     (void)PartialMapDstIdx;                                                    \
     153             :     (void)PartialMapSrcIdx;                                                    \
     154             :     const ValueMapping *Map = getCopyMapping(                                  \
     155             :         AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size);  \
     156             :     (void)Map;                                                                 \
     157             :     assert(Map[0].BreakDown ==                                                 \
     158             :                &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] &&  \
     159             :            Map[0].NumBreakDowns == 1 && #RBNameDst #Size                       \
     160             :            " Dst is incorrectly initialized");                                 \
     161             :     assert(Map[1].BreakDown ==                                                 \
     162             :                &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] &&  \
     163             :            Map[1].NumBreakDowns == 1 && #RBNameSrc #Size                       \
     164             :            " Src is incorrectly initialized");                                 \
     165             :                                                                                \
     166             :   } while (false)
     167             : 
     168        1204 :   CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
     169        1204 :   CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32);
     170        1204 :   CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
     171        1204 :   CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64);
     172        1204 :   CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32);
     173        1204 :   CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32);
     174        1204 :   CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
     175        1204 :   CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
     176             : 
     177             :   assert(verify(TRI) && "Invalid register bank information");
     178             : }
     179             : 
     180          66 : unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A,
     181             :                                            const RegisterBank &B,
     182             :                                            unsigned Size) const {
     183             :   // What do we do with different size?
     184             :   // copy are same size.
     185             :   // Will introduce other hooks for different size:
     186             :   // * extract cost.
     187             :   // * build_sequence cost.
     188             : 
     189             :   // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
     190             :   // FIXME: This should be deduced from the scheduling model.
     191          66 :   if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
     192             :     // FMOVXDr or FMOVWSr.
     193             :     return 5;
     194          34 :   if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
     195             :     // FMOVDXr or FMOVSWr.
     196             :     return 4;
     197             : 
     198          16 :   return RegisterBankInfo::copyCost(A, B, Size);
     199             : }
     200             : 
     201         766 : const RegisterBank &AArch64RegisterBankInfo::getRegBankFromRegClass(
     202             :     const TargetRegisterClass &RC) const {
     203         766 :   switch (RC.getID()) {
     204         249 :   case AArch64::FPR8RegClassID:
     205             :   case AArch64::FPR16RegClassID:
     206             :   case AArch64::FPR32RegClassID:
     207             :   case AArch64::FPR64RegClassID:
     208             :   case AArch64::FPR128RegClassID:
     209             :   case AArch64::FPR128_loRegClassID:
     210             :   case AArch64::DDRegClassID:
     211             :   case AArch64::DDDRegClassID:
     212             :   case AArch64::DDDDRegClassID:
     213             :   case AArch64::QQRegClassID:
     214             :   case AArch64::QQQRegClassID:
     215             :   case AArch64::QQQQRegClassID:
     216         498 :     return getRegBank(AArch64::FPRRegBankID);
     217         517 :   case AArch64::GPR32commonRegClassID:
     218             :   case AArch64::GPR32RegClassID:
     219             :   case AArch64::GPR32spRegClassID:
     220             :   case AArch64::GPR32sponlyRegClassID:
     221             :   case AArch64::GPR32allRegClassID:
     222             :   case AArch64::GPR64commonRegClassID:
     223             :   case AArch64::GPR64RegClassID:
     224             :   case AArch64::GPR64spRegClassID:
     225             :   case AArch64::GPR64sponlyRegClassID:
     226             :   case AArch64::GPR64allRegClassID:
     227             :   case AArch64::tcGPR64RegClassID:
     228             :   case AArch64::WSeqPairsClassRegClassID:
     229             :   case AArch64::XSeqPairsClassRegClassID:
     230        1034 :     return getRegBank(AArch64::GPRRegBankID);
     231           0 :   case AArch64::CCRRegClassID:
     232           0 :     return getRegBank(AArch64::CCRRegBankID);
     233           0 :   default:
     234           0 :     llvm_unreachable("Register class not supported");
     235             :   }
     236             : }
     237             : 
     238             : RegisterBankInfo::InstructionMappings
     239          63 : AArch64RegisterBankInfo::getInstrAlternativeMappings(
     240             :     const MachineInstr &MI) const {
     241          63 :   const MachineFunction &MF = *MI.getParent()->getParent();
     242          63 :   const TargetSubtargetInfo &STI = MF.getSubtarget();
     243          63 :   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
     244          63 :   const MachineRegisterInfo &MRI = MF.getRegInfo();
     245             : 
     246         126 :   switch (MI.getOpcode()) {
     247           3 :   case TargetOpcode::G_OR: {
     248             :     // 32 and 64-bit or can be mapped on either FPR or
     249             :     // GPR for the same cost.
     250           3 :     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
     251           3 :     if (Size != 32 && Size != 64)
     252             :       break;
     253             : 
     254             :     // If the instruction has any implicit-defs or uses,
     255             :     // do not mess with it.
     256           3 :     if (MI.getNumOperands() != 3)
     257             :       break;
     258           6 :     InstructionMappings AltMappings;
     259             :     const InstructionMapping &GPRMapping = getInstructionMapping(
     260             :         /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
     261           6 :         /*NumOperands*/ 3);
     262             :     const InstructionMapping &FPRMapping = getInstructionMapping(
     263             :         /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
     264           6 :         /*NumOperands*/ 3);
     265             : 
     266           3 :     AltMappings.push_back(&GPRMapping);
     267           3 :     AltMappings.push_back(&FPRMapping);
     268           3 :     return AltMappings;
     269             :   }
     270          10 :   case TargetOpcode::G_BITCAST: {
     271          10 :     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
     272          10 :     if (Size != 32 && Size != 64)
     273             :       break;
     274             : 
     275             :     // If the instruction has any implicit-defs or uses,
     276             :     // do not mess with it.
     277          10 :     if (MI.getNumOperands() != 2)
     278             :       break;
     279             : 
     280          20 :     InstructionMappings AltMappings;
     281             :     const InstructionMapping &GPRMapping = getInstructionMapping(
     282             :         /*ID*/ 1, /*Cost*/ 1,
     283             :         getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
     284          20 :         /*NumOperands*/ 2);
     285             :     const InstructionMapping &FPRMapping = getInstructionMapping(
     286             :         /*ID*/ 2, /*Cost*/ 1,
     287             :         getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
     288          20 :         /*NumOperands*/ 2);
     289             :     const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
     290             :         /*ID*/ 3,
     291             :         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
     292             :         getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
     293          20 :         /*NumOperands*/ 2);
     294             :     const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
     295             :         /*ID*/ 3,
     296             :         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
     297             :         getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
     298          20 :         /*NumOperands*/ 2);
     299             : 
     300          10 :     AltMappings.push_back(&GPRMapping);
     301          10 :     AltMappings.push_back(&FPRMapping);
     302          10 :     AltMappings.push_back(&GPRToFPRMapping);
     303          10 :     AltMappings.push_back(&FPRToGPRMapping);
     304          10 :     return AltMappings;
     305             :   }
     306           2 :   case TargetOpcode::G_LOAD: {
     307           2 :     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
     308           2 :     if (Size != 64)
     309             :       break;
     310             : 
     311             :     // If the instruction has any implicit-defs or uses,
     312             :     // do not mess with it.
     313           2 :     if (MI.getNumOperands() != 2)
     314             :       break;
     315             : 
     316           4 :     InstructionMappings AltMappings;
     317             :     const InstructionMapping &GPRMapping = getInstructionMapping(
     318             :         /*ID*/ 1, /*Cost*/ 1,
     319           2 :         getOperandsMapping({getValueMapping(PMI_FirstGPR, Size),
     320             :                             // Addresses are GPR 64-bit.
     321           2 :                             getValueMapping(PMI_FirstGPR, 64)}),
     322           8 :         /*NumOperands*/ 2);
     323             :     const InstructionMapping &FPRMapping = getInstructionMapping(
     324             :         /*ID*/ 2, /*Cost*/ 1,
     325           2 :         getOperandsMapping({getValueMapping(PMI_FirstFPR, Size),
     326             :                             // Addresses are GPR 64-bit.
     327           2 :                             getValueMapping(PMI_FirstGPR, 64)}),
     328           6 :         /*NumOperands*/ 2);
     329             : 
     330           2 :     AltMappings.push_back(&GPRMapping);
     331           2 :     AltMappings.push_back(&FPRMapping);
     332           2 :     return AltMappings;
     333             :   }
     334             :   default:
     335             :     break;
     336             :   }
     337          48 :   return RegisterBankInfo::getInstrAlternativeMappings(MI);
     338             : }
     339             : 
     340          10 : void AArch64RegisterBankInfo::applyMappingImpl(
     341             :     const OperandsMapper &OpdMapper) const {
     342          10 :   switch (OpdMapper.getMI().getOpcode()) {
     343          10 :   case TargetOpcode::G_OR:
     344             :   case TargetOpcode::G_BITCAST:
     345             :   case TargetOpcode::G_LOAD:
     346             :     // Those ID must match getInstrAlternativeMappings.
     347             :     assert((OpdMapper.getInstrMapping().getID() >= 1 &&
     348             :             OpdMapper.getInstrMapping().getID() <= 4) &&
     349             :            "Don't know how to handle that ID");
     350          10 :     return applyDefaultMapping(OpdMapper);
     351           0 :   default:
     352           0 :     llvm_unreachable("Don't know how to handle that operation");
     353             :   }
     354             : }
     355             : 
     356             : /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
     357             : /// having only floating-point operands.
     358             : static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
     359             :   switch (Opc) {
     360             :   case TargetOpcode::G_FADD:
     361             :   case TargetOpcode::G_FSUB:
     362             :   case TargetOpcode::G_FMUL:
     363             :   case TargetOpcode::G_FDIV:
     364             :   case TargetOpcode::G_FCONSTANT:
     365             :   case TargetOpcode::G_FPEXT:
     366             :   case TargetOpcode::G_FPTRUNC:
     367             :     return true;
     368             :   }
     369             :   return false;
     370             : }
     371             : 
     372             : const RegisterBankInfo::InstructionMapping &
     373          48 : AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
     374             :     const MachineInstr &MI) const {
     375          96 :   const unsigned Opc = MI.getOpcode();
     376          48 :   const MachineFunction &MF = *MI.getParent()->getParent();
     377          48 :   const MachineRegisterInfo &MRI = MF.getRegInfo();
     378             : 
     379          48 :   unsigned NumOperands = MI.getNumOperands();
     380             :   assert(NumOperands <= 3 &&
     381             :          "This code is for instructions with 3 or less operands");
     382             : 
     383          48 :   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
     384          48 :   unsigned Size = Ty.getSizeInBits();
     385          33 :   bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
     386             : 
     387          48 :   PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
     388             : 
     389             : #ifndef NDEBUG
     390             :   // Make sure all the operands are using similar size and type.
     391             :   // Should probably be checked by the machine verifier.
     392             :   // This code won't catch cases where the number of lanes is
     393             :   // different between the operands.
     394             :   // If we want to go to that level of details, it is probably
     395             :   // best to check that the types are the same, period.
     396             :   // Currently, we just check that the register banks are the same
     397             :   // for each types.
     398             :   for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
     399             :     LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
     400             :     assert(
     401             :         AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
     402             :             RBIdx, OpTy.getSizeInBits()) ==
     403             :             AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
     404             :         "Operand has incompatible size");
     405             :     bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
     406             :     (void)OpIsFPR;
     407             :     assert(IsFPR == OpIsFPR && "Operand has incompatible type");
     408             :   }
     409             : #endif // End NDEBUG.
     410             : 
     411             :   return getInstructionMapping(DefaultMappingID, 1,
     412          96 :                                getValueMapping(RBIdx, Size), NumOperands);
     413             : }
     414             : 
     415             : const RegisterBankInfo::InstructionMapping &
     416         266 : AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     417         532 :   const unsigned Opc = MI.getOpcode();
     418         266 :   const MachineFunction &MF = *MI.getParent()->getParent();
     419         266 :   const MachineRegisterInfo &MRI = MF.getRegInfo();
     420             : 
     421             :   // Try the default logic for non-generic instructions that are either copies
     422             :   // or already have some operands assigned to banks.
     423         266 :   if (!isPreISelGenericOpcode(Opc) ||
     424             :       Opc == TargetOpcode::G_PHI) {
     425             :     const RegisterBankInfo::InstructionMapping &Mapping =
     426         144 :         getInstrMappingImpl(MI);
     427             :     if (Mapping.isValid())
     428             :       return Mapping;
     429             :   }
     430             : 
     431         123 :   switch (Opc) {
     432             :     // G_{F|S|U}REM are not listed because they are not legal.
     433             :     // Arithmetic ops.
     434          48 :   case TargetOpcode::G_ADD:
     435             :   case TargetOpcode::G_SUB:
     436             :   case TargetOpcode::G_GEP:
     437             :   case TargetOpcode::G_MUL:
     438             :   case TargetOpcode::G_SDIV:
     439             :   case TargetOpcode::G_UDIV:
     440             :     // Bitwise ops.
     441             :   case TargetOpcode::G_AND:
     442             :   case TargetOpcode::G_OR:
     443             :   case TargetOpcode::G_XOR:
     444             :     // Shifts.
     445             :   case TargetOpcode::G_SHL:
     446             :   case TargetOpcode::G_LSHR:
     447             :   case TargetOpcode::G_ASHR:
     448             :     // Floating point ops.
     449             :   case TargetOpcode::G_FADD:
     450             :   case TargetOpcode::G_FSUB:
     451             :   case TargetOpcode::G_FMUL:
     452             :   case TargetOpcode::G_FDIV:
     453          48 :     return getSameKindOfOperandsMapping(MI);
     454          20 :   case TargetOpcode::G_BITCAST: {
     455          20 :     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
     456          20 :     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
     457          20 :     unsigned Size = DstTy.getSizeInBits();
     458          20 :     bool DstIsGPR = !DstTy.isVector();
     459          20 :     bool SrcIsGPR = !SrcTy.isVector();
     460          20 :     const RegisterBank &DstRB =
     461             :         DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
     462          20 :     const RegisterBank &SrcRB =
     463             :         SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
     464             :     return getInstructionMapping(
     465             :         DefaultMappingID, copyCost(DstRB, SrcRB, Size),
     466             :         getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
     467          40 :         /*NumOperands*/ 2);
     468             :   }
     469             :   default:
     470             :     break;
     471             :   }
     472             : 
     473          55 :   unsigned NumOperands = MI.getNumOperands();
     474             : 
     475             :   // Track the size and bank of each register.  We don't do partial mappings.
     476         165 :   SmallVector<unsigned, 4> OpSize(NumOperands);
     477         165 :   SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
     478         167 :   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
     479         224 :     auto &MO = MI.getOperand(Idx);
     480         135 :     if (!MO.isReg() || !MO.getReg())
     481          23 :       continue;
     482             : 
     483          89 :     LLT Ty = MRI.getType(MO.getReg());
     484         178 :     OpSize[Idx] = Ty.getSizeInBits();
     485             : 
     486             :     // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
     487             :     // For floating-point instructions, scalars go in FPRs.
     488         169 :     if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc) ||
     489          82 :         Ty.getSizeInBits() > 64)
     490          16 :       OpRegBankIdx[Idx] = PMI_FirstFPR;
     491             :     else
     492         162 :       OpRegBankIdx[Idx] = PMI_FirstGPR;
     493             :   }
     494             : 
     495          55 :   unsigned Cost = 1;
     496             :   // Some of the floating-point instructions have mixed GPR and FPR operands:
     497             :   // fine-tune the computed mapping.
     498          55 :   switch (Opc) {
     499           2 :   case TargetOpcode::G_SITOFP:
     500             :   case TargetOpcode::G_UITOFP:
     501           2 :     OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
     502             :     break;
     503           2 :   case TargetOpcode::G_FPTOSI:
     504             :   case TargetOpcode::G_FPTOUI:
     505           2 :     OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
     506             :     break;
     507           1 :   case TargetOpcode::G_FCMP:
     508           1 :     OpRegBankIdx = {PMI_FirstGPR,
     509             :                     /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
     510             :     break;
     511           0 :   case TargetOpcode::G_BITCAST:
     512             :     // This is going to be a cross register bank copy and this is expensive.
     513           0 :     if (OpRegBankIdx[0] != OpRegBankIdx[1])
     514           0 :       Cost = copyCost(
     515           0 :           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
     516           0 :           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
     517           0 :           OpSize[0]);
     518             :     break;
     519           8 :   case TargetOpcode::G_LOAD:
     520             :     // Loading in vector unit is slightly more expensive.
     521             :     // This is actually only true for the LD1R and co instructions,
     522             :     // but anyway for the fast mode this number does not matter and
     523             :     // for the greedy mode the cost of the cross bank copy will
     524             :     // offset this number.
     525             :     // FIXME: Should be derived from the scheduling model.
     526           8 :     if (OpRegBankIdx[0] != PMI_FirstGPR)
     527             :       Cost = 2;
     528             :     else
     529             :       // Check if that load feeds fp instructions.
     530             :       // In that case, we want the default mapping to be on FPR
     531             :       // instead of blind map every scalar to GPR.
     532             :       for (const MachineInstr &UseMI :
     533          24 :            MRI.use_instructions(MI.getOperand(0).getReg()))
     534             :         // If we have at least one direct use in a FP instruction,
     535             :         // assume this was a floating point load in the IR.
     536             :         // If it was not, we would have had a bitcast before
     537             :         // reaching that instruction.
     538           4 :         if (isPreISelGenericFloatingPointOpcode(UseMI.getOpcode())) {
     539           2 :           OpRegBankIdx[0] = PMI_FirstFPR;
     540           2 :           break;
     541             :         }
     542             :     break;
     543           9 :   case TargetOpcode::G_STORE:
     544             :     // Check if that store is fed by fp instructions.
     545           9 :     if (OpRegBankIdx[0] == PMI_FirstGPR) {
     546           9 :       unsigned VReg = MI.getOperand(0).getReg();
     547           9 :       if (!VReg)
     548             :         break;
     549           9 :       MachineInstr *DefMI = MRI.getVRegDef(VReg);
     550          18 :       if (isPreISelGenericFloatingPointOpcode(DefMI->getOpcode()))
     551           2 :         OpRegBankIdx[0] = PMI_FirstFPR;
     552             :       break;
     553          55 :     }
     554             :   }
     555             : 
     556             :   // Finally construct the computed mapping.
     557         165 :   SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
     558         167 :   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
     559         336 :     if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
     560         267 :       auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
     561          89 :       if (!Mapping->isValid())
     562           0 :         return getInvalidInstructionMapping();
     563             : 
     564         178 :       OpdsMapping[Idx] = Mapping;
     565             :     }
     566             :   }
     567             : 
     568             :   return getInstructionMapping(DefaultMappingID, Cost,
     569         110 :                                getOperandsMapping(OpdsMapping), NumOperands);
     570      216918 : }

Generated by: LCOV version 1.13