1//===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
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
10/// AArch64.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
14#include "AArch64RegisterBankInfo.h"
15#include "AArch64RegisterInfo.h"
16#include "AArch64Subtarget.h"
17#include "MCTargetDesc/AArch64AddressingModes.h"
18#include "MCTargetDesc/AArch64MCTargetDesc.h"
19#include "llvm/ADT/APInt.h"
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
23#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
24#include "llvm/CodeGen/GlobalISel/Utils.h"
25#include "llvm/CodeGen/LowLevelTypeUtils.h"
26#include "llvm/CodeGen/MachineFunction.h"
27#include "llvm/CodeGen/MachineInstr.h"
28#include "llvm/CodeGen/MachineOperand.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/CodeGen/MachineSizeOpts.h"
31#include "llvm/CodeGen/RegisterBank.h"
32#include "llvm/CodeGen/RegisterBankInfo.h"
33#include "llvm/CodeGen/TargetOpcodes.h"
34#include "llvm/CodeGen/TargetRegisterInfo.h"
35#include "llvm/CodeGen/TargetSubtargetInfo.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/IntrinsicsAArch64.h"
38#include "llvm/Support/ErrorHandling.h"
39#include "llvm/Support/Threading.h"
40#include <cassert>
41
42#define GET_TARGET_REGBANK_IMPL
43#include "AArch64GenRegisterBank.inc"
44
45// This file will be TableGen'ed at some point.
46#include "AArch64GenRegisterBankInfo.def"
47
48using namespace llvm;
49static const unsigned CustomMappingID = 1;
50
51AArch64RegisterBankInfo::AArch64RegisterBankInfo(
52 const TargetRegisterInfo &TRI) {
53 static llvm::once_flag InitializeRegisterBankFlag;
54
55 static auto InitializeRegisterBankOnce = [&]() {
56 // We have only one set of register banks, whatever the subtarget
57 // is. Therefore, the initialization of the RegBanks table should be
58 // done only once. Indeed the table of all register banks
59 // (AArch64::RegBanks) is unique in the compiler. At some point, it
60 // will get tablegen'ed and the whole constructor becomes empty.
61
62 const RegisterBank &RBGPR = getRegBank(ID: AArch64::GPRRegBankID);
63 (void)RBGPR;
64 assert(&AArch64::GPRRegBank == &RBGPR &&
65 "The order in RegBanks is messed up");
66
67 const RegisterBank &RBFPR = getRegBank(ID: AArch64::FPRRegBankID);
68 (void)RBFPR;
69 assert(&AArch64::FPRRegBank == &RBFPR &&
70 "The order in RegBanks is messed up");
71
72 const RegisterBank &RBCCR = getRegBank(ID: AArch64::CCRegBankID);
73 (void)RBCCR;
74 assert(&AArch64::CCRegBank == &RBCCR &&
75 "The order in RegBanks is messed up");
76
77 // The GPR register bank is fully defined by all the registers in
78 // GR64all + its subclasses.
79 assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
80 "Subclass not added?");
81 assert(getMaximumSize(RBGPR.getID()) == 128 &&
82 "GPRs should hold up to 128-bit");
83
84 // The FPR register bank is fully defined by all the registers in
85 // GR64all + its subclasses.
86 assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
87 "Subclass not added?");
88 assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
89 "Subclass not added?");
90 assert(getMaximumSize(RBFPR.getID()) == 512 &&
91 "FPRs should hold up to 512-bit via QQQQ sequence");
92
93 assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
94 "Class not added?");
95 assert(getMaximumSize(RBCCR.getID()) == 32 &&
96 "CCR should hold up to 32-bit");
97
98 // Check that the TableGen'ed like file is in sync we our expectations.
99 // First, the Idx.
100 assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR,
101 {PMI_GPR32, PMI_GPR64, PMI_GPR128}) &&
102 "PartialMappingIdx's are incorrectly ordered");
103 assert(checkPartialMappingIdx(PMI_FirstFPR, PMI_LastFPR,
104 {PMI_FPR16, PMI_FPR32, PMI_FPR64, PMI_FPR128,
105 PMI_FPR256, PMI_FPR512}) &&
106 "PartialMappingIdx's are incorrectly ordered");
107// Now, the content.
108// Check partial mapping.
109#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
110 do { \
111 assert( \
112 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
113 #Idx " is incorrectly initialized"); \
114 } while (false)
115
116 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
117 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
118 CHECK_PARTIALMAP(PMI_GPR128, 0, 128, RBGPR);
119 CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR);
120 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
121 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
122 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
123 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
124 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
125
126// Check value mapping.
127#define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
128 do { \
129 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
130 PartialMappingIdx::PMI_First##RBName, Size, \
131 Offset) && \
132 #RBName #Size " " #Offset " is incorrectly initialized"); \
133 } while (false)
134
135#define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
136
137 CHECK_VALUEMAP(GPR, 32);
138 CHECK_VALUEMAP(GPR, 64);
139 CHECK_VALUEMAP(GPR, 128);
140 CHECK_VALUEMAP(FPR, 16);
141 CHECK_VALUEMAP(FPR, 32);
142 CHECK_VALUEMAP(FPR, 64);
143 CHECK_VALUEMAP(FPR, 128);
144 CHECK_VALUEMAP(FPR, 256);
145 CHECK_VALUEMAP(FPR, 512);
146
147// Check the value mapping for 3-operands instructions where all the operands
148// map to the same value mapping.
149#define CHECK_VALUEMAP_3OPS(RBName, Size) \
150 do { \
151 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
152 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
153 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
154 } while (false)
155
156 CHECK_VALUEMAP_3OPS(GPR, 32);
157 CHECK_VALUEMAP_3OPS(GPR, 64);
158 CHECK_VALUEMAP_3OPS(GPR, 128);
159 CHECK_VALUEMAP_3OPS(FPR, 32);
160 CHECK_VALUEMAP_3OPS(FPR, 64);
161 CHECK_VALUEMAP_3OPS(FPR, 128);
162 CHECK_VALUEMAP_3OPS(FPR, 256);
163 CHECK_VALUEMAP_3OPS(FPR, 512);
164
165#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
166 do { \
167 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
168 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
169 (void)PartialMapDstIdx; \
170 (void)PartialMapSrcIdx; \
171 const ValueMapping *Map = getCopyMapping(AArch64::RBNameDst##RegBankID, \
172 AArch64::RBNameSrc##RegBankID, \
173 TypeSize::getFixed(Size)); \
174 (void)Map; \
175 assert(Map[0].BreakDown == \
176 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
177 Map[0].NumBreakDowns == 1 && \
178 #RBNameDst #Size " Dst is incorrectly initialized"); \
179 assert(Map[1].BreakDown == \
180 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
181 Map[1].NumBreakDowns == 1 && \
182 #RBNameSrc #Size " Src is incorrectly initialized"); \
183 \
184 } while (false)
185
186 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
187 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32);
188 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
189 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64);
190 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32);
191 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32);
192 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
193 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
194
195#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
196 do { \
197 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
198 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
199 (void)PartialMapDstIdx; \
200 (void)PartialMapSrcIdx; \
201 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
202 (void)Map; \
203 assert(Map[0].BreakDown == \
204 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
205 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
206 " Dst is incorrectly initialized"); \
207 assert(Map[1].BreakDown == \
208 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
209 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
210 " Src is incorrectly initialized"); \
211 \
212 } while (false)
213
214 CHECK_VALUEMAP_FPEXT(32, 16);
215 CHECK_VALUEMAP_FPEXT(64, 16);
216 CHECK_VALUEMAP_FPEXT(64, 32);
217 CHECK_VALUEMAP_FPEXT(128, 64);
218
219 assert(verify(TRI) && "Invalid register bank information");
220 };
221
222 llvm::call_once(flag&: InitializeRegisterBankFlag, F&: InitializeRegisterBankOnce);
223}
224
225unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A,
226 const RegisterBank &B,
227 const TypeSize Size) const {
228 // What do we do with different size?
229 // copy are same size.
230 // Will introduce other hooks for different size:
231 // * extract cost.
232 // * build_sequence cost.
233
234 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
235 // FIXME: This should be deduced from the scheduling model.
236 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
237 // FMOVXDr or FMOVWSr.
238 return 5;
239 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
240 // FMOVDXr or FMOVSWr.
241 return 4;
242
243 return RegisterBankInfo::copyCost(A, B, Size);
244}
245
246const RegisterBank &
247AArch64RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
248 LLT Ty) const {
249 switch (RC.getID()) {
250 case AArch64::GPR64sponlyRegClassID:
251 return getRegBank(ID: AArch64::GPRRegBankID);
252 default:
253 return AArch64GenRegisterBankInfo::getRegBankFromRegClass(RC, Ty);
254 }
255}
256
257RegisterBankInfo::InstructionMappings
258AArch64RegisterBankInfo::getInstrAlternativeMappings(
259 const MachineInstr &MI) const {
260 const MachineFunction &MF = *MI.getParent()->getParent();
261 const TargetSubtargetInfo &STI = MF.getSubtarget();
262 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
263 const MachineRegisterInfo &MRI = MF.getRegInfo();
264
265 switch (MI.getOpcode()) {
266 case TargetOpcode::G_OR: {
267 // 32 and 64-bit or can be mapped on either FPR or
268 // GPR for the same cost.
269 TypeSize Size = getSizeInBits(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
270 if (Size != 32 && Size != 64)
271 break;
272
273 // If the instruction has any implicit-defs or uses,
274 // do not mess with it.
275 if (MI.getNumOperands() != 3)
276 break;
277 InstructionMappings AltMappings;
278 const InstructionMapping &GPRMapping = getInstructionMapping(
279 /*ID*/ 1, /*Cost*/ 1, OperandsMapping: getValueMapping(RBIdx: PMI_FirstGPR, Size),
280 /*NumOperands*/ 3);
281 const InstructionMapping &FPRMapping = getInstructionMapping(
282 /*ID*/ 2, /*Cost*/ 1, OperandsMapping: getValueMapping(RBIdx: PMI_FirstFPR, Size),
283 /*NumOperands*/ 3);
284
285 AltMappings.push_back(Elt: &GPRMapping);
286 AltMappings.push_back(Elt: &FPRMapping);
287 return AltMappings;
288 }
289 case TargetOpcode::G_BITCAST: {
290 TypeSize Size = getSizeInBits(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
291 if (Size != 32 && Size != 64)
292 break;
293
294 // If the instruction has any implicit-defs or uses,
295 // do not mess with it.
296 if (MI.getNumOperands() != 2)
297 break;
298
299 InstructionMappings AltMappings;
300 const InstructionMapping &GPRMapping = getInstructionMapping(
301 /*ID*/ 1, /*Cost*/ 1,
302 OperandsMapping: getCopyMapping(DstBankID: AArch64::GPRRegBankID, SrcBankID: AArch64::GPRRegBankID, Size),
303 /*NumOperands*/ 2);
304 const InstructionMapping &FPRMapping = getInstructionMapping(
305 /*ID*/ 2, /*Cost*/ 1,
306 OperandsMapping: getCopyMapping(DstBankID: AArch64::FPRRegBankID, SrcBankID: AArch64::FPRRegBankID, Size),
307 /*NumOperands*/ 2);
308 const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
309 /*ID*/ 3,
310 /*Cost*/
311 copyCost(A: AArch64::GPRRegBank, B: AArch64::FPRRegBank,
312 Size: TypeSize::getFixed(ExactSize: Size)),
313 OperandsMapping: getCopyMapping(DstBankID: AArch64::FPRRegBankID, SrcBankID: AArch64::GPRRegBankID, Size),
314 /*NumOperands*/ 2);
315 const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
316 /*ID*/ 3,
317 /*Cost*/
318 copyCost(A: AArch64::GPRRegBank, B: AArch64::FPRRegBank,
319 Size: TypeSize::getFixed(ExactSize: Size)),
320 OperandsMapping: getCopyMapping(DstBankID: AArch64::GPRRegBankID, SrcBankID: AArch64::FPRRegBankID, Size),
321 /*NumOperands*/ 2);
322
323 AltMappings.push_back(Elt: &GPRMapping);
324 AltMappings.push_back(Elt: &FPRMapping);
325 AltMappings.push_back(Elt: &GPRToFPRMapping);
326 AltMappings.push_back(Elt: &FPRToGPRMapping);
327 return AltMappings;
328 }
329 case TargetOpcode::G_LOAD: {
330 TypeSize Size = getSizeInBits(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
331 if (Size != 64)
332 break;
333
334 // If the instruction has any implicit-defs or uses,
335 // do not mess with it.
336 if (MI.getNumOperands() != 2)
337 break;
338
339 InstructionMappings AltMappings;
340 const InstructionMapping &GPRMapping = getInstructionMapping(
341 /*ID*/ 1, /*Cost*/ 1,
342 OperandsMapping: getOperandsMapping(
343 OpdsMapping: {getValueMapping(RBIdx: PMI_FirstGPR, Size),
344 // Addresses are GPR 64-bit.
345 getValueMapping(RBIdx: PMI_FirstGPR, Size: TypeSize::getFixed(ExactSize: 64))}),
346 /*NumOperands*/ 2);
347 const InstructionMapping &FPRMapping = getInstructionMapping(
348 /*ID*/ 2, /*Cost*/ 1,
349 OperandsMapping: getOperandsMapping(
350 OpdsMapping: {getValueMapping(RBIdx: PMI_FirstFPR, Size),
351 // Addresses are GPR 64-bit.
352 getValueMapping(RBIdx: PMI_FirstGPR, Size: TypeSize::getFixed(ExactSize: 64))}),
353 /*NumOperands*/ 2);
354
355 AltMappings.push_back(Elt: &GPRMapping);
356 AltMappings.push_back(Elt: &FPRMapping);
357 return AltMappings;
358 }
359 default:
360 break;
361 }
362 return RegisterBankInfo::getInstrAlternativeMappings(MI);
363}
364
365static bool preferGPRForFPImm(const MachineInstr &MI,
366 const MachineRegisterInfo &MRI,
367 const AArch64Subtarget &STI) {
368 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
369 Register Dst = MI.getOperand(i: 0).getReg();
370 LLT Ty = MRI.getType(Reg: Dst);
371
372 unsigned Size = Ty.getSizeInBits();
373 if (Size != 16 && Size != 32 && Size != 64)
374 return false;
375
376 EVT VT = EVT::getFloatingPointVT(BitWidth: Size);
377 const AArch64TargetLowering *TLI = STI.getTargetLowering();
378
379 const APFloat Imm = MI.getOperand(i: 1).getFPImm()->getValueAPF();
380 const APInt ImmBits = Imm.bitcastToAPInt();
381
382 // Check if we can encode this as a movi. Note, we only have one pattern so
383 // far for movis, hence the one check.
384 if (Size == 32) {
385 uint64_t Val = APInt::getSplat(NewLen: 64, V: ImmBits).getZExtValue();
386 if (AArch64_AM::isAdvSIMDModImmType4(Imm: Val))
387 return false;
388 }
389
390 // We want to use GPR when the value cannot be encoded as the immediate value
391 // of a fmov and when it will not result in a constant pool load. As
392 // AArch64TargetLowering::isFPImmLegal is used by the instruction selector
393 // to choose whether to emit a constant pool load, negating this check will
394 // ensure it would not have become a constant pool load.
395 bool OptForSize =
396 shouldOptimizeForSize(F: &MI.getMF()->getFunction(), PSI: nullptr, BFI: nullptr);
397 bool IsLegal = TLI->isFPImmLegal(Imm, VT, ForCodeSize: OptForSize);
398 bool IsFMov = TLI->isFPImmLegalAsFMov(Imm, VT);
399 return !IsFMov && IsLegal;
400}
401
402// Some of the instructions in applyMappingImpl attempt to anyext small values.
403// It may be that these values come from a G_CONSTANT that has been expanded to
404// 32 bits and then truncated. If this is the case, we shouldn't insert an
405// anyext and should instead make use of the G_CONSTANT directly, deleting the
406// trunc if possible.
407static bool foldTruncOfI32Constant(MachineInstr &MI, unsigned OpIdx,
408 MachineRegisterInfo &MRI,
409 const AArch64RegisterBankInfo &RBI) {
410 MachineOperand &Op = MI.getOperand(i: OpIdx);
411
412 Register ScalarReg = Op.getReg();
413 MachineInstr *TruncMI = MRI.getVRegDef(Reg: ScalarReg);
414 if (!TruncMI || TruncMI->getOpcode() != TargetOpcode::G_TRUNC)
415 return false;
416
417 Register TruncSrc = TruncMI->getOperand(i: 1).getReg();
418 MachineInstr *SrcDef = MRI.getVRegDef(Reg: TruncSrc);
419 if (!SrcDef || SrcDef->getOpcode() != TargetOpcode::G_CONSTANT)
420 return false;
421
422 LLT TruncSrcTy = MRI.getType(Reg: TruncSrc);
423 if (!TruncSrcTy.isScalar() || TruncSrcTy.getSizeInBits() != 32)
424 return false;
425
426 // Avoid truncating and extending a constant, this helps with selection.
427 Op.setReg(TruncSrc);
428 MRI.setRegBank(Reg: TruncSrc, RegBank: RBI.getRegBank(ID: AArch64::GPRRegBankID));
429
430 if (MRI.use_empty(RegNo: ScalarReg))
431 TruncMI->eraseFromParent();
432
433 return true;
434}
435
436void AArch64RegisterBankInfo::applyMappingImpl(
437 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
438 MachineInstr &MI = OpdMapper.getMI();
439 MachineRegisterInfo &MRI = OpdMapper.getMRI();
440
441 switch (MI.getOpcode()) {
442 case TargetOpcode::G_CONSTANT: {
443 Register Dst = MI.getOperand(i: 0).getReg();
444 [[maybe_unused]] LLT DstTy = MRI.getType(Reg: Dst);
445 assert(MRI.getRegBank(Dst) == &AArch64::GPRRegBank && DstTy.isScalar() &&
446 DstTy.getSizeInBits() < 32 &&
447 "Expected a scalar smaller than 32 bits on a GPR.");
448 Builder.setInsertPt(MBB&: *MI.getParent(), II: std::next(x: MI.getIterator()));
449 Register ExtReg = MRI.createGenericVirtualRegister(Ty: LLT::scalar(SizeInBits: 32));
450 Builder.buildTrunc(Res: Dst, Op: ExtReg);
451
452 APInt Val = MI.getOperand(i: 1).getCImm()->getValue().zext(width: 32);
453 LLVMContext &Ctx = Builder.getMF().getFunction().getContext();
454 MI.getOperand(i: 1).setCImm(ConstantInt::get(Context&: Ctx, V: Val));
455 MI.getOperand(i: 0).setReg(ExtReg);
456 MRI.setRegBank(Reg: ExtReg, RegBank: AArch64::GPRRegBank);
457
458 return applyDefaultMapping(OpdMapper);
459 }
460 case TargetOpcode::G_FCONSTANT: {
461 Register Dst = MI.getOperand(i: 0).getReg();
462 assert(MRI.getRegBank(Dst) == &AArch64::GPRRegBank &&
463 "Expected Dst to be on a GPR.");
464 const APFloat &Imm = MI.getOperand(i: 1).getFPImm()->getValueAPF();
465 APInt Bits = Imm.bitcastToAPInt();
466 Builder.setInsertPt(MBB&: *MI.getParent(), II: MI.getIterator());
467 if (Bits.getBitWidth() < 32) {
468 Register ExtReg = MRI.createGenericVirtualRegister(Ty: LLT::scalar(SizeInBits: 32));
469 Builder.buildConstant(Res: ExtReg, Val: Bits.zext(width: 32));
470 Builder.buildTrunc(Res: Dst, Op: ExtReg);
471 MRI.setRegBank(Reg: ExtReg, RegBank: AArch64::GPRRegBank);
472 } else {
473 Builder.buildConstant(Res: Dst, Val: Bits);
474 }
475 MI.eraseFromParent();
476 return;
477 }
478 case TargetOpcode::G_STORE: {
479 Register Dst = MI.getOperand(i: 0).getReg();
480 LLT Ty = MRI.getType(Reg: Dst);
481
482 if (MRI.getRegBank(Reg: Dst) == &AArch64::GPRRegBank && Ty.isScalar() &&
483 Ty.getSizeInBits() < 32) {
484
485 if (foldTruncOfI32Constant(MI, OpIdx: 0, MRI, RBI: *this))
486 return applyDefaultMapping(OpdMapper);
487
488 Builder.setInsertPt(MBB&: *MI.getParent(), II: MI.getIterator());
489 auto Ext = Builder.buildAnyExt(Res: LLT::scalar(SizeInBits: 32), Op: Dst);
490 MI.getOperand(i: 0).setReg(Ext.getReg(Idx: 0));
491 MRI.setRegBank(Reg: Ext.getReg(Idx: 0), RegBank: AArch64::GPRRegBank);
492 }
493 return applyDefaultMapping(OpdMapper);
494 }
495 case TargetOpcode::G_LOAD: {
496 Register Dst = MI.getOperand(i: 0).getReg();
497 LLT Ty = MRI.getType(Reg: Dst);
498 if (MRI.getRegBank(Reg: Dst) == &AArch64::GPRRegBank && Ty.isScalar() &&
499 Ty.getSizeInBits() < 32) {
500 Builder.setInsertPt(MBB&: *MI.getParent(), II: std::next(x: MI.getIterator()));
501 Register ExtReg = MRI.createGenericVirtualRegister(Ty: LLT::scalar(SizeInBits: 32));
502 Builder.buildTrunc(Res: Dst, Op: ExtReg);
503 MI.getOperand(i: 0).setReg(ExtReg);
504 MRI.setRegBank(Reg: ExtReg, RegBank: AArch64::GPRRegBank);
505 }
506 [[fallthrough]];
507 }
508 case TargetOpcode::G_OR:
509 case TargetOpcode::G_BITCAST:
510 // Those ID must match getInstrAlternativeMappings.
511 assert((OpdMapper.getInstrMapping().getID() >= 1 &&
512 OpdMapper.getInstrMapping().getID() <= 4) &&
513 "Don't know how to handle that ID");
514 return applyDefaultMapping(OpdMapper);
515 case TargetOpcode::G_INSERT_VECTOR_ELT: {
516 if (foldTruncOfI32Constant(MI, OpIdx: 2, MRI, RBI: *this))
517 return applyDefaultMapping(OpdMapper);
518
519 // Extend smaller gpr operands to 32 bit.
520 Builder.setInsertPt(MBB&: *MI.getParent(), II: MI.getIterator());
521 auto Ext = Builder.buildAnyExt(Res: LLT::scalar(SizeInBits: 32), Op: MI.getOperand(i: 2).getReg());
522 MRI.setRegBank(Reg: Ext.getReg(Idx: 0), RegBank: getRegBank(ID: AArch64::GPRRegBankID));
523 MI.getOperand(i: 2).setReg(Ext.getReg(Idx: 0));
524 return applyDefaultMapping(OpdMapper);
525 }
526 case AArch64::G_DUP: {
527 if (foldTruncOfI32Constant(MI, OpIdx: 1, MRI, RBI: *this))
528 return applyDefaultMapping(OpdMapper);
529
530 // Extend smaller gpr to 32-bits
531 assert(MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() < 32 &&
532 "Expected sources smaller than 32-bits");
533 Builder.setInsertPt(MBB&: *MI.getParent(), II: MI.getIterator());
534
535 Register ConstReg =
536 Builder.buildAnyExt(Res: LLT::scalar(SizeInBits: 32), Op: MI.getOperand(i: 1).getReg())
537 .getReg(Idx: 0);
538 MRI.setRegBank(Reg: ConstReg, RegBank: getRegBank(ID: AArch64::GPRRegBankID));
539 MI.getOperand(i: 1).setReg(ConstReg);
540
541 return applyDefaultMapping(OpdMapper);
542 }
543 default:
544 llvm_unreachable("Don't know how to handle that operation");
545 }
546}
547
548const RegisterBankInfo::InstructionMapping &
549AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
550 const MachineInstr &MI) const {
551 const unsigned Opc = MI.getOpcode();
552 const MachineFunction &MF = *MI.getParent()->getParent();
553 const MachineRegisterInfo &MRI = MF.getRegInfo();
554
555 unsigned NumOperands = MI.getNumOperands();
556 assert(NumOperands <= 3 &&
557 "This code is for instructions with 3 or less operands");
558
559 LLT Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
560 TypeSize Size = Ty.getSizeInBits();
561 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
562
563 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
564
565#ifndef NDEBUG
566 // Make sure all the operands are using similar size and type.
567 // Should probably be checked by the machine verifier.
568 // This code won't catch cases where the number of lanes is
569 // different between the operands.
570 // If we want to go to that level of details, it is probably
571 // best to check that the types are the same, period.
572 // Currently, we just check that the register banks are the same
573 // for each types.
574 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
575 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
576 assert(
577 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
578 RBIdx, OpTy.getSizeInBits()) ==
579 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
580 "Operand has incompatible size");
581 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
582 (void)OpIsFPR;
583 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
584 }
585#endif // End NDEBUG.
586
587 return getInstructionMapping(ID: DefaultMappingID, Cost: 1,
588 OperandsMapping: getValueMapping(RBIdx, Size), NumOperands);
589}
590
591/// \returns true if a given intrinsic only uses and defines FPRs.
592static bool isFPIntrinsic(const MachineRegisterInfo &MRI,
593 const MachineInstr &MI) {
594 // TODO: Add more intrinsics.
595 switch (cast<GIntrinsic>(Val: MI).getIntrinsicID()) {
596 default:
597 return false;
598 case Intrinsic::aarch64_neon_uaddlv:
599 case Intrinsic::aarch64_neon_uaddv:
600 case Intrinsic::aarch64_neon_saddv:
601 case Intrinsic::aarch64_neon_umaxv:
602 case Intrinsic::aarch64_neon_smaxv:
603 case Intrinsic::aarch64_neon_uminv:
604 case Intrinsic::aarch64_neon_sminv:
605 case Intrinsic::aarch64_neon_faddv:
606 case Intrinsic::aarch64_neon_fmaxv:
607 case Intrinsic::aarch64_neon_fminv:
608 case Intrinsic::aarch64_neon_fmaxnmv:
609 case Intrinsic::aarch64_neon_fminnmv:
610 case Intrinsic::aarch64_neon_fmulx:
611 case Intrinsic::aarch64_neon_frecpe:
612 case Intrinsic::aarch64_neon_frecps:
613 case Intrinsic::aarch64_neon_frecpx:
614 case Intrinsic::aarch64_neon_frsqrte:
615 case Intrinsic::aarch64_neon_frsqrts:
616 case Intrinsic::aarch64_neon_facge:
617 case Intrinsic::aarch64_neon_facgt:
618 case Intrinsic::aarch64_neon_fabd:
619 case Intrinsic::aarch64_neon_sqrdmlah:
620 case Intrinsic::aarch64_neon_sqrdmlsh:
621 case Intrinsic::aarch64_neon_sqrdmulh:
622 case Intrinsic::aarch64_neon_sqadd:
623 case Intrinsic::aarch64_neon_sqsub:
624 case Intrinsic::aarch64_neon_srshl:
625 case Intrinsic::aarch64_neon_urshl:
626 case Intrinsic::aarch64_neon_sqshl:
627 case Intrinsic::aarch64_neon_uqshl:
628 case Intrinsic::aarch64_neon_sqrshl:
629 case Intrinsic::aarch64_neon_uqrshl:
630 case Intrinsic::aarch64_neon_ushl:
631 case Intrinsic::aarch64_neon_sshl:
632 case Intrinsic::aarch64_neon_sqshrn:
633 case Intrinsic::aarch64_neon_sqshrun:
634 case Intrinsic::aarch64_neon_sqrshrn:
635 case Intrinsic::aarch64_neon_sqrshrun:
636 case Intrinsic::aarch64_neon_uqshrn:
637 case Intrinsic::aarch64_neon_uqrshrn:
638 case Intrinsic::aarch64_crypto_sha1h:
639 case Intrinsic::aarch64_crypto_sha1c:
640 case Intrinsic::aarch64_crypto_sha1p:
641 case Intrinsic::aarch64_crypto_sha1m:
642 case Intrinsic::aarch64_sisd_fcvtxn:
643 case Intrinsic::aarch64_sisd_fabd:
644 return true;
645 case Intrinsic::aarch64_neon_saddlv: {
646 const LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 2).getReg());
647 return SrcTy.getElementType().getSizeInBits() >= 16 &&
648 SrcTy.getElementCount().getFixedValue() >= 4;
649 }
650 }
651}
652
653bool AArch64RegisterBankInfo::isPHIWithFPConstraints(
654 const MachineInstr &MI, const MachineRegisterInfo &MRI,
655 const AArch64RegisterInfo &TRI, const unsigned Depth) const {
656 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
657 return false;
658
659 return any_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
660 P: [&](const MachineInstr &UseMI) {
661 if (onlyUsesFP(MI: UseMI, MRI, TRI, Depth: Depth + 1))
662 return true;
663 return isPHIWithFPConstraints(MI: UseMI, MRI, TRI, Depth: Depth + 1);
664 });
665}
666
667bool AArch64RegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
668 const MachineRegisterInfo &MRI,
669 const AArch64RegisterInfo &TRI,
670 unsigned Depth) const {
671 unsigned Op = MI.getOpcode();
672 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI))
673 return true;
674
675 // Do we have an explicit floating point instruction?
676 if (isPreISelGenericFloatingPointOpcode(Opc: Op))
677 return true;
678
679 // No. Check if we have a copy-like instruction. If we do, then we could
680 // still be fed by floating point instructions.
681 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
682 !isPreISelGenericOptimizationHint(Opcode: Op))
683 return false;
684
685 // Check if we already know the register bank.
686 auto *RB = getRegBank(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
687 if (RB == &AArch64::FPRRegBank)
688 return true;
689 if (RB == &AArch64::GPRRegBank)
690 return false;
691
692 // We don't know anything.
693 //
694 // If we have a phi, we may be able to infer that it will be assigned a FPR
695 // based off of its inputs.
696 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
697 return false;
698
699 return any_of(Range: MI.explicit_uses(), P: [&](const MachineOperand &Op) {
700 return Op.isReg() &&
701 onlyDefinesFP(MI: *MRI.getVRegDef(Reg: Op.getReg()), MRI, TRI, Depth: Depth + 1);
702 });
703}
704
705bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
706 const MachineRegisterInfo &MRI,
707 const AArch64RegisterInfo &TRI,
708 unsigned Depth) const {
709 switch (MI.getOpcode()) {
710 case TargetOpcode::G_FPTOSI:
711 case TargetOpcode::G_FPTOUI:
712 case TargetOpcode::G_FPTOSI_SAT:
713 case TargetOpcode::G_FPTOUI_SAT:
714 case TargetOpcode::G_FCMP:
715 case TargetOpcode::G_LROUND:
716 case TargetOpcode::G_LLROUND:
717 case AArch64::G_PMULL:
718 case AArch64::G_SLI:
719 case AArch64::G_SRI:
720 return true;
721 case TargetOpcode::G_INTRINSIC:
722 switch (cast<GIntrinsic>(Val: MI).getIntrinsicID()) {
723 case Intrinsic::aarch64_neon_fcvtas:
724 case Intrinsic::aarch64_neon_fcvtau:
725 case Intrinsic::aarch64_neon_fcvtzs:
726 case Intrinsic::aarch64_neon_fcvtzu:
727 case Intrinsic::aarch64_neon_fcvtms:
728 case Intrinsic::aarch64_neon_fcvtmu:
729 case Intrinsic::aarch64_neon_fcvtns:
730 case Intrinsic::aarch64_neon_fcvtnu:
731 case Intrinsic::aarch64_neon_fcvtps:
732 case Intrinsic::aarch64_neon_fcvtpu:
733 return true;
734 default:
735 break;
736 }
737 break;
738 default:
739 break;
740 }
741 return hasFPConstraints(MI, MRI, TRI, Depth);
742}
743
744bool AArch64RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
745 const MachineRegisterInfo &MRI,
746 const AArch64RegisterInfo &TRI,
747 unsigned Depth) const {
748 switch (MI.getOpcode()) {
749 case AArch64::G_DUP:
750 case AArch64::G_SADDLP:
751 case AArch64::G_UADDLP:
752 case TargetOpcode::G_SITOFP:
753 case TargetOpcode::G_UITOFP:
754 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
755 case TargetOpcode::G_INSERT_VECTOR_ELT:
756 case TargetOpcode::G_BUILD_VECTOR:
757 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
758 case AArch64::G_SLI:
759 case AArch64::G_SRI:
760 return true;
761 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
762 switch (cast<GIntrinsic>(Val: MI).getIntrinsicID()) {
763 case Intrinsic::aarch64_neon_ld1x2:
764 case Intrinsic::aarch64_neon_ld1x3:
765 case Intrinsic::aarch64_neon_ld1x4:
766 case Intrinsic::aarch64_neon_ld2:
767 case Intrinsic::aarch64_neon_ld2lane:
768 case Intrinsic::aarch64_neon_ld2r:
769 case Intrinsic::aarch64_neon_ld3:
770 case Intrinsic::aarch64_neon_ld3lane:
771 case Intrinsic::aarch64_neon_ld3r:
772 case Intrinsic::aarch64_neon_ld4:
773 case Intrinsic::aarch64_neon_ld4lane:
774 case Intrinsic::aarch64_neon_ld4r:
775 return true;
776 default:
777 break;
778 }
779 break;
780 default:
781 break;
782 }
783 return hasFPConstraints(MI, MRI, TRI, Depth);
784}
785
786bool AArch64RegisterBankInfo::prefersFPUse(const MachineInstr &MI,
787 const MachineRegisterInfo &MRI,
788 const AArch64RegisterInfo &TRI,
789 unsigned Depth) const {
790 switch (MI.getOpcode()) {
791 case TargetOpcode::G_SITOFP:
792 case TargetOpcode::G_UITOFP:
793 return MRI.getType(Reg: MI.getOperand(i: 0).getReg()).getSizeInBits() ==
794 MRI.getType(Reg: MI.getOperand(i: 1).getReg()).getSizeInBits();
795 }
796 return onlyDefinesFP(MI, MRI, TRI, Depth);
797}
798
799bool AArch64RegisterBankInfo::isLoadFromFPType(const MachineInstr &MI) const {
800 // GMemOperation because we also want to match indexed loads.
801 auto *MemOp = cast<GMemOperation>(Val: &MI);
802 const Value *LdVal = MemOp->getMMO().getValue();
803 if (!LdVal)
804 return false;
805
806 Type *EltTy = nullptr;
807 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Val: LdVal)) {
808 EltTy = GV->getValueType();
809 // Look at the first element of the struct to determine the type we are
810 // loading
811 while (StructType *StructEltTy = dyn_cast<StructType>(Val: EltTy)) {
812 if (StructEltTy->getNumElements() == 0)
813 break;
814 EltTy = StructEltTy->getTypeAtIndex(N: 0U);
815 }
816 // Look at the first element of the array to determine its type
817 if (isa<ArrayType>(Val: EltTy))
818 EltTy = EltTy->getArrayElementType();
819 } else if (!isa<Constant>(Val: LdVal)) {
820 // FIXME: grubbing around uses is pretty ugly, but with no more
821 // `getPointerElementType` there's not much else we can do.
822 for (const auto *LdUser : LdVal->users()) {
823 if (isa<LoadInst>(Val: LdUser)) {
824 EltTy = LdUser->getType();
825 break;
826 }
827 if (isa<StoreInst>(Val: LdUser) && LdUser->getOperand(i: 1) == LdVal) {
828 EltTy = LdUser->getOperand(i: 0)->getType();
829 break;
830 }
831 }
832 }
833 return EltTy && EltTy->isFPOrFPVectorTy();
834}
835
836const RegisterBankInfo::InstructionMapping &
837AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
838 const unsigned Opc = MI.getOpcode();
839
840 // Try the default logic for non-generic instructions that are either copies
841 // or already have some operands assigned to banks.
842 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opcode: Opc)) ||
843 Opc == TargetOpcode::G_PHI) {
844 const RegisterBankInfo::InstructionMapping &Mapping =
845 getInstrMappingImpl(MI);
846 if (Mapping.isValid())
847 return Mapping;
848 }
849
850 const MachineFunction &MF = *MI.getParent()->getParent();
851 const MachineRegisterInfo &MRI = MF.getRegInfo();
852 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
853 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
854
855 switch (Opc) {
856 // G_{F|S|U}REM are not listed because they are not legal.
857 // Arithmetic ops.
858 case TargetOpcode::G_ADD:
859 case TargetOpcode::G_SUB:
860 case TargetOpcode::G_PTR_ADD:
861 case TargetOpcode::G_MUL:
862 case TargetOpcode::G_SDIV:
863 case TargetOpcode::G_UDIV:
864 // Bitwise ops.
865 case TargetOpcode::G_AND:
866 case TargetOpcode::G_OR:
867 case TargetOpcode::G_XOR:
868 // Floating point ops.
869 case TargetOpcode::G_FADD:
870 case TargetOpcode::G_FSUB:
871 case TargetOpcode::G_FMUL:
872 case TargetOpcode::G_FDIV:
873 case TargetOpcode::G_FMAXIMUM:
874 case TargetOpcode::G_FMINIMUM:
875 return getSameKindOfOperandsMapping(MI);
876 case TargetOpcode::G_FPEXT: {
877 LLT DstTy = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
878 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg());
879 return getInstructionMapping(
880 ID: DefaultMappingID, /*Cost*/ 1,
881 OperandsMapping: getFPExtMapping(DstSize: DstTy.getSizeInBits(), SrcSize: SrcTy.getSizeInBits()),
882 /*NumOperands*/ 2);
883 }
884 // Shifts.
885 case TargetOpcode::G_SHL:
886 case TargetOpcode::G_LSHR:
887 case TargetOpcode::G_ASHR: {
888 LLT ShiftAmtTy = MRI.getType(Reg: MI.getOperand(i: 2).getReg());
889 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg());
890 if (ShiftAmtTy.getSizeInBits() == 64 && SrcTy.getSizeInBits() == 32)
891 return getInstructionMapping(ID: DefaultMappingID, Cost: 1,
892 OperandsMapping: &ValMappings[Shift64Imm], NumOperands: 3);
893 return getSameKindOfOperandsMapping(MI);
894 }
895 case TargetOpcode::COPY: {
896 Register DstReg = MI.getOperand(i: 0).getReg();
897 Register SrcReg = MI.getOperand(i: 1).getReg();
898 // Check if one of the register is not a generic register.
899 if ((DstReg.isPhysical() || !MRI.getType(Reg: DstReg).isValid()) ||
900 (SrcReg.isPhysical() || !MRI.getType(Reg: SrcReg).isValid())) {
901 const RegisterBank *DstRB = getRegBank(Reg: DstReg, MRI, TRI);
902 const RegisterBank *SrcRB = getRegBank(Reg: SrcReg, MRI, TRI);
903 if (!DstRB)
904 DstRB = SrcRB;
905 else if (!SrcRB)
906 SrcRB = DstRB;
907 // If both RB are null that means both registers are generic.
908 // We shouldn't be here.
909 assert(DstRB && SrcRB && "Both RegBank were nullptr");
910 TypeSize Size = getSizeInBits(Reg: DstReg, MRI, TRI);
911 return getInstructionMapping(
912 ID: DefaultMappingID, Cost: copyCost(A: *DstRB, B: *SrcRB, Size),
913 OperandsMapping: getCopyMapping(DstBankID: DstRB->getID(), SrcBankID: SrcRB->getID(), Size),
914 // We only care about the mapping of the destination.
915 /*NumOperands*/ 1);
916 }
917 // Both registers are generic, use G_BITCAST.
918 [[fallthrough]];
919 }
920 case TargetOpcode::G_BITCAST: {
921 LLT DstTy = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
922 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg());
923 TypeSize Size = DstTy.getSizeInBits();
924 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
925 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
926 const RegisterBank &DstRB =
927 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
928 const RegisterBank &SrcRB =
929 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
930 return getInstructionMapping(
931 ID: DefaultMappingID, Cost: copyCost(A: DstRB, B: SrcRB, Size),
932 OperandsMapping: getCopyMapping(DstBankID: DstRB.getID(), SrcBankID: SrcRB.getID(), Size),
933 // We only care about the mapping of the destination for COPY.
934 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
935 }
936 default:
937 break;
938 }
939
940 unsigned NumOperands = MI.getNumOperands();
941 unsigned MappingID = DefaultMappingID;
942
943 // Track the size and bank of each register. We don't do partial mappings.
944 SmallVector<unsigned, 4> OpSize(NumOperands);
945 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
946 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
947 auto &MO = MI.getOperand(i: Idx);
948 if (!MO.isReg() || !MO.getReg())
949 continue;
950
951 LLT Ty = MRI.getType(Reg: MO.getReg());
952 if (!Ty.isValid())
953 continue;
954 OpSize[Idx] = Ty.getSizeInBits().getKnownMinValue();
955
956 // As a top-level guess, vectors including both scalable and non-scalable
957 // ones go in FPRs, scalars and pointers in GPRs.
958 // For floating-point instructions, scalars go in FPRs.
959 if (Ty.isVector())
960 OpRegBankIdx[Idx] = PMI_FirstFPR;
961 else if (isPreISelGenericFloatingPointOpcode(Opc) ||
962 (MO.isDef() && onlyDefinesFP(MI, MRI, TRI)) ||
963 (MO.isUse() && onlyUsesFP(MI, MRI, TRI)) ||
964 Ty.getSizeInBits() > 64)
965 OpRegBankIdx[Idx] = PMI_FirstFPR;
966 else
967 OpRegBankIdx[Idx] = PMI_FirstGPR;
968 }
969
970 unsigned Cost = 1;
971 // Some of the floating-point instructions have mixed GPR and FPR operands:
972 // fine-tune the computed mapping.
973 switch (Opc) {
974 case TargetOpcode::G_CONSTANT: {
975 Register Dst = MI.getOperand(i: 0).getReg();
976 LLT DstTy = MRI.getType(Reg: Dst);
977 if (DstTy.isScalar() && DstTy.getSizeInBits() < 32)
978 MappingID = CustomMappingID;
979 break;
980 }
981 case TargetOpcode::G_FCONSTANT: {
982 if (preferGPRForFPImm(MI, MRI, STI)) {
983 // Materialize in GPR and rely on later bank copies for FP uses.
984 MappingID = CustomMappingID;
985 OpRegBankIdx = {PMI_FirstGPR};
986 }
987 break;
988 }
989 case AArch64::G_DUP: {
990 Register ScalarReg = MI.getOperand(i: 1).getReg();
991 LLT ScalarTy = MRI.getType(Reg: ScalarReg);
992 auto ScalarDef = MRI.getVRegDef(Reg: ScalarReg);
993 // We want to select dup(load) into LD1R.
994 if (ScalarDef->getOpcode() == TargetOpcode::G_LOAD)
995 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
996 // s8 is an exception for G_DUP, which we always want on gpr.
997 else if (ScalarTy.getSizeInBits() != 8 &&
998 (getRegBank(Reg: ScalarReg, MRI, TRI) == &AArch64::FPRRegBank ||
999 onlyDefinesFP(MI: *ScalarDef, MRI, TRI)))
1000 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1001 else {
1002 if (ScalarTy.getSizeInBits() < 32 &&
1003 getRegBank(Reg: ScalarReg, MRI, TRI) == &AArch64::GPRRegBank) {
1004 // Calls applyMappingImpl()
1005 MappingID = CustomMappingID;
1006 }
1007 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
1008 }
1009 break;
1010 }
1011 case TargetOpcode::G_TRUNC: {
1012 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg());
1013 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128)
1014 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1015 break;
1016 }
1017 case TargetOpcode::G_SITOFP:
1018 case TargetOpcode::G_UITOFP: {
1019 if (MRI.getType(Reg: MI.getOperand(i: 0).getReg()).isVector())
1020 break;
1021 // Integer to FP conversions don't necessarily happen between GPR -> FPR
1022 // regbanks. They can also be done within an FPR register.
1023 Register SrcReg = MI.getOperand(i: 1).getReg();
1024 if (getRegBank(Reg: SrcReg, MRI, TRI) == &AArch64::FPRRegBank &&
1025 MRI.getType(Reg: SrcReg).getSizeInBits() ==
1026 MRI.getType(Reg: MI.getOperand(i: 0).getReg()).getSizeInBits())
1027 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1028 else
1029 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
1030 break;
1031 }
1032 case TargetOpcode::G_FPTOSI_SAT:
1033 case TargetOpcode::G_FPTOUI_SAT:
1034 case TargetOpcode::G_FPTOSI:
1035 case TargetOpcode::G_FPTOUI:
1036 case TargetOpcode::G_INTRINSIC_LRINT:
1037 case TargetOpcode::G_INTRINSIC_LLRINT:
1038 case TargetOpcode::G_LROUND:
1039 case TargetOpcode::G_LLROUND: {
1040 LLT DstType = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
1041 if (DstType.isVector())
1042 break;
1043 if (DstType == LLT::scalar(SizeInBits: 16)) {
1044 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1045 break;
1046 }
1047 TypeSize DstSize = getSizeInBits(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
1048 TypeSize SrcSize = getSizeInBits(Reg: MI.getOperand(i: 1).getReg(), MRI, TRI);
1049 if (((DstSize == SrcSize) || STI.hasFeature(Feature: AArch64::FeatureFPRCVT)) &&
1050 all_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
1051 P: [&](const MachineInstr &UseMI) {
1052 return onlyUsesFP(MI: UseMI, MRI, TRI) ||
1053 prefersFPUse(MI: UseMI, MRI, TRI);
1054 }))
1055 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1056 else
1057 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
1058 break;
1059 }
1060 case TargetOpcode::G_FCMP: {
1061 // If the result is a vector, it must use a FPR.
1062 AArch64GenRegisterBankInfo::PartialMappingIdx Idx0 =
1063 MRI.getType(Reg: MI.getOperand(i: 0).getReg()).isVector() ? PMI_FirstFPR
1064 : PMI_FirstGPR;
1065 OpRegBankIdx = {Idx0,
1066 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
1067 break;
1068 }
1069 case TargetOpcode::G_BITCAST:
1070 // This is going to be a cross register bank copy and this is expensive.
1071 if (OpRegBankIdx[0] != OpRegBankIdx[1])
1072 Cost = copyCost(
1073 A: *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
1074 B: *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
1075 Size: TypeSize::getFixed(ExactSize: OpSize[0]));
1076 break;
1077 case TargetOpcode::G_LOAD: {
1078 // Loading in vector unit is slightly more expensive.
1079 // This is actually only true for the LD1R and co instructions,
1080 // but anyway for the fast mode this number does not matter and
1081 // for the greedy mode the cost of the cross bank copy will
1082 // offset this number.
1083 // FIXME: Should be derived from the scheduling model.
1084 if (OpRegBankIdx[0] != PMI_FirstGPR) {
1085 Cost = 2;
1086 break;
1087 }
1088
1089 if (cast<GLoad>(Val: MI).isAtomic()) {
1090 // Atomics always use GPR destinations. Don't refine any further.
1091 OpRegBankIdx[0] = PMI_FirstGPR;
1092 if (MRI.getType(Reg: MI.getOperand(i: 0).getReg()).getSizeInBits() < 32)
1093 MappingID = CustomMappingID;
1094 break;
1095 }
1096
1097 // Try to guess the type of the load from the MMO.
1098 if (isLoadFromFPType(MI)) {
1099 OpRegBankIdx[0] = PMI_FirstFPR;
1100 break;
1101 }
1102
1103 // Check if that load feeds fp instructions.
1104 // In that case, we want the default mapping to be on FPR
1105 // instead of blind map every scalar to GPR.
1106 if (any_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
1107 P: [&](const MachineInstr &UseMI) {
1108 // If we have at least one direct or indirect use
1109 // in a FP instruction,
1110 // assume this was a floating point load in the IR. If it was
1111 // not, we would have had a bitcast before reaching that
1112 // instruction.
1113 //
1114 // Int->FP conversion operations are also captured in
1115 // prefersFPUse().
1116
1117 if (isPHIWithFPConstraints(MI: UseMI, MRI, TRI))
1118 return true;
1119
1120 return onlyUsesFP(MI: UseMI, MRI, TRI) ||
1121 prefersFPUse(MI: UseMI, MRI, TRI);
1122 }))
1123 OpRegBankIdx[0] = PMI_FirstFPR;
1124
1125 // On GPR, extend any load < 32bits to 32bit.
1126 LLT Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
1127 if (Ty.isScalar() && Ty.getSizeInBits() < 32)
1128 MappingID = CustomMappingID;
1129 break;
1130 }
1131 case TargetOpcode::G_STORE:
1132 // Check if that store is fed by fp instructions.
1133 if (OpRegBankIdx[0] == PMI_FirstGPR) {
1134 Register VReg = MI.getOperand(i: 0).getReg();
1135 if (VReg) {
1136 MachineInstr *DefMI = MRI.getVRegDef(Reg: VReg);
1137 if (onlyDefinesFP(MI: *DefMI, MRI, TRI)) {
1138 OpRegBankIdx[0] = PMI_FirstFPR;
1139 break;
1140 }
1141 }
1142
1143 // On GPR, extend any store < 32bits to 32bit.
1144 LLT Ty = MRI.getType(Reg: MI.getOperand(i: 0).getReg());
1145 if (Ty.isScalar() && Ty.getSizeInBits() < 32)
1146 MappingID = CustomMappingID;
1147 }
1148 break;
1149 case TargetOpcode::G_INDEXED_STORE:
1150 if (OpRegBankIdx[1] == PMI_FirstGPR) {
1151 Register VReg = MI.getOperand(i: 1).getReg();
1152 if (!VReg)
1153 break;
1154 MachineInstr *DefMI = MRI.getVRegDef(Reg: VReg);
1155 if (onlyDefinesFP(MI: *DefMI, MRI, TRI))
1156 OpRegBankIdx[1] = PMI_FirstFPR;
1157 break;
1158 }
1159 break;
1160 case TargetOpcode::G_INDEXED_SEXTLOAD:
1161 case TargetOpcode::G_INDEXED_ZEXTLOAD:
1162 // These should always be GPR.
1163 OpRegBankIdx[0] = PMI_FirstGPR;
1164 break;
1165 case TargetOpcode::G_INDEXED_LOAD: {
1166 if (isLoadFromFPType(MI))
1167 OpRegBankIdx[0] = PMI_FirstFPR;
1168 break;
1169 }
1170 case TargetOpcode::G_SELECT: {
1171 // If the destination is FPR, preserve that.
1172 if (OpRegBankIdx[0] != PMI_FirstGPR)
1173 break;
1174
1175 // If we're taking in vectors, we have no choice but to put everything on
1176 // FPRs, except for the condition. The condition must always be on a GPR.
1177 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 2).getReg());
1178 if (SrcTy.isVector()) {
1179 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR};
1180 break;
1181 }
1182
1183 // Try to minimize the number of copies. If we have more floating point
1184 // constrained values than not, then we'll put everything on FPR. Otherwise,
1185 // everything has to be on GPR.
1186 unsigned NumFP = 0;
1187
1188 // Check if the uses of the result always produce floating point values.
1189 //
1190 // For example:
1191 //
1192 // %z = G_SELECT %cond %x %y
1193 // fpr = G_FOO %z ...
1194 if (any_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
1195 P: [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); }))
1196 ++NumFP;
1197
1198 // Check if the defs of the source values always produce floating point
1199 // values.
1200 //
1201 // For example:
1202 //
1203 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
1204 // %z = G_SELECT %cond %x %y
1205 //
1206 // Also check whether or not the sources have already been decided to be
1207 // FPR. Keep track of this.
1208 //
1209 // This doesn't check the condition, since it's just whatever is in NZCV.
1210 // This isn't passed explicitly in a register to fcsel/csel.
1211 for (unsigned Idx = 2; Idx < 4; ++Idx) {
1212 Register VReg = MI.getOperand(i: Idx).getReg();
1213 MachineInstr *DefMI = MRI.getVRegDef(Reg: VReg);
1214 if (getRegBank(Reg: VReg, MRI, TRI) == &AArch64::FPRRegBank ||
1215 onlyDefinesFP(MI: *DefMI, MRI, TRI))
1216 ++NumFP;
1217 }
1218
1219 // If we have more FP constraints than not, then move everything over to
1220 // FPR.
1221 if (NumFP >= 2)
1222 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR};
1223
1224 break;
1225 }
1226 case TargetOpcode::G_UNMERGE_VALUES: {
1227 // If the first operand belongs to a FPR register bank, then make sure that
1228 // we preserve that.
1229 if (OpRegBankIdx[0] != PMI_FirstGPR)
1230 break;
1231
1232 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: MI.getNumOperands()-1).getReg());
1233 // UNMERGE into scalars from a vector should always use FPR.
1234 // Likewise if any of the uses are FP instructions.
1235 if (SrcTy.isVector() || SrcTy == LLT::scalar(SizeInBits: 128) ||
1236 any_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
1237 P: [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) {
1238 // Set the register bank of every operand to FPR.
1239 for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
1240 Idx < NumOperands; ++Idx)
1241 OpRegBankIdx[Idx] = PMI_FirstFPR;
1242 }
1243 break;
1244 }
1245 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
1246 // Destination and source need to be FPRs.
1247 OpRegBankIdx[0] = PMI_FirstFPR;
1248 OpRegBankIdx[1] = PMI_FirstFPR;
1249
1250 // Index needs to be a GPR.
1251 OpRegBankIdx[2] = PMI_FirstGPR;
1252 break;
1253 case AArch64::G_SQSHLU_I:
1254 // Destination and source need to be FPRs.
1255 OpRegBankIdx[0] = PMI_FirstFPR;
1256 OpRegBankIdx[1] = PMI_FirstFPR;
1257
1258 // Shift Index needs to be a GPR.
1259 OpRegBankIdx[2] = PMI_FirstGPR;
1260 break;
1261
1262 case TargetOpcode::G_INSERT_VECTOR_ELT:
1263 OpRegBankIdx[0] = PMI_FirstFPR;
1264 OpRegBankIdx[1] = PMI_FirstFPR;
1265
1266 // The element may be either a GPR or FPR. Preserve that behaviour.
1267 if (getRegBank(Reg: MI.getOperand(i: 2).getReg(), MRI, TRI) == &AArch64::FPRRegBank)
1268 OpRegBankIdx[2] = PMI_FirstFPR;
1269 else {
1270 // If the type is i8/i16, and the regank will be GPR, then we change the
1271 // type to i32 in applyMappingImpl.
1272 LLT Ty = MRI.getType(Reg: MI.getOperand(i: 2).getReg());
1273 if (Ty.getSizeInBits() == 8 || Ty.getSizeInBits() == 16) {
1274 // Calls applyMappingImpl()
1275 MappingID = CustomMappingID;
1276 }
1277 OpRegBankIdx[2] = PMI_FirstGPR;
1278 }
1279
1280 // Index needs to be a GPR.
1281 OpRegBankIdx[3] = PMI_FirstGPR;
1282 break;
1283 case TargetOpcode::G_EXTRACT: {
1284 // For s128 sources we have to use fpr unless we know otherwise.
1285 auto Src = MI.getOperand(i: 1).getReg();
1286 LLT SrcTy = MRI.getType(Reg: MI.getOperand(i: 1).getReg());
1287 if (SrcTy.getSizeInBits() != 128)
1288 break;
1289 auto Idx = MRI.getRegClassOrNull(Reg: Src) == &AArch64::XSeqPairsClassRegClass
1290 ? PMI_FirstGPR
1291 : PMI_FirstFPR;
1292 OpRegBankIdx[0] = Idx;
1293 OpRegBankIdx[1] = Idx;
1294 break;
1295 }
1296 case TargetOpcode::G_BUILD_VECTOR: {
1297 // If the first source operand belongs to a FPR register bank, then make
1298 // sure that we preserve that.
1299 if (OpRegBankIdx[1] != PMI_FirstGPR)
1300 break;
1301 Register VReg = MI.getOperand(i: 1).getReg();
1302 if (!VReg)
1303 break;
1304
1305 // Get the instruction that defined the source operand reg, and check if
1306 // it's a floating point operation. Or, if it's a type like s16 which
1307 // doesn't have a exact size gpr register class. The exception is if the
1308 // build_vector has all constant operands, which may be better to leave as
1309 // gpr without copies, so it can be matched in imported patterns.
1310 MachineInstr *DefMI = MRI.getVRegDef(Reg: VReg);
1311 unsigned DefOpc = DefMI->getOpcode();
1312 const LLT SrcTy = MRI.getType(Reg: VReg);
1313 if (all_of(Range: MI.operands(), P: [&](const MachineOperand &Op) {
1314 return Op.isDef() || MRI.getVRegDef(Reg: Op.getReg())->getOpcode() ==
1315 TargetOpcode::G_CONSTANT;
1316 }))
1317 break;
1318 if (isPreISelGenericFloatingPointOpcode(Opc: DefOpc) ||
1319 SrcTy.getSizeInBits() < 32 ||
1320 getRegBank(Reg: VReg, MRI, TRI) == &AArch64::FPRRegBank) {
1321 // Have a floating point op.
1322 // Make sure every operand gets mapped to a FPR register class.
1323 unsigned NumOperands = MI.getNumOperands();
1324 for (unsigned Idx = 0; Idx < NumOperands; ++Idx)
1325 OpRegBankIdx[Idx] = PMI_FirstFPR;
1326 }
1327 break;
1328 }
1329 case TargetOpcode::G_VECREDUCE_FADD:
1330 case TargetOpcode::G_VECREDUCE_FMUL:
1331 case TargetOpcode::G_VECREDUCE_FMAX:
1332 case TargetOpcode::G_VECREDUCE_FMIN:
1333 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
1334 case TargetOpcode::G_VECREDUCE_FMINIMUM:
1335 case TargetOpcode::G_VECREDUCE_ADD:
1336 case TargetOpcode::G_VECREDUCE_MUL:
1337 case TargetOpcode::G_VECREDUCE_AND:
1338 case TargetOpcode::G_VECREDUCE_OR:
1339 case TargetOpcode::G_VECREDUCE_XOR:
1340 case TargetOpcode::G_VECREDUCE_SMAX:
1341 case TargetOpcode::G_VECREDUCE_SMIN:
1342 case TargetOpcode::G_VECREDUCE_UMAX:
1343 case TargetOpcode::G_VECREDUCE_UMIN:
1344 // Reductions produce a scalar value from a vector, the scalar should be on
1345 // FPR bank.
1346 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1347 break;
1348 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
1349 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
1350 // These reductions also take a scalar accumulator input.
1351 // Assign them FPR for now.
1352 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR, PMI_FirstFPR};
1353 break;
1354 case TargetOpcode::G_INTRINSIC:
1355 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
1356 switch (cast<GIntrinsic>(Val: MI).getIntrinsicID()) {
1357 case Intrinsic::aarch64_neon_fcvtas:
1358 case Intrinsic::aarch64_neon_fcvtau:
1359 case Intrinsic::aarch64_neon_fcvtzs:
1360 case Intrinsic::aarch64_neon_fcvtzu:
1361 case Intrinsic::aarch64_neon_fcvtms:
1362 case Intrinsic::aarch64_neon_fcvtmu:
1363 case Intrinsic::aarch64_neon_fcvtns:
1364 case Intrinsic::aarch64_neon_fcvtnu:
1365 case Intrinsic::aarch64_neon_fcvtps:
1366 case Intrinsic::aarch64_neon_fcvtpu: {
1367 OpRegBankIdx[2] = PMI_FirstFPR;
1368 if (MRI.getType(Reg: MI.getOperand(i: 0).getReg()).isVector()) {
1369 OpRegBankIdx[0] = PMI_FirstFPR;
1370 break;
1371 }
1372 TypeSize DstSize = getSizeInBits(Reg: MI.getOperand(i: 0).getReg(), MRI, TRI);
1373 TypeSize SrcSize = getSizeInBits(Reg: MI.getOperand(i: 2).getReg(), MRI, TRI);
1374 // Fp conversions to i16 must be kept on fp register banks to ensure
1375 // proper saturation, as there are no 16-bit gprs.
1376 // In addition, conversion intrinsics have fpr output when the input
1377 // size matches the output size, or FPRCVT is present.
1378 if (DstSize == 16 ||
1379 ((DstSize == SrcSize || STI.hasFeature(Feature: AArch64::FeatureFPRCVT)) &&
1380 all_of(Range: MRI.use_nodbg_instructions(Reg: MI.getOperand(i: 0).getReg()),
1381 P: [&](const MachineInstr &UseMI) {
1382 return onlyUsesFP(MI: UseMI, MRI, TRI) ||
1383 prefersFPUse(MI: UseMI, MRI, TRI);
1384 })))
1385 OpRegBankIdx[0] = PMI_FirstFPR;
1386 else
1387 OpRegBankIdx[0] = PMI_FirstGPR;
1388 break;
1389 }
1390 case Intrinsic::aarch64_neon_vcvtfxs2fp:
1391 case Intrinsic::aarch64_neon_vcvtfxu2fp:
1392 case Intrinsic::aarch64_neon_vcvtfp2fxs:
1393 case Intrinsic::aarch64_neon_vcvtfp2fxu:
1394 // Override these intrinsics, because they would have a partial
1395 // mapping. This is needed for 'half' types, which otherwise don't
1396 // get legalised correctly.
1397 OpRegBankIdx[0] = PMI_FirstFPR;
1398 OpRegBankIdx[2] = PMI_FirstFPR;
1399 // OpRegBankIdx[1] is the intrinsic ID.
1400 // OpRegBankIdx[3] is an integer immediate.
1401 break;
1402 default: {
1403 // Check if we know that the intrinsic has any constraints on its register
1404 // banks. If it does, then update the mapping accordingly.
1405 unsigned Idx = 0;
1406 if (onlyDefinesFP(MI, MRI, TRI))
1407 for (const auto &Op : MI.defs()) {
1408 if (Op.isReg())
1409 OpRegBankIdx[Idx] = PMI_FirstFPR;
1410 ++Idx;
1411 }
1412 else
1413 Idx += MI.getNumExplicitDefs();
1414
1415 if (onlyUsesFP(MI, MRI, TRI))
1416 for (const auto &Op : MI.explicit_uses()) {
1417 if (Op.isReg())
1418 OpRegBankIdx[Idx] = PMI_FirstFPR;
1419 ++Idx;
1420 }
1421 break;
1422 }
1423 }
1424 break;
1425 }
1426 }
1427
1428 // Finally construct the computed mapping.
1429 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
1430 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
1431 if (MI.getOperand(i: Idx).isReg() && MI.getOperand(i: Idx).getReg()) {
1432 LLT Ty = MRI.getType(Reg: MI.getOperand(i: Idx).getReg());
1433 if (!Ty.isValid())
1434 continue;
1435 auto Mapping =
1436 getValueMapping(RBIdx: OpRegBankIdx[Idx], Size: TypeSize::getFixed(ExactSize: OpSize[Idx]));
1437 if (!Mapping->isValid())
1438 return getInvalidInstructionMapping();
1439
1440 OpdsMapping[Idx] = Mapping;
1441 }
1442 }
1443
1444 return getInstructionMapping(ID: MappingID, Cost, OperandsMapping: getOperandsMapping(OpdsMapping),
1445 NumOperands);
1446}
1447