xref: /llvm-project/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp (revision 52e5683ddddad787caf15c8edfd34eb4a9c8704a)
1 //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the RegisterBankInfo class for ARM.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #include "ARMRegisterBankInfo.h"
14 #include "ARMInstrInfo.h" // For the register classes
15 #include "ARMSubtarget.h"
16 #include "llvm/CodeGen/MachineRegisterInfo.h"
17 #include "llvm/CodeGen/RegisterBank.h"
18 #include "llvm/CodeGen/RegisterBankInfo.h"
19 #include "llvm/CodeGen/TargetRegisterInfo.h"
20 
21 #define GET_TARGET_REGBANK_IMPL
22 #include "ARMGenRegisterBank.inc"
23 
24 using namespace llvm;
25 
26 // FIXME: TableGen this.
27 // If it grows too much and TableGen still isn't ready to do the job, extract it
28 // into an ARMGenRegisterBankInfo.def (similar to AArch64).
29 namespace llvm {
30 namespace ARM {
31 enum PartialMappingIdx {
32   PMI_GPR,
33   PMI_SPR,
34   PMI_DPR,
35   PMI_Min = PMI_GPR,
36 };
37 
38 const RegisterBankInfo::PartialMapping PartMappings[]{
39     // GPR Partial Mapping
40     {0, 32, GPRRegBank},
41     // SPR Partial Mapping
42     {0, 32, FPRRegBank},
43     // DPR Partial Mapping
44     {0, 64, FPRRegBank},
45 };
46 
47 #ifndef NDEBUG
48 static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,
49                              unsigned Start, unsigned Length,
50                              unsigned RegBankID) {
51   return PM.StartIdx == Start && PM.Length == Length &&
52          PM.RegBank->getID() == RegBankID;
53 }
54 
55 static void checkPartialMappings() {
56   assert(
57       checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
58       "Wrong mapping for GPR");
59   assert(
60       checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
61       "Wrong mapping for SPR");
62   assert(
63       checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
64       "Wrong mapping for DPR");
65 }
66 #endif
67 
68 enum ValueMappingIdx {
69   InvalidIdx = 0,
70   GPR3OpsIdx = 1,
71   SPR3OpsIdx = 4,
72   DPR3OpsIdx = 7,
73 };
74 
75 const RegisterBankInfo::ValueMapping ValueMappings[] = {
76     // invalid
77     {nullptr, 0},
78     // 3 ops in GPRs
79     {&PartMappings[PMI_GPR - PMI_Min], 1},
80     {&PartMappings[PMI_GPR - PMI_Min], 1},
81     {&PartMappings[PMI_GPR - PMI_Min], 1},
82     // 3 ops in SPRs
83     {&PartMappings[PMI_SPR - PMI_Min], 1},
84     {&PartMappings[PMI_SPR - PMI_Min], 1},
85     {&PartMappings[PMI_SPR - PMI_Min], 1},
86     // 3 ops in DPRs
87     {&PartMappings[PMI_DPR - PMI_Min], 1},
88     {&PartMappings[PMI_DPR - PMI_Min], 1},
89     {&PartMappings[PMI_DPR - PMI_Min], 1}};
90 
91 #ifndef NDEBUG
92 static bool
93 checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
94                   const RegisterBankInfo::PartialMapping *BreakDown) {
95   return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
96 }
97 
98 static void checkValueMappings() {
99   assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
100                            &PartMappings[PMI_GPR - PMI_Min]) &&
101          "Wrong value mapping for 3 GPR ops instruction");
102   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
103                            &PartMappings[PMI_GPR - PMI_Min]) &&
104          "Wrong value mapping for 3 GPR ops instruction");
105   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
106                            &PartMappings[PMI_GPR - PMI_Min]) &&
107          "Wrong value mapping for 3 GPR ops instruction");
108 
109   assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
110                            &PartMappings[PMI_SPR - PMI_Min]) &&
111          "Wrong value mapping for 3 SPR ops instruction");
112   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
113                            &PartMappings[PMI_SPR - PMI_Min]) &&
114          "Wrong value mapping for 3 SPR ops instruction");
115   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
116                            &PartMappings[PMI_SPR - PMI_Min]) &&
117          "Wrong value mapping for 3 SPR ops instruction");
118 
119   assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
120                            &PartMappings[PMI_DPR - PMI_Min]) &&
121          "Wrong value mapping for 3 DPR ops instruction");
122   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
123                            &PartMappings[PMI_DPR - PMI_Min]) &&
124          "Wrong value mapping for 3 DPR ops instruction");
125   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
126                            &PartMappings[PMI_DPR - PMI_Min]) &&
127          "Wrong value mapping for 3 DPR ops instruction");
128 }
129 #endif
130 } // end namespace arm
131 } // end namespace llvm
132 
133 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) {
134   // We have only one set of register banks, whatever the subtarget
135   // is. Therefore, the initialization of the RegBanks table should be
136   // done only once. Indeed the table of all register banks
137   // (ARM::RegBanks) is unique in the compiler. At some point, it
138   // will get tablegen'ed and the whole constructor becomes empty.
139   static llvm::once_flag InitializeRegisterBankFlag;
140 
141   static auto InitializeRegisterBankOnce = [&]() {
142     const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
143     (void)RBGPR;
144     assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
145 
146     // Initialize the GPR bank.
147     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
148            "Subclass not added?");
149     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
150            "Subclass not added?");
151     assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
152            "Subclass not added?");
153     assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
154            "Subclass not added?");
155     assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
156            "Subclass not added?");
157     assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
158            "Subclass not added?");
159     assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&
160            "Subclass not added?");
161     assert(getMaximumSize(RBGPR.getID()) == 32 &&
162            "GPRs should hold up to 32-bit");
163 
164 #ifndef NDEBUG
165     ARM::checkPartialMappings();
166     ARM::checkValueMappings();
167 #endif
168   };
169 
170   llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
171 }
172 
173 const RegisterBankInfo::InstructionMapping &
174 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
175   auto Opc = MI.getOpcode();
176 
177   // Try the default logic for non-generic instructions that are either copies
178   // or already have some operands assigned to banks.
179   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
180     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
181     if (Mapping.isValid())
182       return Mapping;
183   }
184 
185   using namespace TargetOpcode;
186 
187   const MachineFunction &MF = *MI.getParent()->getParent();
188   const MachineRegisterInfo &MRI = MF.getRegInfo();
189   unsigned NumOperands = MI.getNumOperands();
190   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
191 
192   switch (Opc) {
193   case G_ADD:
194   case G_SUB: {
195     // Integer operations where the source and destination are in the
196     // same register class.
197     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
198     OperandsMapping = Ty.getSizeInBits() == 64
199                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
200                           : &ARM::ValueMappings[ARM::GPR3OpsIdx];
201     break;
202   }
203   case G_MUL:
204   case G_AND:
205   case G_OR:
206   case G_XOR:
207   case G_LSHR:
208   case G_ASHR:
209   case G_SHL:
210   case G_SDIV:
211   case G_UDIV:
212   case G_SEXT:
213   case G_ZEXT:
214   case G_ANYEXT:
215   case G_PTR_ADD:
216   case G_INTTOPTR:
217   case G_PTRTOINT:
218   case G_CTLZ:
219     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
220     // the real world we would use different mappings.
221     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
222     break;
223   case G_TRUNC: {
224     // In some cases we may end up with a G_TRUNC from a 64-bit value to a
225     // 32-bit value. This isn't a real floating point trunc (that would be a
226     // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
227     // because the legalizer doesn't distinguish between integer and floating
228     // point values so it may leave some 64-bit integers un-narrowed. Until we
229     // have a more principled solution that doesn't let such things sneak all
230     // the way to this point, just map the source to a DPR and the destination
231     // to a GPR.
232     LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
233     OperandsMapping =
234         LargeTy.getSizeInBits() <= 32
235             ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
236             : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
237                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]});
238     break;
239   }
240   case G_LOAD:
241   case G_STORE: {
242     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
243     OperandsMapping =
244         Ty.getSizeInBits() == 64
245             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
246                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
247             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
248     break;
249   }
250   case G_FADD:
251   case G_FSUB:
252   case G_FMUL:
253   case G_FDIV:
254   case G_FNEG: {
255     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
256     OperandsMapping =Ty.getSizeInBits() == 64
257                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
258                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
259     break;
260   }
261   case G_FMA: {
262     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
263     OperandsMapping =
264         Ty.getSizeInBits() == 64
265             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
266                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
267                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
268                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]})
269             : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
270                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
271                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
272                                   &ARM::ValueMappings[ARM::SPR3OpsIdx]});
273     break;
274   }
275   case G_FPEXT: {
276     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
277     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
278     if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
279       OperandsMapping =
280           getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
281                               &ARM::ValueMappings[ARM::SPR3OpsIdx]});
282     break;
283   }
284   case G_FPTRUNC: {
285     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
286     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
287     if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
288       OperandsMapping =
289           getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
290                               &ARM::ValueMappings[ARM::DPR3OpsIdx]});
291     break;
292   }
293   case G_FPTOSI:
294   case G_FPTOUI: {
295     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
296     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
297     if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
298         ToTy.getSizeInBits() == 32)
299       OperandsMapping =
300           FromTy.getSizeInBits() == 64
301               ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
302                                     &ARM::ValueMappings[ARM::DPR3OpsIdx]})
303               : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
304                                     &ARM::ValueMappings[ARM::SPR3OpsIdx]});
305     break;
306   }
307   case G_SITOFP:
308   case G_UITOFP: {
309     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
310     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
311     if (FromTy.getSizeInBits() == 32 &&
312         (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
313       OperandsMapping =
314           ToTy.getSizeInBits() == 64
315               ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
316                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]})
317               : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
318                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]});
319     break;
320   }
321   case G_FCONSTANT: {
322     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
323     OperandsMapping = getOperandsMapping(
324         {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
325                                   : &ARM::ValueMappings[ARM::SPR3OpsIdx],
326          nullptr});
327     break;
328   }
329   case G_CONSTANT:
330   case G_FRAME_INDEX:
331   case G_GLOBAL_VALUE:
332   case G_CONSTANT_POOL:
333     OperandsMapping =
334         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
335     break;
336   case G_SELECT: {
337     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
338     (void)Ty;
339     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
340     (void)Ty2;
341     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
342     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
343     OperandsMapping =
344         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
345                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
346                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
347                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
348     break;
349   }
350   case G_ICMP: {
351     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
352     (void)Ty2;
353     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
354     OperandsMapping =
355         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
356                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
357                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
358     break;
359   }
360   case G_FCMP: {
361     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
362     (void)Ty;
363     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
364     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
365     (void)Ty2;
366     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
367     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
368            "Mismatched operand sizes for G_FCMP");
369 
370     unsigned Size = Ty1.getSizeInBits();
371     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
372 
373     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
374                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
375     OperandsMapping =
376         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
377                             FPRValueMapping, FPRValueMapping});
378     break;
379   }
380   case G_MERGE_VALUES: {
381     // We only support G_MERGE_VALUES for creating a double precision floating
382     // point value out of two GPRs.
383     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
384     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
385     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
386     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
387         Ty2.getSizeInBits() != 32)
388       return getInvalidInstructionMapping();
389     OperandsMapping =
390         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
391                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
392                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
393     break;
394   }
395   case G_UNMERGE_VALUES: {
396     // We only support G_UNMERGE_VALUES for splitting a double precision
397     // floating point value into two GPRs.
398     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
399     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
400     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
401     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
402         Ty2.getSizeInBits() != 64)
403       return getInvalidInstructionMapping();
404     OperandsMapping =
405         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
406                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
407                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
408     break;
409   }
410   case G_BR:
411     OperandsMapping = getOperandsMapping({nullptr});
412     break;
413   case G_BRCOND:
414     OperandsMapping =
415         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
416     break;
417   case DBG_VALUE: {
418     SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
419     const MachineOperand &MaybeReg = MI.getOperand(0);
420     if (MaybeReg.isReg() && MaybeReg.getReg()) {
421       unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
422       if (Size > 32 && Size != 64)
423         return getInvalidInstructionMapping();
424       OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
425                                    : &ARM::ValueMappings[ARM::GPR3OpsIdx];
426     }
427     OperandsMapping = getOperandsMapping(OperandBanks);
428     break;
429   }
430   case G_GET_FPENV:
431   case G_SET_FPENV:
432   case G_GET_FPMODE:
433     OperandsMapping =
434         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
435     break;
436   case G_RESET_FPENV:
437     OperandsMapping = getOperandsMapping({nullptr});
438     break;
439   default:
440     return getInvalidInstructionMapping();
441   }
442 
443 #ifndef NDEBUG
444   for (unsigned i = 0; i < NumOperands; i++) {
445     for (const auto &Mapping : OperandsMapping[i]) {
446       assert(
447           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
448            MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&
449           "Trying to use floating point register bank on target without vfp");
450     }
451   }
452 #endif
453 
454   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
455                                NumOperands);
456 }
457