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