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