xref: /llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision 4fa83c03fd7b33bf826bfc05d370df038329e826)
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 "llvm/CodeGen/GlobalISel/RegisterBank.h"
17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/Target/TargetRegisterInfo.h"
20 
21 #define GET_TARGET_REGBANK_IMPL
22 #include "ARMGenRegisterBank.inc"
23 
24 using namespace llvm;
25 
26 #ifndef LLVM_BUILD_GLOBAL_ISEL
27 #error "You shouldn't build this"
28 #endif
29 
30 // FIXME: TableGen this.
31 // If it grows too much and TableGen still isn't ready to do the job, extract it
32 // into an ARMGenRegisterBankInfo.def (similar to AArch64).
33 namespace llvm {
34 namespace ARM {
35 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
36 RegisterBankInfo::PartialMapping FPRPartialMapping{0, 32, FPRRegBank};
37 
38 RegisterBankInfo::ValueMapping ValueMappings[] = {
39     {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1},
40     {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}};
41 } // end namespace arm
42 } // end namespace llvm
43 
44 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
45     : ARMGenRegisterBankInfo() {
46   static bool AlreadyInit = false;
47   // We have only one set of register banks, whatever the subtarget
48   // is. Therefore, the initialization of the RegBanks table should be
49   // done only once. Indeed the table of all register banks
50   // (ARM::RegBanks) is unique in the compiler. At some point, it
51   // will get tablegen'ed and the whole constructor becomes empty.
52   if (AlreadyInit)
53     return;
54   AlreadyInit = true;
55 
56   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
57   (void)RBGPR;
58   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
59 
60   // Initialize the GPR bank.
61   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
62          "Subclass not added?");
63   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
64          "Subclass not added?");
65   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
66          "Subclass not added?");
67   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
68          "Subclass not added?");
69   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
70          "Subclass not added?");
71   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
72          "Subclass not added?");
73   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
74          "Subclass not added?");
75   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
76 }
77 
78 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
79     const TargetRegisterClass &RC) const {
80   using namespace ARM;
81 
82   switch (RC.getID()) {
83   case GPRRegClassID:
84   case GPRnopcRegClassID:
85   case tGPR_and_tcGPRRegClassID:
86     return getRegBank(ARM::GPRRegBankID);
87   case SPR_8RegClassID:
88   case SPRRegClassID:
89     return getRegBank(ARM::FPRRegBankID);
90   default:
91     llvm_unreachable("Unsupported register kind");
92   }
93 
94   llvm_unreachable("Switch should handle all register classes");
95 }
96 
97 RegisterBankInfo::InstructionMapping
98 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
99   auto Opc = MI.getOpcode();
100 
101   // Try the default logic for non-generic instructions that are either copies
102   // or already have some operands assigned to banks.
103   if (!isPreISelGenericOpcode(Opc)) {
104     InstructionMapping Mapping = getInstrMappingImpl(MI);
105     if (Mapping.isValid())
106       return Mapping;
107   }
108 
109   using namespace TargetOpcode;
110 
111   unsigned NumOperands = MI.getNumOperands();
112   const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
113 
114   switch (Opc) {
115   case G_ADD:
116   case G_LOAD:
117   case G_SEXT:
118   case G_ZEXT:
119     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
120     // the real world we would use different mappings.
121     OperandsMapping = &ARM::ValueMappings[0];
122     break;
123   case G_FADD:
124     OperandsMapping = &ARM::ValueMappings[3];
125     break;
126   case G_FRAME_INDEX:
127     OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
128     break;
129   default:
130     return InstructionMapping{};
131   }
132 
133   return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
134                             NumOperands};
135 }
136