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(flag&: InitializeRegisterBankFlag, F&: 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(Opcode: 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(Reg: MI.getOperand(i: 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(Reg: MI.getOperand(i: 1).getReg()); |
276 | OperandsMapping = |
277 | LargeTy.getSizeInBits() <= 32 |
278 | ? &ARM::ValueMappings[ARM::GPR3OpsIdx] |
279 | : getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
286 | OperandsMapping = |
287 | Ty.getSizeInBits() == 64 |
288 | ? getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 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(Reg: MI.getOperand(i: 0).getReg()); |
306 | OperandsMapping = |
307 | Ty.getSizeInBits() == 64 |
308 | ? getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::DPR3OpsIdx], |
309 | &ARM::ValueMappings[ARM::DPR3OpsIdx], |
310 | &ARM::ValueMappings[ARM::DPR3OpsIdx], |
311 | &ARM::ValueMappings[ARM::DPR3OpsIdx]}) |
312 | : getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
320 | LLT FromTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
321 | if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32) |
322 | OperandsMapping = |
323 | getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::DPR3OpsIdx], |
324 | &ARM::ValueMappings[ARM::SPR3OpsIdx]}); |
325 | break; |
326 | } |
327 | case G_FPTRUNC: { |
328 | LLT ToTy = MRI.getType(Reg: MI.getOperand(i: 0).getReg()); |
329 | LLT FromTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
330 | if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64) |
331 | OperandsMapping = |
332 | getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
339 | LLT FromTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
340 | if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) && |
341 | ToTy.getSizeInBits() == 32) |
342 | OperandsMapping = |
343 | FromTy.getSizeInBits() == 64 |
344 | ? getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::GPR3OpsIdx], |
345 | &ARM::ValueMappings[ARM::DPR3OpsIdx]}) |
346 | : getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
353 | LLT FromTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
354 | if (FromTy.getSizeInBits() == 32 && |
355 | (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64)) |
356 | OperandsMapping = |
357 | ToTy.getSizeInBits() == 64 |
358 | ? getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::DPR3OpsIdx], |
359 | &ARM::ValueMappings[ARM::GPR3OpsIdx]}) |
360 | : getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::SPR3OpsIdx], |
361 | &ARM::ValueMappings[ARM::GPR3OpsIdx]}); |
362 | break; |
363 | } |
364 | case G_FCONSTANT: { |
365 | LLT Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg()); |
366 | OperandsMapping = getOperandsMapping( |
367 | OpdsMapping: {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(OpdsMapping: {&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); |
377 | break; |
378 | case G_SELECT: { |
379 | LLT Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg()); |
380 | (void)Ty; |
381 | LLT Ty2 = MRI.getType(Reg: MI.getOperand(i: 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(OpdsMapping: {&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(Reg: MI.getOperand(i: 2).getReg()); |
394 | (void)Ty2; |
395 | assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP" ); |
396 | OperandsMapping = |
397 | getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
404 | (void)Ty; |
405 | LLT Ty1 = MRI.getType(Reg: MI.getOperand(i: 2).getReg()); |
406 | LLT Ty2 = MRI.getType(Reg: MI.getOperand(i: 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(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
426 | LLT Ty1 = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
427 | LLT Ty2 = MRI.getType(Reg: MI.getOperand(i: 2).getReg()); |
428 | if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || |
429 | Ty2.getSizeInBits() != 32) |
430 | return getInvalidInstructionMapping(); |
431 | OperandsMapping = |
432 | getOperandsMapping(OpdsMapping: {&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(Reg: MI.getOperand(i: 0).getReg()); |
441 | LLT Ty1 = MRI.getType(Reg: MI.getOperand(i: 1).getReg()); |
442 | LLT Ty2 = MRI.getType(Reg: MI.getOperand(i: 2).getReg()); |
443 | if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || |
444 | Ty2.getSizeInBits() != 64) |
445 | return getInvalidInstructionMapping(); |
446 | OperandsMapping = |
447 | getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::GPR3OpsIdx], |
448 | &ARM::ValueMappings[ARM::GPR3OpsIdx], |
449 | &ARM::ValueMappings[ARM::DPR3OpsIdx]}); |
450 | break; |
451 | } |
452 | case G_BR: |
453 | OperandsMapping = getOperandsMapping(OpdsMapping: {nullptr}); |
454 | break; |
455 | case G_BRCOND: |
456 | OperandsMapping = |
457 | getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); |
458 | break; |
459 | case DBG_VALUE: { |
460 | SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands); |
461 | const MachineOperand &MaybeReg = MI.getOperand(i: 0); |
462 | if (MaybeReg.isReg() && MaybeReg.getReg()) { |
463 | unsigned Size = MRI.getType(Reg: 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(OpdsMapping: OperandBanks); |
470 | break; |
471 | } |
472 | case G_GET_FPENV: |
473 | case G_SET_FPENV: |
474 | OperandsMapping = |
475 | getOperandsMapping(OpdsMapping: {&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr}); |
476 | break; |
477 | case G_RESET_FPENV: |
478 | OperandsMapping = getOperandsMapping(OpdsMapping: {nullptr}); |
479 | break; |
480 | default: |
481 | return getInvalidInstructionMapping(); |
482 | } |
483 | |
484 | #ifndef NDEBUG |
485 | for (unsigned i = 0; i < NumOperands; i++) { |
486 | for (const auto &Mapping : OperandsMapping[i]) { |
487 | assert( |
488 | (Mapping.RegBank->getID() != ARM::FPRRegBankID || |
489 | MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) && |
490 | "Trying to use floating point register bank on target without vfp" ); |
491 | } |
492 | } |
493 | #endif |
494 | |
495 | return getInstructionMapping(ID: DefaultMappingID, /*Cost=*/1, OperandsMapping, |
496 | NumOperands); |
497 | } |
498 | |