xref: /llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp (revision f71cb9dbb739bb58ce7e52e49fe384ff2ff11687)
1009cd4e4SKit Barton //===- PPCRegisterBankInfo.cpp --------------------------------------------===//
2009cd4e4SKit Barton //
3009cd4e4SKit Barton // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4009cd4e4SKit Barton // See https://llvm.org/LICENSE.txt for license information.
5009cd4e4SKit Barton // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009cd4e4SKit Barton //
7009cd4e4SKit Barton //===----------------------------------------------------------------------===//
8009cd4e4SKit Barton /// \file
9009cd4e4SKit Barton /// This file implements the targeting of the RegisterBankInfo class for
10009cd4e4SKit Barton /// PowerPC.
11009cd4e4SKit Barton //===----------------------------------------------------------------------===//
12009cd4e4SKit Barton 
13009cd4e4SKit Barton #include "PPCRegisterBankInfo.h"
14009cd4e4SKit Barton #include "PPCRegisterInfo.h"
157c760b22SSameer Sahasrabuddhe #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
1692e96c7bSMalay Sanghi #include "llvm/CodeGen/GlobalISel/Utils.h"
17009cd4e4SKit Barton #include "llvm/CodeGen/MachineFunction.h"
18009cd4e4SKit Barton #include "llvm/CodeGen/MachineRegisterInfo.h"
19009cd4e4SKit Barton 
20009cd4e4SKit Barton #define DEBUG_TYPE "ppc-reg-bank-info"
21009cd4e4SKit Barton 
22009cd4e4SKit Barton #define GET_TARGET_REGBANK_IMPL
23009cd4e4SKit Barton #include "PPCGenRegisterBank.inc"
24009cd4e4SKit Barton 
25be4a1dfbSKai Nacke // This file will be TableGen'ed at some point.
26be4a1dfbSKai Nacke #include "PPCGenRegisterBankInfo.def"
27be4a1dfbSKai Nacke 
28009cd4e4SKit Barton using namespace llvm;
29009cd4e4SKit Barton 
3062128719SKazu Hirata PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}
31be4a1dfbSKai Nacke 
32be4a1dfbSKai Nacke const RegisterBank &
33be4a1dfbSKai Nacke PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
34be4a1dfbSKai Nacke                                             LLT Ty) const {
35be4a1dfbSKai Nacke   switch (RC.getID()) {
36d9143ce3SChen Zheng   case PPC::VSFRCRegClassID:
37d9143ce3SChen Zheng   case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
38d9143ce3SChen Zheng   case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
39d9143ce3SChen Zheng   case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
40d9143ce3SChen Zheng   case PPC::F8RCRegClassID:
41d9143ce3SChen Zheng   case PPC::VFRCRegClassID:
42d9143ce3SChen Zheng   case PPC::VSSRCRegClassID:
43d9143ce3SChen Zheng   case PPC::F4RCRegClassID:
44d9143ce3SChen Zheng     return getRegBank(PPC::FPRRegBankID);
45be4a1dfbSKai Nacke   default:
46*a79db96eSKai Nacke     return PPCGenRegisterBankInfo::getRegBankFromRegClass(RC, Ty);
47be4a1dfbSKai Nacke   }
48be4a1dfbSKai Nacke }
49be4a1dfbSKai Nacke 
50be4a1dfbSKai Nacke const RegisterBankInfo::InstructionMapping &
51be4a1dfbSKai Nacke PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
52be4a1dfbSKai Nacke   const unsigned Opc = MI.getOpcode();
53be4a1dfbSKai Nacke 
54be4a1dfbSKai Nacke   // Try the default logic for non-generic instructions that are either copies
55be4a1dfbSKai Nacke   // or already have some operands assigned to banks.
56be4a1dfbSKai Nacke   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
57be4a1dfbSKai Nacke     const RegisterBankInfo::InstructionMapping &Mapping =
58be4a1dfbSKai Nacke         getInstrMappingImpl(MI);
59be4a1dfbSKai Nacke     if (Mapping.isValid())
60be4a1dfbSKai Nacke       return Mapping;
61be4a1dfbSKai Nacke   }
62be4a1dfbSKai Nacke 
63d9143ce3SChen Zheng   const MachineFunction &MF = *MI.getParent()->getParent();
64d9143ce3SChen Zheng   const MachineRegisterInfo &MRI = MF.getRegInfo();
65d9143ce3SChen Zheng   const TargetSubtargetInfo &STI = MF.getSubtarget();
66d9143ce3SChen Zheng   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
67d9143ce3SChen Zheng 
68be4a1dfbSKai Nacke   unsigned NumOperands = MI.getNumOperands();
69be4a1dfbSKai Nacke   const ValueMapping *OperandsMapping = nullptr;
70be4a1dfbSKai Nacke   unsigned Cost = 1;
71be4a1dfbSKai Nacke   unsigned MappingID = DefaultMappingID;
72be4a1dfbSKai Nacke 
73be4a1dfbSKai Nacke   switch (Opc) {
742b1e895aSKai Nacke     // Arithmetic ops.
752b1e895aSKai Nacke   case TargetOpcode::G_ADD:
762b1e895aSKai Nacke   case TargetOpcode::G_SUB:
77be4a1dfbSKai Nacke     // Bitwise ops.
78be4a1dfbSKai Nacke   case TargetOpcode::G_AND:
79be4a1dfbSKai Nacke   case TargetOpcode::G_OR:
80be4a1dfbSKai Nacke   case TargetOpcode::G_XOR:
81b41d22dbSChen Zheng     // Extension ops.
82b41d22dbSChen Zheng   case TargetOpcode::G_SEXT:
83b41d22dbSChen Zheng   case TargetOpcode::G_ZEXT:
843508f123SAmy Kwan   case TargetOpcode::G_ANYEXT: {
85be4a1dfbSKai Nacke     assert(NumOperands <= 3 &&
86be4a1dfbSKai Nacke            "This code is for instructions with 3 or less operands");
873508f123SAmy Kwan     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
883508f123SAmy Kwan     unsigned Size = Ty.getSizeInBits();
893508f123SAmy Kwan     switch (Size) {
903508f123SAmy Kwan     case 128:
913508f123SAmy Kwan       OperandsMapping = getValueMapping(PMI_VEC128);
923508f123SAmy Kwan       break;
933508f123SAmy Kwan     default:
94be4a1dfbSKai Nacke       OperandsMapping = getValueMapping(PMI_GPR64);
95be4a1dfbSKai Nacke       break;
963508f123SAmy Kwan     }
973508f123SAmy Kwan     break;
983508f123SAmy Kwan   }
99d9143ce3SChen Zheng   case TargetOpcode::G_FADD:
100d9143ce3SChen Zheng   case TargetOpcode::G_FSUB:
101d9143ce3SChen Zheng   case TargetOpcode::G_FMUL:
102d9143ce3SChen Zheng   case TargetOpcode::G_FDIV: {
103d9143ce3SChen Zheng     Register SrcReg = MI.getOperand(1).getReg();
104d9143ce3SChen Zheng     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
105d9143ce3SChen Zheng 
1063508f123SAmy Kwan     assert((Size == 32 || Size == 64 || Size == 128) &&
1073508f123SAmy Kwan            "Unsupported floating point types!\n");
1083508f123SAmy Kwan     switch (Size) {
1093508f123SAmy Kwan     case 32:
1103508f123SAmy Kwan       OperandsMapping = getValueMapping(PMI_FPR32);
1113508f123SAmy Kwan       break;
1123508f123SAmy Kwan     case 64:
1133508f123SAmy Kwan       OperandsMapping = getValueMapping(PMI_FPR64);
1143508f123SAmy Kwan       break;
1153508f123SAmy Kwan     case 128:
1163508f123SAmy Kwan       OperandsMapping = getValueMapping(PMI_VEC128);
1173508f123SAmy Kwan       break;
1183508f123SAmy Kwan     }
119d9143ce3SChen Zheng     break;
120d9143ce3SChen Zheng   }
121ac93a4e7SChen Zheng   case TargetOpcode::G_FCMP: {
122ac93a4e7SChen Zheng     unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
123ac93a4e7SChen Zheng 
124ac93a4e7SChen Zheng     OperandsMapping = getOperandsMapping(
125ac93a4e7SChen Zheng         {getValueMapping(PMI_CR), nullptr,
126ac93a4e7SChen Zheng          getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
127ac93a4e7SChen Zheng          getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
128ac93a4e7SChen Zheng     break;
129ac93a4e7SChen Zheng   }
130be4a1dfbSKai Nacke   case TargetOpcode::G_CONSTANT:
131be4a1dfbSKai Nacke     OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
132be4a1dfbSKai Nacke     break;
1336ee2f770SChen Zheng   case TargetOpcode::G_CONSTANT_POOL:
1346ee2f770SChen Zheng     OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
1356ee2f770SChen Zheng     break;
1360a9b1c59SChen Zheng   case TargetOpcode::G_FPTOUI:
1370a9b1c59SChen Zheng   case TargetOpcode::G_FPTOSI: {
1380a9b1c59SChen Zheng     Register SrcReg = MI.getOperand(1).getReg();
1390a9b1c59SChen Zheng     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
1400a9b1c59SChen Zheng 
1410a9b1c59SChen Zheng     OperandsMapping = getOperandsMapping(
1420a9b1c59SChen Zheng         {getValueMapping(PMI_GPR64),
1430a9b1c59SChen Zheng          getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});
1440a9b1c59SChen Zheng     break;
1450a9b1c59SChen Zheng   }
1460a9b1c59SChen Zheng   case TargetOpcode::G_UITOFP:
1470a9b1c59SChen Zheng   case TargetOpcode::G_SITOFP: {
1480a9b1c59SChen Zheng     Register SrcReg = MI.getOperand(0).getReg();
1490a9b1c59SChen Zheng     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
1500a9b1c59SChen Zheng 
1510a9b1c59SChen Zheng     OperandsMapping =
1520a9b1c59SChen Zheng         getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),
1530a9b1c59SChen Zheng                             getValueMapping(PMI_GPR64)});
1540a9b1c59SChen Zheng     break;
1550a9b1c59SChen Zheng   }
156503a935dSChen Zheng   case TargetOpcode::G_LOAD: {
157b41d22dbSChen Zheng     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
158503a935dSChen Zheng     // Check if that load feeds fp instructions.
159503a935dSChen Zheng     if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
160503a935dSChen Zheng                [&](const MachineInstr &UseMI) {
161503a935dSChen Zheng                  // If we have at least one direct use in a FP instruction,
162503a935dSChen Zheng                  // assume this was a floating point load in the IR. If it was
163503a935dSChen Zheng                  // not, we would have had a bitcast before reaching that
164503a935dSChen Zheng                  // instruction.
165503a935dSChen Zheng                  //
166503a935dSChen Zheng                  // Int->FP conversion operations are also captured in
167503a935dSChen Zheng                  // onlyDefinesFP().
168503a935dSChen Zheng                  return onlyUsesFP(UseMI, MRI, TRI);
169503a935dSChen Zheng                }))
170503a935dSChen Zheng       OperandsMapping = getOperandsMapping(
171b41d22dbSChen Zheng           {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
172b41d22dbSChen Zheng            getValueMapping(PMI_GPR64)});
173503a935dSChen Zheng     else
174503a935dSChen Zheng       OperandsMapping = getOperandsMapping(
175b41d22dbSChen Zheng           {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
176b41d22dbSChen Zheng            getValueMapping(PMI_GPR64)});
177503a935dSChen Zheng     break;
178503a935dSChen Zheng   }
179503a935dSChen Zheng   case TargetOpcode::G_STORE: {
180503a935dSChen Zheng     // Check if the store is fed by fp instructions.
181503a935dSChen Zheng     MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
182b41d22dbSChen Zheng     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
183503a935dSChen Zheng     if (onlyDefinesFP(*DefMI, MRI, TRI))
184503a935dSChen Zheng       OperandsMapping = getOperandsMapping(
185b41d22dbSChen Zheng           {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
186b41d22dbSChen Zheng            getValueMapping(PMI_GPR64)});
187503a935dSChen Zheng     else
188503a935dSChen Zheng       OperandsMapping = getOperandsMapping(
189b41d22dbSChen Zheng           {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
190b41d22dbSChen Zheng            getValueMapping(PMI_GPR64)});
191503a935dSChen Zheng     break;
192503a935dSChen Zheng   }
193d9630c34SKai Luo   case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
194d9630c34SKai Luo     // FIXME: We have to check every operand in this MI and compute value
195d9630c34SKai Luo     // mapping accordingly.
196d9630c34SKai Luo     SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
197d9630c34SKai Luo     OperandsMapping = getOperandsMapping(OpdsMapping);
198d9630c34SKai Luo     break;
199d9630c34SKai Luo   }
2003508f123SAmy Kwan   case TargetOpcode::G_BITCAST: {
2013508f123SAmy Kwan     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
2023508f123SAmy Kwan     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
2033508f123SAmy Kwan     unsigned DstSize = DstTy.getSizeInBits();
2043508f123SAmy Kwan 
2053508f123SAmy Kwan     bool DstIsGPR = !DstTy.isVector();
2063508f123SAmy Kwan     bool SrcIsGPR = !SrcTy.isVector();
2073508f123SAmy Kwan     // TODO: Currently, only vector and GPR register banks are handled.
2083508f123SAmy Kwan     //       This needs to be extended to handle floating point register
2093508f123SAmy Kwan     //       banks in the future.
2103508f123SAmy Kwan     const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
2113508f123SAmy Kwan     const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
2123508f123SAmy Kwan 
2133508f123SAmy Kwan     return getInstructionMapping(
2143508f123SAmy Kwan         MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
2153508f123SAmy Kwan         NumOperands);
2163508f123SAmy Kwan   }
217be4a1dfbSKai Nacke   default:
218be4a1dfbSKai Nacke     return getInvalidInstructionMapping();
219be4a1dfbSKai Nacke   }
220be4a1dfbSKai Nacke 
221be4a1dfbSKai Nacke   return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
222be4a1dfbSKai Nacke }
223be4a1dfbSKai Nacke 
224503a935dSChen Zheng /// \returns true if a given intrinsic \p ID only uses and defines FPRs.
225503a935dSChen Zheng static bool isFPIntrinsic(unsigned ID) {
226503a935dSChen Zheng   // TODO: Add more intrinsics.
227503a935dSChen Zheng   return false;
228503a935dSChen Zheng }
229503a935dSChen Zheng 
230503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to
231503a935dSChen Zheng /// put this function in class RegisterBankInfo.
232503a935dSChen Zheng bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
233503a935dSChen Zheng                                            const MachineRegisterInfo &MRI,
234503a935dSChen Zheng                                            const TargetRegisterInfo &TRI,
235503a935dSChen Zheng                                            unsigned Depth) const {
236503a935dSChen Zheng   unsigned Op = MI.getOpcode();
2377c760b22SSameer Sahasrabuddhe 
2387c760b22SSameer Sahasrabuddhe   if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
2397c760b22SSameer Sahasrabuddhe     if (isFPIntrinsic(GI->getIntrinsicID()))
240503a935dSChen Zheng       return true;
2417c760b22SSameer Sahasrabuddhe   }
242503a935dSChen Zheng 
243503a935dSChen Zheng   // Do we have an explicit floating point instruction?
244503a935dSChen Zheng   if (isPreISelGenericFloatingPointOpcode(Op))
245503a935dSChen Zheng     return true;
246503a935dSChen Zheng 
247503a935dSChen Zheng   // No. Check if we have a copy-like instruction. If we do, then we could
248503a935dSChen Zheng   // still be fed by floating point instructions.
249503a935dSChen Zheng   if (Op != TargetOpcode::COPY && !MI.isPHI() &&
250503a935dSChen Zheng       !isPreISelGenericOptimizationHint(Op))
251503a935dSChen Zheng     return false;
252503a935dSChen Zheng 
253503a935dSChen Zheng   // Check if we already know the register bank.
254503a935dSChen Zheng   auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
255503a935dSChen Zheng   if (RB == &PPC::FPRRegBank)
256503a935dSChen Zheng     return true;
257503a935dSChen Zheng   if (RB == &PPC::GPRRegBank)
258503a935dSChen Zheng     return false;
259503a935dSChen Zheng 
260503a935dSChen Zheng   // We don't know anything.
261503a935dSChen Zheng   //
262503a935dSChen Zheng   // If we have a phi, we may be able to infer that it will be assigned a FPR
263503a935dSChen Zheng   // based off of its inputs.
264503a935dSChen Zheng   if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
265503a935dSChen Zheng     return false;
266503a935dSChen Zheng 
267503a935dSChen Zheng   return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
268503a935dSChen Zheng     return Op.isReg() &&
269503a935dSChen Zheng            onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
270503a935dSChen Zheng   });
271503a935dSChen Zheng }
272503a935dSChen Zheng 
273503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to
274503a935dSChen Zheng /// put this function in class RegisterBankInfo.
275503a935dSChen Zheng bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
276503a935dSChen Zheng                                      const MachineRegisterInfo &MRI,
277503a935dSChen Zheng                                      const TargetRegisterInfo &TRI,
278503a935dSChen Zheng                                      unsigned Depth) const {
279503a935dSChen Zheng   switch (MI.getOpcode()) {
280503a935dSChen Zheng   case TargetOpcode::G_FPTOSI:
281503a935dSChen Zheng   case TargetOpcode::G_FPTOUI:
282503a935dSChen Zheng   case TargetOpcode::G_FCMP:
283503a935dSChen Zheng   case TargetOpcode::G_LROUND:
284503a935dSChen Zheng   case TargetOpcode::G_LLROUND:
285503a935dSChen Zheng     return true;
286503a935dSChen Zheng   default:
287503a935dSChen Zheng     break;
288503a935dSChen Zheng   }
289503a935dSChen Zheng   return hasFPConstraints(MI, MRI, TRI, Depth);
290503a935dSChen Zheng }
291503a935dSChen Zheng 
292503a935dSChen Zheng /// FIXME: this is copied from target AArch64. Needs some code refactor here to
293503a935dSChen Zheng /// put this function in class RegisterBankInfo.
294503a935dSChen Zheng bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
295503a935dSChen Zheng                                         const MachineRegisterInfo &MRI,
296503a935dSChen Zheng                                         const TargetRegisterInfo &TRI,
297503a935dSChen Zheng                                         unsigned Depth) const {
298503a935dSChen Zheng   switch (MI.getOpcode()) {
299503a935dSChen Zheng   case TargetOpcode::G_SITOFP:
300503a935dSChen Zheng   case TargetOpcode::G_UITOFP:
301503a935dSChen Zheng     return true;
302503a935dSChen Zheng   default:
303503a935dSChen Zheng     break;
304503a935dSChen Zheng   }
305503a935dSChen Zheng   return hasFPConstraints(MI, MRI, TRI, Depth);
306503a935dSChen Zheng }
307503a935dSChen Zheng 
308be4a1dfbSKai Nacke RegisterBankInfo::InstructionMappings
309be4a1dfbSKai Nacke PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
310be4a1dfbSKai Nacke   // TODO Implement.
311be4a1dfbSKai Nacke   return RegisterBankInfo::getInstrAlternativeMappings(MI);
312be4a1dfbSKai Nacke }
313