xref: /llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision d64d5024a4b80d6d909dc34232d024c4f4a86e1e)
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 using namespace llvm;
22 
23 #ifndef LLVM_BUILD_GLOBAL_ISEL
24 #error "You shouldn't build this"
25 #endif
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 const uint32_t GPRCoverageData[] = {
33     // Classes 0-31
34     (1u << ARM::GPRRegClassID) | (1u << ARM::GPRwithAPSRRegClassID) |
35         (1u << ARM::GPRnopcRegClassID) | (1u << ARM::rGPRRegClassID) |
36         (1u << ARM::hGPRRegClassID) | (1u << ARM::tGPRRegClassID) |
37         (1u << ARM::GPRnopc_and_hGPRRegClassID) |
38         (1u << ARM::hGPR_and_rGPRRegClassID) | (1u << ARM::tcGPRRegClassID) |
39         (1u << ARM::tGPR_and_tcGPRRegClassID) | (1u << ARM::GPRspRegClassID) |
40         (1u << ARM::hGPR_and_tcGPRRegClassID),
41     // Classes 32-63
42     0,
43     // Classes 64-96
44     0,
45     // FIXME: Some of the entries below this point can be safely removed once
46     // this is tablegenerated. It's only needed because of the hardcoded
47     // register class limit.
48     // Classes 97-128
49     0,
50     // Classes 129-160
51     0,
52     // Classes 161-192
53     0,
54     // Classes 193-224
55     0,
56 };
57 
58 // FIXME: The 200 will be replaced by the number of register classes when this is
59 //        tablegenerated.
60 RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData, 200);
61 RegisterBank *RegBanks[] = {&GPRRegBank};
62 
63 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank};
64 
65 RegisterBankInfo::ValueMapping ValueMappings[] = {
66     {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}};
67 } // end namespace arm
68 } // end namespace llvm
69 
70 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
71     : RegisterBankInfo(ARM::RegBanks, ARM::NumRegisterBanks) {
72   static bool AlreadyInit = false;
73   // We have only one set of register banks, whatever the subtarget
74   // is. Therefore, the initialization of the RegBanks table should be
75   // done only once. Indeed the table of all register banks
76   // (ARM::RegBanks) is unique in the compiler. At some point, it
77   // will get tablegen'ed and the whole constructor becomes empty.
78   if (AlreadyInit)
79     return;
80   AlreadyInit = true;
81 
82   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
83   (void)RBGPR;
84   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
85 
86   // Initialize the GPR bank.
87   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
88          "Subclass not added?");
89   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
90          "Subclass not added?");
91   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
92          "Subclass not added?");
93   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
94          "Subclass not added?");
95   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
96          "Subclass not added?");
97   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
98          "Subclass not added?");
99   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
100          "Subclass not added?");
101   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
102 }
103 
104 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
105     const TargetRegisterClass &RC) const {
106   using namespace ARM;
107 
108   switch (RC.getID()) {
109   case GPRRegClassID:
110   case tGPR_and_tcGPRRegClassID:
111     return getRegBank(ARM::GPRRegBankID);
112   default:
113     llvm_unreachable("Unsupported register kind");
114   }
115 
116   llvm_unreachable("Switch should handle all register classes");
117 }
118 
119 RegisterBankInfo::InstructionMapping
120 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
121   auto Opc = MI.getOpcode();
122 
123   // Try the default logic for non-generic instructions that are either copies
124   // or already have some operands assigned to banks.
125   if (!isPreISelGenericOpcode(Opc)) {
126     InstructionMapping Mapping = getInstrMappingImpl(MI);
127     if (Mapping.isValid())
128       return Mapping;
129   }
130 
131   using namespace TargetOpcode;
132 
133   unsigned NumOperands = MI.getNumOperands();
134   const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
135 
136   switch (Opc) {
137   case G_ADD:
138   case G_LOAD:
139     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
140     // the real world we would use different mappings.
141     OperandsMapping = &ARM::ValueMappings[0];
142     break;
143   case G_FRAME_INDEX:
144     OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
145     break;
146   default:
147     return InstructionMapping{};
148   }
149 
150   return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
151                             NumOperands};
152 }
153