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::GPRnoip_and_tcGPRRegClassID)) &&
160            "Subclass not added?");
161     assert(RBGPR.covers(*TRI.getRegClass(
162                ARM::tGPREven_and_GPRnoip_and_tcGPRRegClassID)) &&
163            "Subclass not added?");
164     assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&
165            "Subclass not added?");
166     assert(getMaximumSize(RBGPR.getID()) == 32 &&
167            "GPRs should hold up to 32-bit");
168 
169 #ifndef NDEBUG
170     ARM::checkPartialMappings();
171     ARM::checkValueMappings();
172 #endif
173   };
174 
175   llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
176 }
177 
178 const RegisterBank &
179 ARMRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
180                                             LLT) const {
181   using namespace ARM;
182 
183   switch (RC.getID()) {
184   case GPRRegClassID:
185   case GPRwithAPSRRegClassID:
186   case GPRnoipRegClassID:
187   case GPRnopcRegClassID:
188   case GPRnoip_and_GPRnopcRegClassID:
189   case rGPRRegClassID:
190   case GPRspRegClassID:
191   case GPRnoip_and_tcGPRRegClassID:
192   case tcGPRRegClassID:
193   case tGPRRegClassID:
194   case tGPREvenRegClassID:
195   case tGPROddRegClassID:
196   case tGPR_and_tGPREvenRegClassID:
197   case tGPR_and_tGPROddRegClassID:
198   case tGPREven_and_tcGPRRegClassID:
199   case tGPREven_and_GPRnoip_and_tcGPRRegClassID:
200   case tGPROdd_and_tcGPRRegClassID:
201     return getRegBank(ARM::GPRRegBankID);
202   case HPRRegClassID:
203   case SPR_8RegClassID:
204   case SPRRegClassID:
205   case DPR_8RegClassID:
206   case DPRRegClassID:
207   case QPRRegClassID:
208     return getRegBank(ARM::FPRRegBankID);
209   default:
210     llvm_unreachable("Unsupported register kind");
211   }
212 
213   llvm_unreachable("Switch should handle all register classes");
214 }
215 
216 const RegisterBankInfo::InstructionMapping &
217 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
218   auto Opc = MI.getOpcode();
219 
220   // Try the default logic for non-generic instructions that are either copies
221   // or already have some operands assigned to banks.
222   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
223     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
224     if (Mapping.isValid())
225       return Mapping;
226   }
227 
228   using namespace TargetOpcode;
229 
230   const MachineFunction &MF = *MI.getParent()->getParent();
231   const MachineRegisterInfo &MRI = MF.getRegInfo();
232   unsigned NumOperands = MI.getNumOperands();
233   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
234 
235   switch (Opc) {
236   case G_ADD:
237   case G_SUB: {
238     // Integer operations where the source and destination are in the
239     // same register class.
240     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
241     OperandsMapping = Ty.getSizeInBits() == 64
242                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
243                           : &ARM::ValueMappings[ARM::GPR3OpsIdx];
244     break;
245   }
246   case G_MUL:
247   case G_AND:
248   case G_OR:
249   case G_XOR:
250   case G_LSHR:
251   case G_ASHR:
252   case G_SHL:
253   case G_SDIV:
254   case G_UDIV:
255   case G_SEXT:
256   case G_ZEXT:
257   case G_ANYEXT:
258   case G_PTR_ADD:
259   case G_INTTOPTR:
260   case G_PTRTOINT:
261   case G_CTLZ:
262     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
263     // the real world we would use different mappings.
264     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
265     break;
266   case G_TRUNC: {
267     // In some cases we may end up with a G_TRUNC from a 64-bit value to a
268     // 32-bit value. This isn't a real floating point trunc (that would be a
269     // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
270     // because the legalizer doesn't distinguish between integer and floating
271     // point values so it may leave some 64-bit integers un-narrowed. Until we
272     // have a more principled solution that doesn't let such things sneak all
273     // the way to this point, just map the source to a DPR and the destination
274     // to a GPR.
275     LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
276     OperandsMapping =
277         LargeTy.getSizeInBits() <= 32
278             ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
279             : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
280                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]});
281     break;
282   }
283   case G_LOAD:
284   case G_STORE: {
285     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
286     OperandsMapping =
287         Ty.getSizeInBits() == 64
288             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
289                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
290             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
291     break;
292   }
293   case G_FADD:
294   case G_FSUB:
295   case G_FMUL:
296   case G_FDIV:
297   case G_FNEG: {
298     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
299     OperandsMapping =Ty.getSizeInBits() == 64
300                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
301                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
302     break;
303   }
304   case G_FMA: {
305     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
306     OperandsMapping =
307         Ty.getSizeInBits() == 64
308             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
309                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
310                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
311                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]})
312             : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
313                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
314                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
315                                   &ARM::ValueMappings[ARM::SPR3OpsIdx]});
316     break;
317   }
318   case G_FPEXT: {
319     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
320     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
321     if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
322       OperandsMapping =
323           getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
324                               &ARM::ValueMappings[ARM::SPR3OpsIdx]});
325     break;
326   }
327   case G_FPTRUNC: {
328     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
329     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
330     if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
331       OperandsMapping =
332           getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
333                               &ARM::ValueMappings[ARM::DPR3OpsIdx]});
334     break;
335   }
336   case G_FPTOSI:
337   case G_FPTOUI: {
338     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
339     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
340     if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
341         ToTy.getSizeInBits() == 32)
342       OperandsMapping =
343           FromTy.getSizeInBits() == 64
344               ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
345                                     &ARM::ValueMappings[ARM::DPR3OpsIdx]})
346               : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
347                                     &ARM::ValueMappings[ARM::SPR3OpsIdx]});
348     break;
349   }
350   case G_SITOFP:
351   case G_UITOFP: {
352     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
353     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
354     if (FromTy.getSizeInBits() == 32 &&
355         (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
356       OperandsMapping =
357           ToTy.getSizeInBits() == 64
358               ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
359                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]})
360               : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
361                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]});
362     break;
363   }
364   case G_FCONSTANT: {
365     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
366     OperandsMapping = getOperandsMapping(
367         {Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
368                                   : &ARM::ValueMappings[ARM::SPR3OpsIdx],
369          nullptr});
370     break;
371   }
372   case G_CONSTANT:
373   case G_FRAME_INDEX:
374   case G_GLOBAL_VALUE:
375     OperandsMapping =
376         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
377     break;
378   case G_SELECT: {
379     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
380     (void)Ty;
381     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
382     (void)Ty2;
383     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
384     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
385     OperandsMapping =
386         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
387                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
388                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
389                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
390     break;
391   }
392   case G_ICMP: {
393     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
394     (void)Ty2;
395     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
396     OperandsMapping =
397         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
398                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
399                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
400     break;
401   }
402   case G_FCMP: {
403     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
404     (void)Ty;
405     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
406     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
407     (void)Ty2;
408     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
409     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
410            "Mismatched operand sizes for G_FCMP");
411 
412     unsigned Size = Ty1.getSizeInBits();
413     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
414 
415     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
416                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
417     OperandsMapping =
418         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
419                             FPRValueMapping, FPRValueMapping});
420     break;
421   }
422   case G_MERGE_VALUES: {
423     // We only support G_MERGE_VALUES for creating a double precision floating
424     // point value out of two GPRs.
425     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
426     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
427     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
428     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
429         Ty2.getSizeInBits() != 32)
430       return getInvalidInstructionMapping();
431     OperandsMapping =
432         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
433                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
434                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
435     break;
436   }
437   case G_UNMERGE_VALUES: {
438     // We only support G_UNMERGE_VALUES for splitting a double precision
439     // floating point value into two GPRs.
440     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
441     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
442     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
443     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
444         Ty2.getSizeInBits() != 64)
445       return getInvalidInstructionMapping();
446     OperandsMapping =
447         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
448                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
449                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
450     break;
451   }
452   case G_BR:
453     OperandsMapping = getOperandsMapping({nullptr});
454     break;
455   case G_BRCOND:
456     OperandsMapping =
457         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
458     break;
459   case DBG_VALUE: {
460     SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
461     const MachineOperand &MaybeReg = MI.getOperand(0);
462     if (MaybeReg.isReg() && MaybeReg.getReg()) {
463       unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
464       if (Size > 32 && Size != 64)
465         return getInvalidInstructionMapping();
466       OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
467                                    : &ARM::ValueMappings[ARM::GPR3OpsIdx];
468     }
469     OperandsMapping = getOperandsMapping(OperandBanks);
470     break;
471   }
472   default:
473     return getInvalidInstructionMapping();
474   }
475 
476 #ifndef NDEBUG
477   for (unsigned i = 0; i < NumOperands; i++) {
478     for (const auto &Mapping : OperandsMapping[i]) {
479       assert(
480           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
481            MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&
482           "Trying to use floating point register bank on target without vfp");
483     }
484   }
485 #endif
486 
487   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
488                                NumOperands);
489 }
490