1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the RegisterBankInfo class for
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
14 #include "AArch64RegisterBankInfo.h"
15 #include "AArch64InstrInfo.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
18 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
19 #include "llvm/CodeGen/LowLevelType.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineOperand.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/TargetOpcodes.h"
25 #include "llvm/CodeGen/TargetRegisterInfo.h"
26 #include "llvm/CodeGen/TargetSubtargetInfo.h"
27 #include "llvm/Support/ErrorHandling.h"
31 #define GET_TARGET_REGBANK_IMPL
32 #include "AArch64GenRegisterBank.inc"
34 // This file will be TableGen'ed at some point.
35 #include "AArch64GenRegisterBankInfo.def"
39 AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo
&TRI
)
40 : AArch64GenRegisterBankInfo() {
41 static bool AlreadyInit
= false;
42 // We have only one set of register banks, whatever the subtarget
43 // is. Therefore, the initialization of the RegBanks table should be
44 // done only once. Indeed the table of all register banks
45 // (AArch64::RegBanks) is unique in the compiler. At some point, it
46 // will get tablegen'ed and the whole constructor becomes empty.
51 const RegisterBank
&RBGPR
= getRegBank(AArch64::GPRRegBankID
);
53 assert(&AArch64::GPRRegBank
== &RBGPR
&&
54 "The order in RegBanks is messed up");
56 const RegisterBank
&RBFPR
= getRegBank(AArch64::FPRRegBankID
);
58 assert(&AArch64::FPRRegBank
== &RBFPR
&&
59 "The order in RegBanks is messed up");
61 const RegisterBank
&RBCCR
= getRegBank(AArch64::CCRegBankID
);
63 assert(&AArch64::CCRegBank
== &RBCCR
&& "The order in RegBanks is messed up");
65 // The GPR register bank is fully defined by all the registers in
66 // GR64all + its subclasses.
67 assert(RBGPR
.covers(*TRI
.getRegClass(AArch64::GPR32RegClassID
)) &&
68 "Subclass not added?");
69 assert(RBGPR
.getSize() == 64 && "GPRs should hold up to 64-bit");
71 // The FPR register bank is fully defined by all the registers in
72 // GR64all + its subclasses.
73 assert(RBFPR
.covers(*TRI
.getRegClass(AArch64::QQRegClassID
)) &&
74 "Subclass not added?");
75 assert(RBFPR
.covers(*TRI
.getRegClass(AArch64::FPR64RegClassID
)) &&
76 "Subclass not added?");
77 assert(RBFPR
.getSize() == 512 &&
78 "FPRs should hold up to 512-bit via QQQQ sequence");
80 assert(RBCCR
.covers(*TRI
.getRegClass(AArch64::CCRRegClassID
)) &&
82 assert(RBCCR
.getSize() == 32 && "CCR should hold up to 32-bit");
84 // Check that the TableGen'ed like file is in sync we our expectations.
86 assert(checkPartialMappingIdx(PMI_FirstGPR
, PMI_LastGPR
,
87 {PMI_GPR32
, PMI_GPR64
}) &&
88 "PartialMappingIdx's are incorrectly ordered");
89 assert(checkPartialMappingIdx(PMI_FirstFPR
, PMI_LastFPR
,
90 {PMI_FPR16
, PMI_FPR32
, PMI_FPR64
, PMI_FPR128
,
91 PMI_FPR256
, PMI_FPR512
}) &&
92 "PartialMappingIdx's are incorrectly ordered");
94 // Check partial mapping.
95 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
98 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
99 #Idx " is incorrectly initialized"); \
102 CHECK_PARTIALMAP(PMI_GPR32
, 0, 32, RBGPR
);
103 CHECK_PARTIALMAP(PMI_GPR64
, 0, 64, RBGPR
);
104 CHECK_PARTIALMAP(PMI_FPR16
, 0, 16, RBFPR
);
105 CHECK_PARTIALMAP(PMI_FPR32
, 0, 32, RBFPR
);
106 CHECK_PARTIALMAP(PMI_FPR64
, 0, 64, RBFPR
);
107 CHECK_PARTIALMAP(PMI_FPR128
, 0, 128, RBFPR
);
108 CHECK_PARTIALMAP(PMI_FPR256
, 0, 256, RBFPR
);
109 CHECK_PARTIALMAP(PMI_FPR512
, 0, 512, RBFPR
);
111 // Check value mapping.
112 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
114 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
115 PartialMappingIdx::PMI_First##RBName, Size, \
117 #RBName #Size " " #Offset " is incorrectly initialized"); \
120 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
122 CHECK_VALUEMAP(GPR
, 32);
123 CHECK_VALUEMAP(GPR
, 64);
124 CHECK_VALUEMAP(FPR
, 16);
125 CHECK_VALUEMAP(FPR
, 32);
126 CHECK_VALUEMAP(FPR
, 64);
127 CHECK_VALUEMAP(FPR
, 128);
128 CHECK_VALUEMAP(FPR
, 256);
129 CHECK_VALUEMAP(FPR
, 512);
131 // Check the value mapping for 3-operands instructions where all the operands
132 // map to the same value mapping.
133 #define CHECK_VALUEMAP_3OPS(RBName, Size) \
135 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
136 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
137 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
140 CHECK_VALUEMAP_3OPS(GPR
, 32);
141 CHECK_VALUEMAP_3OPS(GPR
, 64);
142 CHECK_VALUEMAP_3OPS(FPR
, 32);
143 CHECK_VALUEMAP_3OPS(FPR
, 64);
144 CHECK_VALUEMAP_3OPS(FPR
, 128);
145 CHECK_VALUEMAP_3OPS(FPR
, 256);
146 CHECK_VALUEMAP_3OPS(FPR
, 512);
148 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
150 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
151 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
152 (void)PartialMapDstIdx; \
153 (void)PartialMapSrcIdx; \
154 const ValueMapping *Map = getCopyMapping( \
155 AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \
157 assert(Map[0].BreakDown == \
158 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
159 Map[0].NumBreakDowns == 1 && #RBNameDst #Size \
160 " Dst is incorrectly initialized"); \
161 assert(Map[1].BreakDown == \
162 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
163 Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \
164 " Src is incorrectly initialized"); \
168 CHECK_VALUEMAP_CROSSREGCPY(GPR
, GPR
, 32);
169 CHECK_VALUEMAP_CROSSREGCPY(GPR
, FPR
, 32);
170 CHECK_VALUEMAP_CROSSREGCPY(GPR
, GPR
, 64);
171 CHECK_VALUEMAP_CROSSREGCPY(GPR
, FPR
, 64);
172 CHECK_VALUEMAP_CROSSREGCPY(FPR
, FPR
, 32);
173 CHECK_VALUEMAP_CROSSREGCPY(FPR
, GPR
, 32);
174 CHECK_VALUEMAP_CROSSREGCPY(FPR
, FPR
, 64);
175 CHECK_VALUEMAP_CROSSREGCPY(FPR
, GPR
, 64);
177 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
179 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
180 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
181 (void)PartialMapDstIdx; \
182 (void)PartialMapSrcIdx; \
183 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
185 assert(Map[0].BreakDown == \
186 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
187 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
188 " Dst is incorrectly initialized"); \
189 assert(Map[1].BreakDown == \
190 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
191 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
192 " Src is incorrectly initialized"); \
196 CHECK_VALUEMAP_FPEXT(32, 16);
197 CHECK_VALUEMAP_FPEXT(64, 16);
198 CHECK_VALUEMAP_FPEXT(64, 32);
199 CHECK_VALUEMAP_FPEXT(128, 64);
201 assert(verify(TRI
) && "Invalid register bank information");
204 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank
&A
,
205 const RegisterBank
&B
,
206 unsigned Size
) const {
207 // What do we do with different size?
208 // copy are same size.
209 // Will introduce other hooks for different size:
211 // * build_sequence cost.
213 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
214 // FIXME: This should be deduced from the scheduling model.
215 if (&A
== &AArch64::GPRRegBank
&& &B
== &AArch64::FPRRegBank
)
216 // FMOVXDr or FMOVWSr.
218 if (&A
== &AArch64::FPRRegBank
&& &B
== &AArch64::GPRRegBank
)
219 // FMOVDXr or FMOVSWr.
222 return RegisterBankInfo::copyCost(A
, B
, Size
);
225 const RegisterBank
&AArch64RegisterBankInfo::getRegBankFromRegClass(
226 const TargetRegisterClass
&RC
) const {
227 switch (RC
.getID()) {
228 case AArch64::FPR8RegClassID
:
229 case AArch64::FPR16RegClassID
:
230 case AArch64::FPR32RegClassID
:
231 case AArch64::FPR64RegClassID
:
232 case AArch64::FPR128RegClassID
:
233 case AArch64::FPR128_loRegClassID
:
234 case AArch64::DDRegClassID
:
235 case AArch64::DDDRegClassID
:
236 case AArch64::DDDDRegClassID
:
237 case AArch64::QQRegClassID
:
238 case AArch64::QQQRegClassID
:
239 case AArch64::QQQQRegClassID
:
240 return getRegBank(AArch64::FPRRegBankID
);
241 case AArch64::GPR32commonRegClassID
:
242 case AArch64::GPR32RegClassID
:
243 case AArch64::GPR32spRegClassID
:
244 case AArch64::GPR32sponlyRegClassID
:
245 case AArch64::GPR32argRegClassID
:
246 case AArch64::GPR32allRegClassID
:
247 case AArch64::GPR64commonRegClassID
:
248 case AArch64::GPR64RegClassID
:
249 case AArch64::GPR64spRegClassID
:
250 case AArch64::GPR64sponlyRegClassID
:
251 case AArch64::GPR64argRegClassID
:
252 case AArch64::GPR64allRegClassID
:
253 case AArch64::GPR64noipRegClassID
:
254 case AArch64::GPR64common_and_GPR64noipRegClassID
:
255 case AArch64::GPR64noip_and_tcGPR64RegClassID
:
256 case AArch64::tcGPR64RegClassID
:
257 case AArch64::WSeqPairsClassRegClassID
:
258 case AArch64::XSeqPairsClassRegClassID
:
259 return getRegBank(AArch64::GPRRegBankID
);
260 case AArch64::CCRRegClassID
:
261 return getRegBank(AArch64::CCRegBankID
);
263 llvm_unreachable("Register class not supported");
267 RegisterBankInfo::InstructionMappings
268 AArch64RegisterBankInfo::getInstrAlternativeMappings(
269 const MachineInstr
&MI
) const {
270 const MachineFunction
&MF
= *MI
.getParent()->getParent();
271 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
272 const TargetRegisterInfo
&TRI
= *STI
.getRegisterInfo();
273 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
275 switch (MI
.getOpcode()) {
276 case TargetOpcode::G_OR
: {
277 // 32 and 64-bit or can be mapped on either FPR or
278 // GPR for the same cost.
279 unsigned Size
= getSizeInBits(MI
.getOperand(0).getReg(), MRI
, TRI
);
280 if (Size
!= 32 && Size
!= 64)
283 // If the instruction has any implicit-defs or uses,
284 // do not mess with it.
285 if (MI
.getNumOperands() != 3)
287 InstructionMappings AltMappings
;
288 const InstructionMapping
&GPRMapping
= getInstructionMapping(
289 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR
, Size
),
291 const InstructionMapping
&FPRMapping
= getInstructionMapping(
292 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR
, Size
),
295 AltMappings
.push_back(&GPRMapping
);
296 AltMappings
.push_back(&FPRMapping
);
299 case TargetOpcode::G_BITCAST
: {
300 unsigned Size
= getSizeInBits(MI
.getOperand(0).getReg(), MRI
, TRI
);
301 if (Size
!= 32 && Size
!= 64)
304 // If the instruction has any implicit-defs or uses,
305 // do not mess with it.
306 if (MI
.getNumOperands() != 2)
309 InstructionMappings AltMappings
;
310 const InstructionMapping
&GPRMapping
= getInstructionMapping(
311 /*ID*/ 1, /*Cost*/ 1,
312 getCopyMapping(AArch64::GPRRegBankID
, AArch64::GPRRegBankID
, Size
),
314 const InstructionMapping
&FPRMapping
= getInstructionMapping(
315 /*ID*/ 2, /*Cost*/ 1,
316 getCopyMapping(AArch64::FPRRegBankID
, AArch64::FPRRegBankID
, Size
),
318 const InstructionMapping
&GPRToFPRMapping
= getInstructionMapping(
320 /*Cost*/ copyCost(AArch64::GPRRegBank
, AArch64::FPRRegBank
, Size
),
321 getCopyMapping(AArch64::FPRRegBankID
, AArch64::GPRRegBankID
, Size
),
323 const InstructionMapping
&FPRToGPRMapping
= getInstructionMapping(
325 /*Cost*/ copyCost(AArch64::GPRRegBank
, AArch64::FPRRegBank
, Size
),
326 getCopyMapping(AArch64::GPRRegBankID
, AArch64::FPRRegBankID
, Size
),
329 AltMappings
.push_back(&GPRMapping
);
330 AltMappings
.push_back(&FPRMapping
);
331 AltMappings
.push_back(&GPRToFPRMapping
);
332 AltMappings
.push_back(&FPRToGPRMapping
);
335 case TargetOpcode::G_LOAD
: {
336 unsigned Size
= getSizeInBits(MI
.getOperand(0).getReg(), MRI
, TRI
);
340 // If the instruction has any implicit-defs or uses,
341 // do not mess with it.
342 if (MI
.getNumOperands() != 2)
345 InstructionMappings AltMappings
;
346 const InstructionMapping
&GPRMapping
= getInstructionMapping(
347 /*ID*/ 1, /*Cost*/ 1,
348 getOperandsMapping({getValueMapping(PMI_FirstGPR
, Size
),
349 // Addresses are GPR 64-bit.
350 getValueMapping(PMI_FirstGPR
, 64)}),
352 const InstructionMapping
&FPRMapping
= getInstructionMapping(
353 /*ID*/ 2, /*Cost*/ 1,
354 getOperandsMapping({getValueMapping(PMI_FirstFPR
, Size
),
355 // Addresses are GPR 64-bit.
356 getValueMapping(PMI_FirstGPR
, 64)}),
359 AltMappings
.push_back(&GPRMapping
);
360 AltMappings
.push_back(&FPRMapping
);
366 return RegisterBankInfo::getInstrAlternativeMappings(MI
);
369 void AArch64RegisterBankInfo::applyMappingImpl(
370 const OperandsMapper
&OpdMapper
) const {
371 switch (OpdMapper
.getMI().getOpcode()) {
372 case TargetOpcode::G_OR
:
373 case TargetOpcode::G_BITCAST
:
374 case TargetOpcode::G_LOAD
:
375 // Those ID must match getInstrAlternativeMappings.
376 assert((OpdMapper
.getInstrMapping().getID() >= 1 &&
377 OpdMapper
.getInstrMapping().getID() <= 4) &&
378 "Don't know how to handle that ID");
379 return applyDefaultMapping(OpdMapper
);
381 llvm_unreachable("Don't know how to handle that operation");
385 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
386 /// having only floating-point operands.
387 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc
) {
389 case TargetOpcode::G_FADD
:
390 case TargetOpcode::G_FSUB
:
391 case TargetOpcode::G_FMUL
:
392 case TargetOpcode::G_FMA
:
393 case TargetOpcode::G_FDIV
:
394 case TargetOpcode::G_FCONSTANT
:
395 case TargetOpcode::G_FPEXT
:
396 case TargetOpcode::G_FPTRUNC
:
397 case TargetOpcode::G_FCEIL
:
398 case TargetOpcode::G_FFLOOR
:
399 case TargetOpcode::G_FNEARBYINT
:
400 case TargetOpcode::G_FNEG
:
401 case TargetOpcode::G_FCOS
:
402 case TargetOpcode::G_FSIN
:
403 case TargetOpcode::G_FLOG10
:
404 case TargetOpcode::G_FLOG
:
405 case TargetOpcode::G_FLOG2
:
406 case TargetOpcode::G_FSQRT
:
407 case TargetOpcode::G_FABS
:
408 case TargetOpcode::G_FEXP
:
409 case TargetOpcode::G_FRINT
:
410 case TargetOpcode::G_INTRINSIC_TRUNC
:
411 case TargetOpcode::G_INTRINSIC_ROUND
:
417 const RegisterBankInfo::InstructionMapping
&
418 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
419 const MachineInstr
&MI
) const {
420 const unsigned Opc
= MI
.getOpcode();
421 const MachineFunction
&MF
= *MI
.getParent()->getParent();
422 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
424 unsigned NumOperands
= MI
.getNumOperands();
425 assert(NumOperands
<= 3 &&
426 "This code is for instructions with 3 or less operands");
428 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
429 unsigned Size
= Ty
.getSizeInBits();
430 bool IsFPR
= Ty
.isVector() || isPreISelGenericFloatingPointOpcode(Opc
);
432 PartialMappingIdx RBIdx
= IsFPR
? PMI_FirstFPR
: PMI_FirstGPR
;
435 // Make sure all the operands are using similar size and type.
436 // Should probably be checked by the machine verifier.
437 // This code won't catch cases where the number of lanes is
438 // different between the operands.
439 // If we want to go to that level of details, it is probably
440 // best to check that the types are the same, period.
441 // Currently, we just check that the register banks are the same
443 for (unsigned Idx
= 1; Idx
!= NumOperands
; ++Idx
) {
444 LLT OpTy
= MRI
.getType(MI
.getOperand(Idx
).getReg());
446 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
447 RBIdx
, OpTy
.getSizeInBits()) ==
448 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx
, Size
) &&
449 "Operand has incompatible size");
450 bool OpIsFPR
= OpTy
.isVector() || isPreISelGenericFloatingPointOpcode(Opc
);
452 assert(IsFPR
== OpIsFPR
&& "Operand has incompatible type");
454 #endif // End NDEBUG.
456 return getInstructionMapping(DefaultMappingID
, 1,
457 getValueMapping(RBIdx
, Size
), NumOperands
);
460 bool AArch64RegisterBankInfo::hasFPConstraints(
461 const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
,
462 const TargetRegisterInfo
&TRI
) const {
463 unsigned Op
= MI
.getOpcode();
465 // Do we have an explicit floating point instruction?
466 if (isPreISelGenericFloatingPointOpcode(Op
))
469 // No. Check if we have a copy-like instruction. If we do, then we could
470 // still be fed by floating point instructions.
471 if (Op
!= TargetOpcode::COPY
&& !MI
.isPHI())
474 // MI is copy-like. Return true if it outputs an FPR.
475 return getRegBank(MI
.getOperand(0).getReg(), MRI
, TRI
) ==
476 &AArch64::FPRRegBank
;
479 bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr
&MI
,
480 const MachineRegisterInfo
&MRI
,
481 const TargetRegisterInfo
&TRI
) const {
482 switch (MI
.getOpcode()) {
483 case TargetOpcode::G_FPTOSI
:
484 case TargetOpcode::G_FPTOUI
:
485 case TargetOpcode::G_FCMP
:
490 return hasFPConstraints(MI
, MRI
, TRI
);
493 bool AArch64RegisterBankInfo::onlyDefinesFP(
494 const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
,
495 const TargetRegisterInfo
&TRI
) const {
496 switch (MI
.getOpcode()) {
497 case TargetOpcode::G_SITOFP
:
498 case TargetOpcode::G_UITOFP
:
499 case TargetOpcode::G_EXTRACT_VECTOR_ELT
:
500 case TargetOpcode::G_INSERT_VECTOR_ELT
:
505 return hasFPConstraints(MI
, MRI
, TRI
);
508 const RegisterBankInfo::InstructionMapping
&
509 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
510 const unsigned Opc
= MI
.getOpcode();
512 // Try the default logic for non-generic instructions that are either copies
513 // or already have some operands assigned to banks.
514 if ((Opc
!= TargetOpcode::COPY
&& !isPreISelGenericOpcode(Opc
)) ||
515 Opc
== TargetOpcode::G_PHI
) {
516 const RegisterBankInfo::InstructionMapping
&Mapping
=
517 getInstrMappingImpl(MI
);
518 if (Mapping
.isValid())
522 const MachineFunction
&MF
= *MI
.getParent()->getParent();
523 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
524 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
525 const TargetRegisterInfo
&TRI
= *STI
.getRegisterInfo();
528 // G_{F|S|U}REM are not listed because they are not legal.
530 case TargetOpcode::G_ADD
:
531 case TargetOpcode::G_SUB
:
532 case TargetOpcode::G_GEP
:
533 case TargetOpcode::G_MUL
:
534 case TargetOpcode::G_SDIV
:
535 case TargetOpcode::G_UDIV
:
537 case TargetOpcode::G_AND
:
538 case TargetOpcode::G_OR
:
539 case TargetOpcode::G_XOR
:
540 // Floating point ops.
541 case TargetOpcode::G_FADD
:
542 case TargetOpcode::G_FSUB
:
543 case TargetOpcode::G_FMUL
:
544 case TargetOpcode::G_FDIV
:
545 return getSameKindOfOperandsMapping(MI
);
546 case TargetOpcode::G_FPEXT
: {
547 LLT DstTy
= MRI
.getType(MI
.getOperand(0).getReg());
548 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
549 return getInstructionMapping(
550 DefaultMappingID
, /*Cost*/ 1,
551 getFPExtMapping(DstTy
.getSizeInBits(), SrcTy
.getSizeInBits()),
555 case TargetOpcode::G_SHL
:
556 case TargetOpcode::G_LSHR
:
557 case TargetOpcode::G_ASHR
: {
558 LLT ShiftAmtTy
= MRI
.getType(MI
.getOperand(2).getReg());
559 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
560 if (ShiftAmtTy
.getSizeInBits() == 64 && SrcTy
.getSizeInBits() == 32)
561 return getInstructionMapping(DefaultMappingID
, 1,
562 &ValMappings
[Shift64Imm
], 3);
563 return getSameKindOfOperandsMapping(MI
);
565 case TargetOpcode::COPY
: {
566 Register DstReg
= MI
.getOperand(0).getReg();
567 Register SrcReg
= MI
.getOperand(1).getReg();
568 // Check if one of the register is not a generic register.
569 if ((Register::isPhysicalRegister(DstReg
) ||
570 !MRI
.getType(DstReg
).isValid()) ||
571 (Register::isPhysicalRegister(SrcReg
) ||
572 !MRI
.getType(SrcReg
).isValid())) {
573 const RegisterBank
*DstRB
= getRegBank(DstReg
, MRI
, TRI
);
574 const RegisterBank
*SrcRB
= getRegBank(SrcReg
, MRI
, TRI
);
579 // If both RB are null that means both registers are generic.
580 // We shouldn't be here.
581 assert(DstRB
&& SrcRB
&& "Both RegBank were nullptr");
582 unsigned Size
= getSizeInBits(DstReg
, MRI
, TRI
);
583 return getInstructionMapping(
584 DefaultMappingID
, copyCost(*DstRB
, *SrcRB
, Size
),
585 getCopyMapping(DstRB
->getID(), SrcRB
->getID(), Size
),
586 // We only care about the mapping of the destination.
589 // Both registers are generic, use G_BITCAST.
592 case TargetOpcode::G_BITCAST
: {
593 LLT DstTy
= MRI
.getType(MI
.getOperand(0).getReg());
594 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
595 unsigned Size
= DstTy
.getSizeInBits();
596 bool DstIsGPR
= !DstTy
.isVector() && DstTy
.getSizeInBits() <= 64;
597 bool SrcIsGPR
= !SrcTy
.isVector() && SrcTy
.getSizeInBits() <= 64;
598 const RegisterBank
&DstRB
=
599 DstIsGPR
? AArch64::GPRRegBank
: AArch64::FPRRegBank
;
600 const RegisterBank
&SrcRB
=
601 SrcIsGPR
? AArch64::GPRRegBank
: AArch64::FPRRegBank
;
602 return getInstructionMapping(
603 DefaultMappingID
, copyCost(DstRB
, SrcRB
, Size
),
604 getCopyMapping(DstRB
.getID(), SrcRB
.getID(), Size
),
605 // We only care about the mapping of the destination for COPY.
606 /*NumOperands*/ Opc
== TargetOpcode::G_BITCAST
? 2 : 1);
612 unsigned NumOperands
= MI
.getNumOperands();
614 // Track the size and bank of each register. We don't do partial mappings.
615 SmallVector
<unsigned, 4> OpSize(NumOperands
);
616 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
617 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
618 auto &MO
= MI
.getOperand(Idx
);
619 if (!MO
.isReg() || !MO
.getReg())
622 LLT Ty
= MRI
.getType(MO
.getReg());
623 OpSize
[Idx
] = Ty
.getSizeInBits();
625 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
626 // For floating-point instructions, scalars go in FPRs.
627 if (Ty
.isVector() || isPreISelGenericFloatingPointOpcode(Opc
) ||
628 Ty
.getSizeInBits() > 64)
629 OpRegBankIdx
[Idx
] = PMI_FirstFPR
;
631 OpRegBankIdx
[Idx
] = PMI_FirstGPR
;
635 // Some of the floating-point instructions have mixed GPR and FPR operands:
636 // fine-tune the computed mapping.
638 case TargetOpcode::G_TRUNC
: {
639 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
640 if (!SrcTy
.isVector() && SrcTy
.getSizeInBits() == 128)
641 OpRegBankIdx
= {PMI_FirstFPR
, PMI_FirstFPR
};
644 case TargetOpcode::G_SITOFP
:
645 case TargetOpcode::G_UITOFP
:
646 if (MRI
.getType(MI
.getOperand(0).getReg()).isVector())
648 OpRegBankIdx
= {PMI_FirstFPR
, PMI_FirstGPR
};
650 case TargetOpcode::G_FPTOSI
:
651 case TargetOpcode::G_FPTOUI
:
652 if (MRI
.getType(MI
.getOperand(0).getReg()).isVector())
654 OpRegBankIdx
= {PMI_FirstGPR
, PMI_FirstFPR
};
656 case TargetOpcode::G_FCMP
:
657 OpRegBankIdx
= {PMI_FirstGPR
,
658 /* Predicate */ PMI_None
, PMI_FirstFPR
, PMI_FirstFPR
};
660 case TargetOpcode::G_BITCAST
:
661 // This is going to be a cross register bank copy and this is expensive.
662 if (OpRegBankIdx
[0] != OpRegBankIdx
[1])
664 *AArch64GenRegisterBankInfo::PartMappings
[OpRegBankIdx
[0]].RegBank
,
665 *AArch64GenRegisterBankInfo::PartMappings
[OpRegBankIdx
[1]].RegBank
,
668 case TargetOpcode::G_LOAD
:
669 // Loading in vector unit is slightly more expensive.
670 // This is actually only true for the LD1R and co instructions,
671 // but anyway for the fast mode this number does not matter and
672 // for the greedy mode the cost of the cross bank copy will
673 // offset this number.
674 // FIXME: Should be derived from the scheduling model.
675 if (OpRegBankIdx
[0] != PMI_FirstGPR
)
678 // Check if that load feeds fp instructions.
679 // In that case, we want the default mapping to be on FPR
680 // instead of blind map every scalar to GPR.
681 for (const MachineInstr
&UseMI
:
682 MRI
.use_instructions(MI
.getOperand(0).getReg())) {
683 // If we have at least one direct use in a FP instruction,
684 // assume this was a floating point load in the IR.
685 // If it was not, we would have had a bitcast before
686 // reaching that instruction.
687 if (onlyUsesFP(UseMI
, MRI
, TRI
)) {
688 OpRegBankIdx
[0] = PMI_FirstFPR
;
693 case TargetOpcode::G_STORE
:
694 // Check if that store is fed by fp instructions.
695 if (OpRegBankIdx
[0] == PMI_FirstGPR
) {
696 Register VReg
= MI
.getOperand(0).getReg();
699 MachineInstr
*DefMI
= MRI
.getVRegDef(VReg
);
700 if (onlyDefinesFP(*DefMI
, MRI
, TRI
))
701 OpRegBankIdx
[0] = PMI_FirstFPR
;
705 case TargetOpcode::G_SELECT
: {
706 // If the destination is FPR, preserve that.
707 if (OpRegBankIdx
[0] != PMI_FirstGPR
)
710 // If we're taking in vectors, we have no choice but to put everything on
711 // FPRs, except for the condition. The condition must always be on a GPR.
712 LLT SrcTy
= MRI
.getType(MI
.getOperand(2).getReg());
713 if (SrcTy
.isVector()) {
714 OpRegBankIdx
= {PMI_FirstFPR
, PMI_FirstGPR
, PMI_FirstFPR
, PMI_FirstFPR
};
718 // Try to minimize the number of copies. If we have more floating point
719 // constrained values than not, then we'll put everything on FPR. Otherwise,
720 // everything has to be on GPR.
723 // Check if the uses of the result always produce floating point values.
727 // %z = G_SELECT %cond %x %y
728 // fpr = G_FOO %z ...
730 MRI
.use_instructions(MI
.getOperand(0).getReg()),
731 [&](MachineInstr
&MI
) { return onlyUsesFP(MI
, MRI
, TRI
); }))
734 // Check if the defs of the source values always produce floating point
739 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
740 // %z = G_SELECT %cond %x %y
742 // Also check whether or not the sources have already been decided to be
743 // FPR. Keep track of this.
745 // This doesn't check the condition, since it's just whatever is in NZCV.
746 // This isn't passed explicitly in a register to fcsel/csel.
747 for (unsigned Idx
= 2; Idx
< 4; ++Idx
) {
748 Register VReg
= MI
.getOperand(Idx
).getReg();
749 MachineInstr
*DefMI
= MRI
.getVRegDef(VReg
);
750 if (getRegBank(VReg
, MRI
, TRI
) == &AArch64::FPRRegBank
||
751 onlyDefinesFP(*DefMI
, MRI
, TRI
))
755 // If we have more FP constraints than not, then move everything over to
758 OpRegBankIdx
= {PMI_FirstFPR
, PMI_FirstGPR
, PMI_FirstFPR
, PMI_FirstFPR
};
762 case TargetOpcode::G_UNMERGE_VALUES
: {
763 // If the first operand belongs to a FPR register bank, then make sure that
765 if (OpRegBankIdx
[0] != PMI_FirstGPR
)
768 LLT SrcTy
= MRI
.getType(MI
.getOperand(MI
.getNumOperands()-1).getReg());
769 // UNMERGE into scalars from a vector should always use FPR.
770 // Likewise if any of the uses are FP instructions.
771 if (SrcTy
.isVector() || SrcTy
== LLT::scalar(128) ||
772 any_of(MRI
.use_instructions(MI
.getOperand(0).getReg()),
773 [&](MachineInstr
&MI
) { return onlyUsesFP(MI
, MRI
, TRI
); })) {
774 // Set the register bank of every operand to FPR.
775 for (unsigned Idx
= 0, NumOperands
= MI
.getNumOperands();
776 Idx
< NumOperands
; ++Idx
)
777 OpRegBankIdx
[Idx
] = PMI_FirstFPR
;
781 case TargetOpcode::G_EXTRACT_VECTOR_ELT
:
782 // Destination and source need to be FPRs.
783 OpRegBankIdx
[0] = PMI_FirstFPR
;
784 OpRegBankIdx
[1] = PMI_FirstFPR
;
786 // Index needs to be a GPR.
787 OpRegBankIdx
[2] = PMI_FirstGPR
;
789 case TargetOpcode::G_INSERT_VECTOR_ELT
:
790 OpRegBankIdx
[0] = PMI_FirstFPR
;
791 OpRegBankIdx
[1] = PMI_FirstFPR
;
793 // The element may be either a GPR or FPR. Preserve that behaviour.
794 if (getRegBank(MI
.getOperand(2).getReg(), MRI
, TRI
) == &AArch64::FPRRegBank
)
795 OpRegBankIdx
[2] = PMI_FirstFPR
;
797 OpRegBankIdx
[2] = PMI_FirstGPR
;
799 // Index needs to be a GPR.
800 OpRegBankIdx
[3] = PMI_FirstGPR
;
802 case TargetOpcode::G_EXTRACT
: {
803 // For s128 sources we have to use fpr.
804 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
805 if (SrcTy
.getSizeInBits() == 128) {
806 OpRegBankIdx
[0] = PMI_FirstFPR
;
807 OpRegBankIdx
[1] = PMI_FirstFPR
;
811 case TargetOpcode::G_BUILD_VECTOR
:
812 // If the first source operand belongs to a FPR register bank, then make
813 // sure that we preserve that.
814 if (OpRegBankIdx
[1] != PMI_FirstGPR
)
816 Register VReg
= MI
.getOperand(1).getReg();
820 // Get the instruction that defined the source operand reg, and check if
821 // it's a floating point operation. Or, if it's a type like s16 which
822 // doesn't have a exact size gpr register class.
823 MachineInstr
*DefMI
= MRI
.getVRegDef(VReg
);
824 unsigned DefOpc
= DefMI
->getOpcode();
825 const LLT SrcTy
= MRI
.getType(VReg
);
826 if (isPreISelGenericFloatingPointOpcode(DefOpc
) ||
827 SrcTy
.getSizeInBits() < 32) {
828 // Have a floating point op.
829 // Make sure every operand gets mapped to a FPR register class.
830 unsigned NumOperands
= MI
.getNumOperands();
831 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
)
832 OpRegBankIdx
[Idx
] = PMI_FirstFPR
;
837 // Finally construct the computed mapping.
838 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
839 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
840 if (MI
.getOperand(Idx
).isReg() && MI
.getOperand(Idx
).getReg()) {
841 auto Mapping
= getValueMapping(OpRegBankIdx
[Idx
], OpSize
[Idx
]);
842 if (!Mapping
->isValid())
843 return getInvalidInstructionMapping();
845 OpdsMapping
[Idx
] = Mapping
;
849 return getInstructionMapping(DefaultMappingID
, Cost
,
850 getOperandsMapping(OpdsMapping
), NumOperands
);