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