xref: /llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision a93803b9fe8817607ce7be9c5ba8ce3b3611e8ee)
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 SPRPartialMapping{0, 32, FPRRegBank};
37 RegisterBankInfo::PartialMapping DPRPartialMapping{0, 64, FPRRegBank};
38 
39 // FIXME: Add the mapping for S(2n+1) as {32, 64, FPRRegBank}
40 RegisterBankInfo::ValueMapping ValueMappings[] = {
41     {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1},
42     {&SPRPartialMapping, 1}, {&SPRPartialMapping, 1}, {&SPRPartialMapping, 1},
43     {&DPRPartialMapping, 1}, {&DPRPartialMapping, 1}, {&DPRPartialMapping, 1}};
44 } // end namespace arm
45 } // end namespace llvm
46 
47 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
48     : ARMGenRegisterBankInfo() {
49   static bool AlreadyInit = false;
50   // We have only one set of register banks, whatever the subtarget
51   // is. Therefore, the initialization of the RegBanks table should be
52   // done only once. Indeed the table of all register banks
53   // (ARM::RegBanks) is unique in the compiler. At some point, it
54   // will get tablegen'ed and the whole constructor becomes empty.
55   if (AlreadyInit)
56     return;
57   AlreadyInit = true;
58 
59   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
60   (void)RBGPR;
61   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
62 
63   // Initialize the GPR bank.
64   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
65          "Subclass not added?");
66   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
67          "Subclass not added?");
68   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
69          "Subclass not added?");
70   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
71          "Subclass not added?");
72   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
73          "Subclass not added?");
74   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
75          "Subclass not added?");
76   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
77          "Subclass not added?");
78   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
79 }
80 
81 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
82     const TargetRegisterClass &RC) const {
83   using namespace ARM;
84 
85   switch (RC.getID()) {
86   case GPRRegClassID:
87   case GPRnopcRegClassID:
88   case tGPR_and_tcGPRRegClassID:
89     return getRegBank(ARM::GPRRegBankID);
90   case SPR_8RegClassID:
91   case SPRRegClassID:
92   case DPR_8RegClassID:
93   case DPRRegClassID:
94     return getRegBank(ARM::FPRRegBankID);
95   default:
96     llvm_unreachable("Unsupported register kind");
97   }
98 
99   llvm_unreachable("Switch should handle all register classes");
100 }
101 
102 RegisterBankInfo::InstructionMapping
103 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
104   auto Opc = MI.getOpcode();
105 
106   // Try the default logic for non-generic instructions that are either copies
107   // or already have some operands assigned to banks.
108   if (!isPreISelGenericOpcode(Opc)) {
109     InstructionMapping Mapping = getInstrMappingImpl(MI);
110     if (Mapping.isValid())
111       return Mapping;
112   }
113 
114   using namespace TargetOpcode;
115 
116   const MachineFunction &MF = *MI.getParent()->getParent();
117   const MachineRegisterInfo &MRI = MF.getRegInfo();
118   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
119 
120   unsigned NumOperands = MI.getNumOperands();
121   const ValueMapping *OperandsMapping = &ARM::ValueMappings[0];
122 
123   switch (Opc) {
124   case G_ADD:
125   case G_SEXT:
126   case G_ZEXT:
127     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
128     // the real world we would use different mappings.
129     OperandsMapping = &ARM::ValueMappings[0];
130     break;
131   case G_LOAD:
132     OperandsMapping = Ty.getSizeInBits() == 64
133                           ? getOperandsMapping({&ARM::ValueMappings[6],
134                                                 &ARM::ValueMappings[0]})
135                           : &ARM::ValueMappings[0];
136     break;
137   case G_FADD:
138     assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) &&
139            "Unsupported size for G_FADD");
140     OperandsMapping = Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[6]
141                                                : &ARM::ValueMappings[3];
142     break;
143   case G_FRAME_INDEX:
144     OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr});
145     break;
146   case G_SEQUENCE: {
147     // We only support G_SEQUENCE for creating a double precision floating point
148     // value out of two GPRs.
149     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
150     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
151     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
152         Ty2.getSizeInBits() != 32)
153       return InstructionMapping{};
154     OperandsMapping =
155         getOperandsMapping({&ARM::ValueMappings[6], &ARM::ValueMappings[0],
156                             nullptr, &ARM::ValueMappings[0], nullptr});
157     break;
158   }
159   case G_EXTRACT: {
160     // We only support G_EXTRACT for splitting a double precision floating point
161     // value into two GPRs.
162     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
163     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
164     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
165         Ty2.getSizeInBits() != 64)
166       return InstructionMapping{};
167     OperandsMapping =
168         getOperandsMapping({&ARM::ValueMappings[0], &ARM::ValueMappings[0],
169                             &ARM::ValueMappings[6], nullptr, nullptr});
170     break;
171   }
172   default:
173     return InstructionMapping{};
174   }
175 
176   return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping,
177                             NumOperands};
178 }
179