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

Generated by: LCOV version 1.13