[Clang] ensure mangled names are valid identifiers before being suggested in ifunc...
[llvm-project.git] / llvm / lib / Target / AArch64 / GISel / AArch64RegisterBankInfo.cpp
blobd9c558819db3d4086a2cc14b6a95117e962cbfdd
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 //===----------------------------------------------------------------------===//
14 #include "AArch64RegisterBankInfo.h"
15 #include "AArch64RegisterInfo.h"
16 #include "MCTargetDesc/AArch64MCTargetDesc.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
20 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21 #include "llvm/CodeGen/GlobalISel/Utils.h"
22 #include "llvm/CodeGen/LowLevelTypeUtils.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineInstr.h"
25 #include "llvm/CodeGen/MachineOperand.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/RegisterBank.h"
28 #include "llvm/CodeGen/RegisterBankInfo.h"
29 #include "llvm/CodeGen/TargetOpcodes.h"
30 #include "llvm/CodeGen/TargetRegisterInfo.h"
31 #include "llvm/CodeGen/TargetSubtargetInfo.h"
32 #include "llvm/IR/IntrinsicsAArch64.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/Threading.h"
35 #include <cassert>
37 #define GET_TARGET_REGBANK_IMPL
38 #include "AArch64GenRegisterBank.inc"
40 // This file will be TableGen'ed at some point.
41 #include "AArch64GenRegisterBankInfo.def"
43 using namespace llvm;
44 static const unsigned CustomMappingID = 1;
46 AArch64RegisterBankInfo::AArch64RegisterBankInfo(
47 const TargetRegisterInfo &TRI) {
48 static llvm::once_flag InitializeRegisterBankFlag;
50 static auto InitializeRegisterBankOnce = [&]() {
51 // We have only one set of register banks, whatever the subtarget
52 // is. Therefore, the initialization of the RegBanks table should be
53 // done only once. Indeed the table of all register banks
54 // (AArch64::RegBanks) is unique in the compiler. At some point, it
55 // will get tablegen'ed and the whole constructor becomes empty.
57 const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
58 (void)RBGPR;
59 assert(&AArch64::GPRRegBank == &RBGPR &&
60 "The order in RegBanks is messed up");
62 const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
63 (void)RBFPR;
64 assert(&AArch64::FPRRegBank == &RBFPR &&
65 "The order in RegBanks is messed up");
67 const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID);
68 (void)RBCCR;
69 assert(&AArch64::CCRegBank == &RBCCR &&
70 "The order in RegBanks is messed up");
72 // The GPR register bank is fully defined by all the registers in
73 // GR64all + its subclasses.
74 assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
75 "Subclass not added?");
76 assert(getMaximumSize(RBGPR.getID()) == 128 &&
77 "GPRs should hold up to 128-bit");
79 // The FPR register bank is fully defined by all the registers in
80 // GR64all + its subclasses.
81 assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
82 "Subclass not added?");
83 assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
84 "Subclass not added?");
85 assert(getMaximumSize(RBFPR.getID()) == 512 &&
86 "FPRs should hold up to 512-bit via QQQQ sequence");
88 assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
89 "Class not added?");
90 assert(getMaximumSize(RBCCR.getID()) == 32 &&
91 "CCR should hold up to 32-bit");
93 // Check that the TableGen'ed like file is in sync we our expectations.
94 // First, the Idx.
95 assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR,
96 {PMI_GPR32, PMI_GPR64, PMI_GPR128}) &&
97 "PartialMappingIdx's are incorrectly ordered");
98 assert(checkPartialMappingIdx(PMI_FirstFPR, PMI_LastFPR,
99 {PMI_FPR16, PMI_FPR32, PMI_FPR64, PMI_FPR128,
100 PMI_FPR256, PMI_FPR512}) &&
101 "PartialMappingIdx's are incorrectly ordered");
102 // Now, the content.
103 // Check partial mapping.
104 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
105 do { \
106 assert( \
107 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
108 #Idx " is incorrectly initialized"); \
109 } while (false)
111 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
112 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
113 CHECK_PARTIALMAP(PMI_GPR128, 0, 128, RBGPR);
114 CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR);
115 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
116 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
117 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
118 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
119 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
121 // Check value mapping.
122 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
123 do { \
124 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
125 PartialMappingIdx::PMI_First##RBName, Size, \
126 Offset) && \
127 #RBName #Size " " #Offset " is incorrectly initialized"); \
128 } while (false)
130 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
132 CHECK_VALUEMAP(GPR, 32);
133 CHECK_VALUEMAP(GPR, 64);
134 CHECK_VALUEMAP(GPR, 128);
135 CHECK_VALUEMAP(FPR, 16);
136 CHECK_VALUEMAP(FPR, 32);
137 CHECK_VALUEMAP(FPR, 64);
138 CHECK_VALUEMAP(FPR, 128);
139 CHECK_VALUEMAP(FPR, 256);
140 CHECK_VALUEMAP(FPR, 512);
142 // Check the value mapping for 3-operands instructions where all the operands
143 // map to the same value mapping.
144 #define CHECK_VALUEMAP_3OPS(RBName, Size) \
145 do { \
146 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
147 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
148 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
149 } while (false)
151 CHECK_VALUEMAP_3OPS(GPR, 32);
152 CHECK_VALUEMAP_3OPS(GPR, 64);
153 CHECK_VALUEMAP_3OPS(GPR, 128);
154 CHECK_VALUEMAP_3OPS(FPR, 32);
155 CHECK_VALUEMAP_3OPS(FPR, 64);
156 CHECK_VALUEMAP_3OPS(FPR, 128);
157 CHECK_VALUEMAP_3OPS(FPR, 256);
158 CHECK_VALUEMAP_3OPS(FPR, 512);
160 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
161 do { \
162 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
163 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
164 (void)PartialMapDstIdx; \
165 (void)PartialMapSrcIdx; \
166 const ValueMapping *Map = getCopyMapping(AArch64::RBNameDst##RegBankID, \
167 AArch64::RBNameSrc##RegBankID, \
168 TypeSize::getFixed(Size)); \
169 (void)Map; \
170 assert(Map[0].BreakDown == \
171 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
172 Map[0].NumBreakDowns == 1 && \
173 #RBNameDst #Size " Dst is incorrectly initialized"); \
174 assert(Map[1].BreakDown == \
175 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
176 Map[1].NumBreakDowns == 1 && \
177 #RBNameSrc #Size " Src is incorrectly initialized"); \
179 } while (false)
181 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
182 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32);
183 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
184 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64);
185 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32);
186 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32);
187 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
188 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
190 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
191 do { \
192 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
193 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
194 (void)PartialMapDstIdx; \
195 (void)PartialMapSrcIdx; \
196 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
197 (void)Map; \
198 assert(Map[0].BreakDown == \
199 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
200 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
201 " Dst is incorrectly initialized"); \
202 assert(Map[1].BreakDown == \
203 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
204 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
205 " Src is incorrectly initialized"); \
207 } while (false)
209 CHECK_VALUEMAP_FPEXT(32, 16);
210 CHECK_VALUEMAP_FPEXT(64, 16);
211 CHECK_VALUEMAP_FPEXT(64, 32);
212 CHECK_VALUEMAP_FPEXT(128, 64);
214 assert(verify(TRI) && "Invalid register bank information");
217 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
220 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A,
221 const RegisterBank &B,
222 const TypeSize Size) const {
223 // What do we do with different size?
224 // copy are same size.
225 // Will introduce other hooks for different size:
226 // * extract cost.
227 // * build_sequence cost.
229 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
230 // FIXME: This should be deduced from the scheduling model.
231 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
232 // FMOVXDr or FMOVWSr.
233 return 5;
234 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
235 // FMOVDXr or FMOVSWr.
236 return 4;
238 return RegisterBankInfo::copyCost(A, B, Size);
241 const RegisterBank &
242 AArch64RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
243 LLT Ty) const {
244 switch (RC.getID()) {
245 case AArch64::GPR64sponlyRegClassID:
246 return getRegBank(AArch64::GPRRegBankID);
247 default:
248 return AArch64GenRegisterBankInfo::getRegBankFromRegClass(RC, Ty);
252 RegisterBankInfo::InstructionMappings
253 AArch64RegisterBankInfo::getInstrAlternativeMappings(
254 const MachineInstr &MI) const {
255 const MachineFunction &MF = *MI.getParent()->getParent();
256 const TargetSubtargetInfo &STI = MF.getSubtarget();
257 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
258 const MachineRegisterInfo &MRI = MF.getRegInfo();
260 switch (MI.getOpcode()) {
261 case TargetOpcode::G_OR: {
262 // 32 and 64-bit or can be mapped on either FPR or
263 // GPR for the same cost.
264 TypeSize Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
265 if (Size != 32 && Size != 64)
266 break;
268 // If the instruction has any implicit-defs or uses,
269 // do not mess with it.
270 if (MI.getNumOperands() != 3)
271 break;
272 InstructionMappings AltMappings;
273 const InstructionMapping &GPRMapping = getInstructionMapping(
274 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
275 /*NumOperands*/ 3);
276 const InstructionMapping &FPRMapping = getInstructionMapping(
277 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
278 /*NumOperands*/ 3);
280 AltMappings.push_back(&GPRMapping);
281 AltMappings.push_back(&FPRMapping);
282 return AltMappings;
284 case TargetOpcode::G_BITCAST: {
285 TypeSize Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
286 if (Size != 32 && Size != 64)
287 break;
289 // If the instruction has any implicit-defs or uses,
290 // do not mess with it.
291 if (MI.getNumOperands() != 2)
292 break;
294 InstructionMappings AltMappings;
295 const InstructionMapping &GPRMapping = getInstructionMapping(
296 /*ID*/ 1, /*Cost*/ 1,
297 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
298 /*NumOperands*/ 2);
299 const InstructionMapping &FPRMapping = getInstructionMapping(
300 /*ID*/ 2, /*Cost*/ 1,
301 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
302 /*NumOperands*/ 2);
303 const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
304 /*ID*/ 3,
305 /*Cost*/
306 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
307 TypeSize::getFixed(Size)),
308 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
309 /*NumOperands*/ 2);
310 const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
311 /*ID*/ 3,
312 /*Cost*/
313 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
314 TypeSize::getFixed(Size)),
315 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
316 /*NumOperands*/ 2);
318 AltMappings.push_back(&GPRMapping);
319 AltMappings.push_back(&FPRMapping);
320 AltMappings.push_back(&GPRToFPRMapping);
321 AltMappings.push_back(&FPRToGPRMapping);
322 return AltMappings;
324 case TargetOpcode::G_LOAD: {
325 TypeSize Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
326 if (Size != 64)
327 break;
329 // If the instruction has any implicit-defs or uses,
330 // do not mess with it.
331 if (MI.getNumOperands() != 2)
332 break;
334 InstructionMappings AltMappings;
335 const InstructionMapping &GPRMapping = getInstructionMapping(
336 /*ID*/ 1, /*Cost*/ 1,
337 getOperandsMapping(
338 {getValueMapping(PMI_FirstGPR, Size),
339 // Addresses are GPR 64-bit.
340 getValueMapping(PMI_FirstGPR, TypeSize::getFixed(64))}),
341 /*NumOperands*/ 2);
342 const InstructionMapping &FPRMapping = getInstructionMapping(
343 /*ID*/ 2, /*Cost*/ 1,
344 getOperandsMapping(
345 {getValueMapping(PMI_FirstFPR, Size),
346 // Addresses are GPR 64-bit.
347 getValueMapping(PMI_FirstGPR, TypeSize::getFixed(64))}),
348 /*NumOperands*/ 2);
350 AltMappings.push_back(&GPRMapping);
351 AltMappings.push_back(&FPRMapping);
352 return AltMappings;
354 default:
355 break;
357 return RegisterBankInfo::getInstrAlternativeMappings(MI);
360 void AArch64RegisterBankInfo::applyMappingImpl(
361 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
362 MachineInstr &MI = OpdMapper.getMI();
363 MachineRegisterInfo &MRI = OpdMapper.getMRI();
365 switch (MI.getOpcode()) {
366 case TargetOpcode::G_OR:
367 case TargetOpcode::G_BITCAST:
368 case TargetOpcode::G_LOAD:
369 // Those ID must match getInstrAlternativeMappings.
370 assert((OpdMapper.getInstrMapping().getID() >= 1 &&
371 OpdMapper.getInstrMapping().getID() <= 4) &&
372 "Don't know how to handle that ID");
373 return applyDefaultMapping(OpdMapper);
374 case TargetOpcode::G_INSERT_VECTOR_ELT: {
375 // Extend smaller gpr operands to 32 bit.
376 Builder.setInsertPt(*MI.getParent(), MI.getIterator());
377 auto Ext = Builder.buildAnyExt(LLT::scalar(32), MI.getOperand(2).getReg());
378 MRI.setRegBank(Ext.getReg(0), getRegBank(AArch64::GPRRegBankID));
379 MI.getOperand(2).setReg(Ext.getReg(0));
380 return applyDefaultMapping(OpdMapper);
382 case AArch64::G_DUP: {
383 // Extend smaller gpr to 32-bits
384 assert(MRI.getType(MI.getOperand(1).getReg()).getSizeInBits() < 32 &&
385 "Expected sources smaller than 32-bits");
386 Builder.setInsertPt(*MI.getParent(), MI.getIterator());
388 Register ConstReg;
389 auto ConstMI = MRI.getVRegDef(MI.getOperand(1).getReg());
390 if (ConstMI->getOpcode() == TargetOpcode::G_CONSTANT) {
391 auto CstVal = ConstMI->getOperand(1).getCImm()->getValue();
392 ConstReg =
393 Builder.buildConstant(LLT::scalar(32), CstVal.sext(32)).getReg(0);
394 } else {
395 ConstReg = Builder.buildAnyExt(LLT::scalar(32), MI.getOperand(1).getReg())
396 .getReg(0);
398 MRI.setRegBank(ConstReg, getRegBank(AArch64::GPRRegBankID));
399 MI.getOperand(1).setReg(ConstReg);
400 return applyDefaultMapping(OpdMapper);
402 default:
403 llvm_unreachable("Don't know how to handle that operation");
407 const RegisterBankInfo::InstructionMapping &
408 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
409 const MachineInstr &MI) const {
410 const unsigned Opc = MI.getOpcode();
411 const MachineFunction &MF = *MI.getParent()->getParent();
412 const MachineRegisterInfo &MRI = MF.getRegInfo();
414 unsigned NumOperands = MI.getNumOperands();
415 assert(NumOperands <= 3 &&
416 "This code is for instructions with 3 or less operands");
418 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
419 TypeSize Size = Ty.getSizeInBits();
420 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
422 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
424 #ifndef NDEBUG
425 // Make sure all the operands are using similar size and type.
426 // Should probably be checked by the machine verifier.
427 // This code won't catch cases where the number of lanes is
428 // different between the operands.
429 // If we want to go to that level of details, it is probably
430 // best to check that the types are the same, period.
431 // Currently, we just check that the register banks are the same
432 // for each types.
433 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
434 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
435 assert(
436 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
437 RBIdx, OpTy.getSizeInBits()) ==
438 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
439 "Operand has incompatible size");
440 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
441 (void)OpIsFPR;
442 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
444 #endif // End NDEBUG.
446 return getInstructionMapping(DefaultMappingID, 1,
447 getValueMapping(RBIdx, Size), NumOperands);
450 /// \returns true if a given intrinsic only uses and defines FPRs.
451 static bool isFPIntrinsic(const MachineRegisterInfo &MRI,
452 const MachineInstr &MI) {
453 // TODO: Add more intrinsics.
454 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
455 default:
456 return false;
457 case Intrinsic::aarch64_neon_uaddlv:
458 case Intrinsic::aarch64_neon_uaddv:
459 case Intrinsic::aarch64_neon_saddv:
460 case Intrinsic::aarch64_neon_umaxv:
461 case Intrinsic::aarch64_neon_smaxv:
462 case Intrinsic::aarch64_neon_uminv:
463 case Intrinsic::aarch64_neon_sminv:
464 case Intrinsic::aarch64_neon_faddv:
465 case Intrinsic::aarch64_neon_fmaxv:
466 case Intrinsic::aarch64_neon_fminv:
467 case Intrinsic::aarch64_neon_fmaxnmv:
468 case Intrinsic::aarch64_neon_fminnmv:
469 return true;
470 case Intrinsic::aarch64_neon_saddlv: {
471 const LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
472 return SrcTy.getElementType().getSizeInBits() >= 16 &&
473 SrcTy.getElementCount().getFixedValue() >= 4;
478 bool AArch64RegisterBankInfo::isPHIWithFPContraints(
479 const MachineInstr &MI, const MachineRegisterInfo &MRI,
480 const TargetRegisterInfo &TRI, const unsigned Depth) const {
481 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
482 return false;
484 return any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
485 [&](const MachineInstr &UseMI) {
486 if (onlyUsesFP(UseMI, MRI, TRI, Depth + 1))
487 return true;
488 return isPHIWithFPContraints(UseMI, MRI, TRI, Depth + 1);
492 bool AArch64RegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
493 const MachineRegisterInfo &MRI,
494 const TargetRegisterInfo &TRI,
495 unsigned Depth) const {
496 unsigned Op = MI.getOpcode();
497 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI))
498 return true;
500 // Do we have an explicit floating point instruction?
501 if (isPreISelGenericFloatingPointOpcode(Op))
502 return true;
504 // No. Check if we have a copy-like instruction. If we do, then we could
505 // still be fed by floating point instructions.
506 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
507 !isPreISelGenericOptimizationHint(Op))
508 return false;
510 // Check if we already know the register bank.
511 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
512 if (RB == &AArch64::FPRRegBank)
513 return true;
514 if (RB == &AArch64::GPRRegBank)
515 return false;
517 // We don't know anything.
519 // If we have a phi, we may be able to infer that it will be assigned a FPR
520 // based off of its inputs.
521 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
522 return false;
524 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
525 return Op.isReg() &&
526 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
530 bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
531 const MachineRegisterInfo &MRI,
532 const TargetRegisterInfo &TRI,
533 unsigned Depth) const {
534 switch (MI.getOpcode()) {
535 case TargetOpcode::G_FPTOSI:
536 case TargetOpcode::G_FPTOUI:
537 case TargetOpcode::G_FPTOSI_SAT:
538 case TargetOpcode::G_FPTOUI_SAT:
539 case TargetOpcode::G_FCMP:
540 case TargetOpcode::G_LROUND:
541 case TargetOpcode::G_LLROUND:
542 return true;
543 default:
544 break;
546 return hasFPConstraints(MI, MRI, TRI, Depth);
549 bool AArch64RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
550 const MachineRegisterInfo &MRI,
551 const TargetRegisterInfo &TRI,
552 unsigned Depth) const {
553 switch (MI.getOpcode()) {
554 case AArch64::G_DUP:
555 case TargetOpcode::G_SITOFP:
556 case TargetOpcode::G_UITOFP:
557 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
558 case TargetOpcode::G_INSERT_VECTOR_ELT:
559 case TargetOpcode::G_BUILD_VECTOR:
560 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
561 return true;
562 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
563 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
564 case Intrinsic::aarch64_neon_ld1x2:
565 case Intrinsic::aarch64_neon_ld1x3:
566 case Intrinsic::aarch64_neon_ld1x4:
567 case Intrinsic::aarch64_neon_ld2:
568 case Intrinsic::aarch64_neon_ld2lane:
569 case Intrinsic::aarch64_neon_ld2r:
570 case Intrinsic::aarch64_neon_ld3:
571 case Intrinsic::aarch64_neon_ld3lane:
572 case Intrinsic::aarch64_neon_ld3r:
573 case Intrinsic::aarch64_neon_ld4:
574 case Intrinsic::aarch64_neon_ld4lane:
575 case Intrinsic::aarch64_neon_ld4r:
576 return true;
577 default:
578 break;
580 break;
581 default:
582 break;
584 return hasFPConstraints(MI, MRI, TRI, Depth);
587 bool AArch64RegisterBankInfo::isLoadFromFPType(const MachineInstr &MI) const {
588 // GMemOperation because we also want to match indexed loads.
589 auto *MemOp = cast<GMemOperation>(&MI);
590 const Value *LdVal = MemOp->getMMO().getValue();
591 if (!LdVal)
592 return false;
594 Type *EltTy = nullptr;
595 if (const GlobalValue *GV = dyn_cast<GlobalValue>(LdVal)) {
596 EltTy = GV->getValueType();
597 // Look at the first element of the struct to determine the type we are
598 // loading
599 while (StructType *StructEltTy = dyn_cast<StructType>(EltTy)) {
600 if (StructEltTy->getNumElements() == 0)
601 break;
602 EltTy = StructEltTy->getTypeAtIndex(0U);
604 // Look at the first element of the array to determine its type
605 if (isa<ArrayType>(EltTy))
606 EltTy = EltTy->getArrayElementType();
607 } else {
608 // FIXME: grubbing around uses is pretty ugly, but with no more
609 // `getPointerElementType` there's not much else we can do.
610 for (const auto *LdUser : LdVal->users()) {
611 if (isa<LoadInst>(LdUser)) {
612 EltTy = LdUser->getType();
613 break;
615 if (isa<StoreInst>(LdUser) && LdUser->getOperand(1) == LdVal) {
616 EltTy = LdUser->getOperand(0)->getType();
617 break;
621 return EltTy && EltTy->isFPOrFPVectorTy();
624 const RegisterBankInfo::InstructionMapping &
625 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
626 const unsigned Opc = MI.getOpcode();
628 // Try the default logic for non-generic instructions that are either copies
629 // or already have some operands assigned to banks.
630 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
631 Opc == TargetOpcode::G_PHI) {
632 const RegisterBankInfo::InstructionMapping &Mapping =
633 getInstrMappingImpl(MI);
634 if (Mapping.isValid())
635 return Mapping;
638 const MachineFunction &MF = *MI.getParent()->getParent();
639 const MachineRegisterInfo &MRI = MF.getRegInfo();
640 const TargetSubtargetInfo &STI = MF.getSubtarget();
641 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
643 switch (Opc) {
644 // G_{F|S|U}REM are not listed because they are not legal.
645 // Arithmetic ops.
646 case TargetOpcode::G_ADD:
647 case TargetOpcode::G_SUB:
648 case TargetOpcode::G_PTR_ADD:
649 case TargetOpcode::G_MUL:
650 case TargetOpcode::G_SDIV:
651 case TargetOpcode::G_UDIV:
652 // Bitwise ops.
653 case TargetOpcode::G_AND:
654 case TargetOpcode::G_OR:
655 case TargetOpcode::G_XOR:
656 // Floating point ops.
657 case TargetOpcode::G_FADD:
658 case TargetOpcode::G_FSUB:
659 case TargetOpcode::G_FMUL:
660 case TargetOpcode::G_FDIV:
661 case TargetOpcode::G_FMAXIMUM:
662 case TargetOpcode::G_FMINIMUM:
663 return getSameKindOfOperandsMapping(MI);
664 case TargetOpcode::G_FPEXT: {
665 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
666 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
667 return getInstructionMapping(
668 DefaultMappingID, /*Cost*/ 1,
669 getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
670 /*NumOperands*/ 2);
672 // Shifts.
673 case TargetOpcode::G_SHL:
674 case TargetOpcode::G_LSHR:
675 case TargetOpcode::G_ASHR: {
676 LLT ShiftAmtTy = MRI.getType(MI.getOperand(2).getReg());
677 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
678 if (ShiftAmtTy.getSizeInBits() == 64 && SrcTy.getSizeInBits() == 32)
679 return getInstructionMapping(DefaultMappingID, 1,
680 &ValMappings[Shift64Imm], 3);
681 return getSameKindOfOperandsMapping(MI);
683 case TargetOpcode::COPY: {
684 Register DstReg = MI.getOperand(0).getReg();
685 Register SrcReg = MI.getOperand(1).getReg();
686 // Check if one of the register is not a generic register.
687 if ((DstReg.isPhysical() || !MRI.getType(DstReg).isValid()) ||
688 (SrcReg.isPhysical() || !MRI.getType(SrcReg).isValid())) {
689 const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
690 const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
691 if (!DstRB)
692 DstRB = SrcRB;
693 else if (!SrcRB)
694 SrcRB = DstRB;
695 // If both RB are null that means both registers are generic.
696 // We shouldn't be here.
697 assert(DstRB && SrcRB && "Both RegBank were nullptr");
698 TypeSize Size = getSizeInBits(DstReg, MRI, TRI);
699 return getInstructionMapping(
700 DefaultMappingID, copyCost(*DstRB, *SrcRB, Size),
701 getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
702 // We only care about the mapping of the destination.
703 /*NumOperands*/ 1);
705 // Both registers are generic, use G_BITCAST.
706 [[fallthrough]];
708 case TargetOpcode::G_BITCAST: {
709 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
710 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
711 TypeSize Size = DstTy.getSizeInBits();
712 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
713 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
714 const RegisterBank &DstRB =
715 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
716 const RegisterBank &SrcRB =
717 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
718 return getInstructionMapping(
719 DefaultMappingID, copyCost(DstRB, SrcRB, Size),
720 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
721 // We only care about the mapping of the destination for COPY.
722 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
724 default:
725 break;
728 unsigned NumOperands = MI.getNumOperands();
729 unsigned MappingID = DefaultMappingID;
731 // Track the size and bank of each register. We don't do partial mappings.
732 SmallVector<unsigned, 4> OpSize(NumOperands);
733 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
734 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
735 auto &MO = MI.getOperand(Idx);
736 if (!MO.isReg() || !MO.getReg())
737 continue;
739 LLT Ty = MRI.getType(MO.getReg());
740 if (!Ty.isValid())
741 continue;
742 OpSize[Idx] = Ty.getSizeInBits().getKnownMinValue();
744 // As a top-level guess, vectors including both scalable and non-scalable
745 // ones go in FPRs, scalars and pointers in GPRs.
746 // For floating-point instructions, scalars go in FPRs.
747 if (Ty.isVector())
748 OpRegBankIdx[Idx] = PMI_FirstFPR;
749 else if (isPreISelGenericFloatingPointOpcode(Opc) ||
750 Ty.getSizeInBits() > 64)
751 OpRegBankIdx[Idx] = PMI_FirstFPR;
752 else
753 OpRegBankIdx[Idx] = PMI_FirstGPR;
756 unsigned Cost = 1;
757 // Some of the floating-point instructions have mixed GPR and FPR operands:
758 // fine-tune the computed mapping.
759 switch (Opc) {
760 case AArch64::G_DUP: {
761 Register ScalarReg = MI.getOperand(1).getReg();
762 LLT ScalarTy = MRI.getType(ScalarReg);
763 auto ScalarDef = MRI.getVRegDef(ScalarReg);
764 // We want to select dup(load) into LD1R.
765 if (ScalarDef->getOpcode() == TargetOpcode::G_LOAD)
766 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
767 // s8 is an exception for G_DUP, which we always want on gpr.
768 else if (ScalarTy.getSizeInBits() != 8 &&
769 (getRegBank(ScalarReg, MRI, TRI) == &AArch64::FPRRegBank ||
770 onlyDefinesFP(*ScalarDef, MRI, TRI)))
771 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
772 else {
773 if (ScalarTy.getSizeInBits() < 32 &&
774 getRegBank(ScalarReg, MRI, TRI) == &AArch64::GPRRegBank) {
775 // Calls applyMappingImpl()
776 MappingID = CustomMappingID;
778 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
780 break;
782 case TargetOpcode::G_TRUNC: {
783 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
784 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128)
785 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
786 break;
788 case TargetOpcode::G_SITOFP:
789 case TargetOpcode::G_UITOFP: {
790 if (MRI.getType(MI.getOperand(0).getReg()).isVector())
791 break;
792 // Integer to FP conversions don't necessarily happen between GPR -> FPR
793 // regbanks. They can also be done within an FPR register.
794 Register SrcReg = MI.getOperand(1).getReg();
795 if (getRegBank(SrcReg, MRI, TRI) == &AArch64::FPRRegBank)
796 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
797 else
798 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
799 break;
801 case TargetOpcode::G_FPTOSI:
802 case TargetOpcode::G_FPTOUI:
803 case TargetOpcode::G_FPTOSI_SAT:
804 case TargetOpcode::G_FPTOUI_SAT:
805 case TargetOpcode::G_INTRINSIC_LRINT:
806 case TargetOpcode::G_INTRINSIC_LLRINT:
807 if (MRI.getType(MI.getOperand(0).getReg()).isVector())
808 break;
809 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
810 break;
811 case TargetOpcode::G_FCMP: {
812 // If the result is a vector, it must use a FPR.
813 AArch64GenRegisterBankInfo::PartialMappingIdx Idx0 =
814 MRI.getType(MI.getOperand(0).getReg()).isVector() ? PMI_FirstFPR
815 : PMI_FirstGPR;
816 OpRegBankIdx = {Idx0,
817 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
818 break;
820 case TargetOpcode::G_BITCAST:
821 // This is going to be a cross register bank copy and this is expensive.
822 if (OpRegBankIdx[0] != OpRegBankIdx[1])
823 Cost = copyCost(
824 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
825 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
826 TypeSize::getFixed(OpSize[0]));
827 break;
828 case TargetOpcode::G_LOAD: {
829 // Loading in vector unit is slightly more expensive.
830 // This is actually only true for the LD1R and co instructions,
831 // but anyway for the fast mode this number does not matter and
832 // for the greedy mode the cost of the cross bank copy will
833 // offset this number.
834 // FIXME: Should be derived from the scheduling model.
835 if (OpRegBankIdx[0] != PMI_FirstGPR) {
836 Cost = 2;
837 break;
840 if (cast<GLoad>(MI).isAtomic()) {
841 // Atomics always use GPR destinations. Don't refine any further.
842 OpRegBankIdx[0] = PMI_FirstGPR;
843 break;
846 // Try to guess the type of the load from the MMO.
847 if (isLoadFromFPType(MI)) {
848 OpRegBankIdx[0] = PMI_FirstFPR;
849 break;
852 // Check if that load feeds fp instructions.
853 // In that case, we want the default mapping to be on FPR
854 // instead of blind map every scalar to GPR.
855 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
856 [&](const MachineInstr &UseMI) {
857 // If we have at least one direct or indirect use
858 // in a FP instruction,
859 // assume this was a floating point load in the IR. If it was
860 // not, we would have had a bitcast before reaching that
861 // instruction.
863 // Int->FP conversion operations are also captured in
864 // onlyDefinesFP().
866 if (isPHIWithFPContraints(UseMI, MRI, TRI))
867 return true;
869 return onlyUsesFP(UseMI, MRI, TRI) ||
870 onlyDefinesFP(UseMI, MRI, TRI);
872 OpRegBankIdx[0] = PMI_FirstFPR;
873 break;
875 case TargetOpcode::G_STORE:
876 // Check if that store is fed by fp instructions.
877 if (OpRegBankIdx[0] == PMI_FirstGPR) {
878 Register VReg = MI.getOperand(0).getReg();
879 if (!VReg)
880 break;
881 MachineInstr *DefMI = MRI.getVRegDef(VReg);
882 if (onlyDefinesFP(*DefMI, MRI, TRI))
883 OpRegBankIdx[0] = PMI_FirstFPR;
884 break;
886 break;
887 case TargetOpcode::G_INDEXED_STORE:
888 if (OpRegBankIdx[1] == PMI_FirstGPR) {
889 Register VReg = MI.getOperand(1).getReg();
890 if (!VReg)
891 break;
892 MachineInstr *DefMI = MRI.getVRegDef(VReg);
893 if (onlyDefinesFP(*DefMI, MRI, TRI))
894 OpRegBankIdx[1] = PMI_FirstFPR;
895 break;
897 break;
898 case TargetOpcode::G_INDEXED_SEXTLOAD:
899 case TargetOpcode::G_INDEXED_ZEXTLOAD:
900 // These should always be GPR.
901 OpRegBankIdx[0] = PMI_FirstGPR;
902 break;
903 case TargetOpcode::G_INDEXED_LOAD: {
904 if (isLoadFromFPType(MI))
905 OpRegBankIdx[0] = PMI_FirstFPR;
906 break;
908 case TargetOpcode::G_SELECT: {
909 // If the destination is FPR, preserve that.
910 if (OpRegBankIdx[0] != PMI_FirstGPR)
911 break;
913 // If we're taking in vectors, we have no choice but to put everything on
914 // FPRs, except for the condition. The condition must always be on a GPR.
915 LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
916 if (SrcTy.isVector()) {
917 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR};
918 break;
921 // Try to minimize the number of copies. If we have more floating point
922 // constrained values than not, then we'll put everything on FPR. Otherwise,
923 // everything has to be on GPR.
924 unsigned NumFP = 0;
926 // Check if the uses of the result always produce floating point values.
928 // For example:
930 // %z = G_SELECT %cond %x %y
931 // fpr = G_FOO %z ...
932 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
933 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); }))
934 ++NumFP;
936 // Check if the defs of the source values always produce floating point
937 // values.
939 // For example:
941 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
942 // %z = G_SELECT %cond %x %y
944 // Also check whether or not the sources have already been decided to be
945 // FPR. Keep track of this.
947 // This doesn't check the condition, since it's just whatever is in NZCV.
948 // This isn't passed explicitly in a register to fcsel/csel.
949 for (unsigned Idx = 2; Idx < 4; ++Idx) {
950 Register VReg = MI.getOperand(Idx).getReg();
951 MachineInstr *DefMI = MRI.getVRegDef(VReg);
952 if (getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank ||
953 onlyDefinesFP(*DefMI, MRI, TRI))
954 ++NumFP;
957 // If we have more FP constraints than not, then move everything over to
958 // FPR.
959 if (NumFP >= 2)
960 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR, PMI_FirstFPR, PMI_FirstFPR};
962 break;
964 case TargetOpcode::G_UNMERGE_VALUES: {
965 // If the first operand belongs to a FPR register bank, then make sure that
966 // we preserve that.
967 if (OpRegBankIdx[0] != PMI_FirstGPR)
968 break;
970 LLT SrcTy = MRI.getType(MI.getOperand(MI.getNumOperands()-1).getReg());
971 // UNMERGE into scalars from a vector should always use FPR.
972 // Likewise if any of the uses are FP instructions.
973 if (SrcTy.isVector() || SrcTy == LLT::scalar(128) ||
974 any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
975 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) {
976 // Set the register bank of every operand to FPR.
977 for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
978 Idx < NumOperands; ++Idx)
979 OpRegBankIdx[Idx] = PMI_FirstFPR;
981 break;
983 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
984 // Destination and source need to be FPRs.
985 OpRegBankIdx[0] = PMI_FirstFPR;
986 OpRegBankIdx[1] = PMI_FirstFPR;
988 // Index needs to be a GPR.
989 OpRegBankIdx[2] = PMI_FirstGPR;
990 break;
991 case TargetOpcode::G_INSERT_VECTOR_ELT:
992 OpRegBankIdx[0] = PMI_FirstFPR;
993 OpRegBankIdx[1] = PMI_FirstFPR;
995 // The element may be either a GPR or FPR. Preserve that behaviour.
996 if (getRegBank(MI.getOperand(2).getReg(), MRI, TRI) == &AArch64::FPRRegBank)
997 OpRegBankIdx[2] = PMI_FirstFPR;
998 else {
999 // If the type is i8/i16, and the regank will be GPR, then we change the
1000 // type to i32 in applyMappingImpl.
1001 LLT Ty = MRI.getType(MI.getOperand(2).getReg());
1002 if (Ty.getSizeInBits() == 8 || Ty.getSizeInBits() == 16) {
1003 // Calls applyMappingImpl()
1004 MappingID = CustomMappingID;
1006 OpRegBankIdx[2] = PMI_FirstGPR;
1009 // Index needs to be a GPR.
1010 OpRegBankIdx[3] = PMI_FirstGPR;
1011 break;
1012 case TargetOpcode::G_EXTRACT: {
1013 // For s128 sources we have to use fpr unless we know otherwise.
1014 auto Src = MI.getOperand(1).getReg();
1015 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
1016 if (SrcTy.getSizeInBits() != 128)
1017 break;
1018 auto Idx = MRI.getRegClassOrNull(Src) == &AArch64::XSeqPairsClassRegClass
1019 ? PMI_FirstGPR
1020 : PMI_FirstFPR;
1021 OpRegBankIdx[0] = Idx;
1022 OpRegBankIdx[1] = Idx;
1023 break;
1025 case TargetOpcode::G_BUILD_VECTOR: {
1026 // If the first source operand belongs to a FPR register bank, then make
1027 // sure that we preserve that.
1028 if (OpRegBankIdx[1] != PMI_FirstGPR)
1029 break;
1030 Register VReg = MI.getOperand(1).getReg();
1031 if (!VReg)
1032 break;
1034 // Get the instruction that defined the source operand reg, and check if
1035 // it's a floating point operation. Or, if it's a type like s16 which
1036 // doesn't have a exact size gpr register class. The exception is if the
1037 // build_vector has all constant operands, which may be better to leave as
1038 // gpr without copies, so it can be matched in imported patterns.
1039 MachineInstr *DefMI = MRI.getVRegDef(VReg);
1040 unsigned DefOpc = DefMI->getOpcode();
1041 const LLT SrcTy = MRI.getType(VReg);
1042 if (all_of(MI.operands(), [&](const MachineOperand &Op) {
1043 return Op.isDef() || MRI.getVRegDef(Op.getReg())->getOpcode() ==
1044 TargetOpcode::G_CONSTANT;
1046 break;
1047 if (isPreISelGenericFloatingPointOpcode(DefOpc) ||
1048 SrcTy.getSizeInBits() < 32 ||
1049 getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank) {
1050 // Have a floating point op.
1051 // Make sure every operand gets mapped to a FPR register class.
1052 unsigned NumOperands = MI.getNumOperands();
1053 for (unsigned Idx = 0; Idx < NumOperands; ++Idx)
1054 OpRegBankIdx[Idx] = PMI_FirstFPR;
1056 break;
1058 case TargetOpcode::G_VECREDUCE_FADD:
1059 case TargetOpcode::G_VECREDUCE_FMUL:
1060 case TargetOpcode::G_VECREDUCE_FMAX:
1061 case TargetOpcode::G_VECREDUCE_FMIN:
1062 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
1063 case TargetOpcode::G_VECREDUCE_FMINIMUM:
1064 case TargetOpcode::G_VECREDUCE_ADD:
1065 case TargetOpcode::G_VECREDUCE_MUL:
1066 case TargetOpcode::G_VECREDUCE_AND:
1067 case TargetOpcode::G_VECREDUCE_OR:
1068 case TargetOpcode::G_VECREDUCE_XOR:
1069 case TargetOpcode::G_VECREDUCE_SMAX:
1070 case TargetOpcode::G_VECREDUCE_SMIN:
1071 case TargetOpcode::G_VECREDUCE_UMAX:
1072 case TargetOpcode::G_VECREDUCE_UMIN:
1073 // Reductions produce a scalar value from a vector, the scalar should be on
1074 // FPR bank.
1075 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1076 break;
1077 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
1078 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
1079 // These reductions also take a scalar accumulator input.
1080 // Assign them FPR for now.
1081 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR, PMI_FirstFPR};
1082 break;
1083 case TargetOpcode::G_INTRINSIC:
1084 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
1085 // Check if we know that the intrinsic has any constraints on its register
1086 // banks. If it does, then update the mapping accordingly.
1087 unsigned Idx = 0;
1088 if (onlyDefinesFP(MI, MRI, TRI))
1089 for (const auto &Op : MI.defs()) {
1090 if (Op.isReg())
1091 OpRegBankIdx[Idx] = PMI_FirstFPR;
1092 ++Idx;
1094 else
1095 Idx += MI.getNumExplicitDefs();
1097 if (onlyUsesFP(MI, MRI, TRI))
1098 for (const auto &Op : MI.explicit_uses()) {
1099 if (Op.isReg())
1100 OpRegBankIdx[Idx] = PMI_FirstFPR;
1101 ++Idx;
1103 break;
1105 case TargetOpcode::G_LROUND:
1106 case TargetOpcode::G_LLROUND: {
1107 // Source is always floating point and destination is always integer.
1108 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
1109 break;
1113 // Finally construct the computed mapping.
1114 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
1115 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
1116 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
1117 LLT Ty = MRI.getType(MI.getOperand(Idx).getReg());
1118 if (!Ty.isValid())
1119 continue;
1120 auto Mapping =
1121 getValueMapping(OpRegBankIdx[Idx], TypeSize::getFixed(OpSize[Idx]));
1122 if (!Mapping->isValid())
1123 return getInvalidInstructionMapping();
1125 OpdsMapping[Idx] = Mapping;
1129 return getInstructionMapping(MappingID, Cost, getOperandsMapping(OpdsMapping),
1130 NumOperands);