xref: /llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp (revision f71cb9dbb739bb58ce7e52e49fe384ff2ff11687)
1 //===- PPCRegisterBankInfo.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 /// PowerPC.
11 //===----------------------------------------------------------------------===//
12 
13 #include "PPCRegisterBankInfo.h"
14 #include "PPCRegisterInfo.h"
15 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
16 #include "llvm/CodeGen/GlobalISel/Utils.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 
20 #define DEBUG_TYPE "ppc-reg-bank-info"
21 
22 #define GET_TARGET_REGBANK_IMPL
23 #include "PPCGenRegisterBank.inc"
24 
25 // This file will be TableGen'ed at some point.
26 #include "PPCGenRegisterBankInfo.def"
27 
28 using namespace llvm;
29 
30 PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}
31 
32 const RegisterBank &
33 PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
34                                             LLT Ty) const {
35   switch (RC.getID()) {
36   case PPC::VSFRCRegClassID:
37   case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
38   case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
39   case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
40   case PPC::F8RCRegClassID:
41   case PPC::VFRCRegClassID:
42   case PPC::VSSRCRegClassID:
43   case PPC::F4RCRegClassID:
44     return getRegBank(PPC::FPRRegBankID);
45   default:
46     return PPCGenRegisterBankInfo::getRegBankFromRegClass(RC, Ty);
47   }
48 }
49 
50 const RegisterBankInfo::InstructionMapping &
51 PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
52   const unsigned Opc = MI.getOpcode();
53 
54   // Try the default logic for non-generic instructions that are either copies
55   // or already have some operands assigned to banks.
56   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
57     const RegisterBankInfo::InstructionMapping &Mapping =
58         getInstrMappingImpl(MI);
59     if (Mapping.isValid())
60       return Mapping;
61   }
62 
63   const MachineFunction &MF = *MI.getParent()->getParent();
64   const MachineRegisterInfo &MRI = MF.getRegInfo();
65   const TargetSubtargetInfo &STI = MF.getSubtarget();
66   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
67 
68   unsigned NumOperands = MI.getNumOperands();
69   const ValueMapping *OperandsMapping = nullptr;
70   unsigned Cost = 1;
71   unsigned MappingID = DefaultMappingID;
72 
73   switch (Opc) {
74     // Arithmetic ops.
75   case TargetOpcode::G_ADD:
76   case TargetOpcode::G_SUB:
77     // Bitwise ops.
78   case TargetOpcode::G_AND:
79   case TargetOpcode::G_OR:
80   case TargetOpcode::G_XOR:
81     // Extension ops.
82   case TargetOpcode::G_SEXT:
83   case TargetOpcode::G_ZEXT:
84   case TargetOpcode::G_ANYEXT: {
85     assert(NumOperands <= 3 &&
86            "This code is for instructions with 3 or less operands");
87     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
88     unsigned Size = Ty.getSizeInBits();
89     switch (Size) {
90     case 128:
91       OperandsMapping = getValueMapping(PMI_VEC128);
92       break;
93     default:
94       OperandsMapping = getValueMapping(PMI_GPR64);
95       break;
96     }
97     break;
98   }
99   case TargetOpcode::G_FADD:
100   case TargetOpcode::G_FSUB:
101   case TargetOpcode::G_FMUL:
102   case TargetOpcode::G_FDIV: {
103     Register SrcReg = MI.getOperand(1).getReg();
104     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
105 
106     assert((Size == 32 || Size == 64 || Size == 128) &&
107            "Unsupported floating point types!\n");
108     switch (Size) {
109     case 32:
110       OperandsMapping = getValueMapping(PMI_FPR32);
111       break;
112     case 64:
113       OperandsMapping = getValueMapping(PMI_FPR64);
114       break;
115     case 128:
116       OperandsMapping = getValueMapping(PMI_VEC128);
117       break;
118     }
119     break;
120   }
121   case TargetOpcode::G_FCMP: {
122     unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
123 
124     OperandsMapping = getOperandsMapping(
125         {getValueMapping(PMI_CR), nullptr,
126          getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
127          getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
128     break;
129   }
130   case TargetOpcode::G_CONSTANT:
131     OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
132     break;
133   case TargetOpcode::G_CONSTANT_POOL:
134     OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
135     break;
136   case TargetOpcode::G_FPTOUI:
137   case TargetOpcode::G_FPTOSI: {
138     Register SrcReg = MI.getOperand(1).getReg();
139     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
140 
141     OperandsMapping = getOperandsMapping(
142         {getValueMapping(PMI_GPR64),
143          getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});
144     break;
145   }
146   case TargetOpcode::G_UITOFP:
147   case TargetOpcode::G_SITOFP: {
148     Register SrcReg = MI.getOperand(0).getReg();
149     unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
150 
151     OperandsMapping =
152         getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),
153                             getValueMapping(PMI_GPR64)});
154     break;
155   }
156   case TargetOpcode::G_LOAD: {
157     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
158     // Check if that load feeds fp instructions.
159     if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
160                [&](const MachineInstr &UseMI) {
161                  // If we have at least one direct use in a FP instruction,
162                  // assume this was a floating point load in the IR. If it was
163                  // not, we would have had a bitcast before reaching that
164                  // instruction.
165                  //
166                  // Int->FP conversion operations are also captured in
167                  // onlyDefinesFP().
168                  return onlyUsesFP(UseMI, MRI, TRI);
169                }))
170       OperandsMapping = getOperandsMapping(
171           {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
172            getValueMapping(PMI_GPR64)});
173     else
174       OperandsMapping = getOperandsMapping(
175           {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
176            getValueMapping(PMI_GPR64)});
177     break;
178   }
179   case TargetOpcode::G_STORE: {
180     // Check if the store is fed by fp instructions.
181     MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
182     unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
183     if (onlyDefinesFP(*DefMI, MRI, TRI))
184       OperandsMapping = getOperandsMapping(
185           {getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
186            getValueMapping(PMI_GPR64)});
187     else
188       OperandsMapping = getOperandsMapping(
189           {getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
190            getValueMapping(PMI_GPR64)});
191     break;
192   }
193   case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
194     // FIXME: We have to check every operand in this MI and compute value
195     // mapping accordingly.
196     SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
197     OperandsMapping = getOperandsMapping(OpdsMapping);
198     break;
199   }
200   case TargetOpcode::G_BITCAST: {
201     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
202     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
203     unsigned DstSize = DstTy.getSizeInBits();
204 
205     bool DstIsGPR = !DstTy.isVector();
206     bool SrcIsGPR = !SrcTy.isVector();
207     // TODO: Currently, only vector and GPR register banks are handled.
208     //       This needs to be extended to handle floating point register
209     //       banks in the future.
210     const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
211     const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
212 
213     return getInstructionMapping(
214         MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
215         NumOperands);
216   }
217   default:
218     return getInvalidInstructionMapping();
219   }
220 
221   return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
222 }
223 
224 /// \returns true if a given intrinsic \p ID only uses and defines FPRs.
225 static bool isFPIntrinsic(unsigned ID) {
226   // TODO: Add more intrinsics.
227   return false;
228 }
229 
230 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
231 /// put this function in class RegisterBankInfo.
232 bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
233                                            const MachineRegisterInfo &MRI,
234                                            const TargetRegisterInfo &TRI,
235                                            unsigned Depth) const {
236   unsigned Op = MI.getOpcode();
237 
238   if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
239     if (isFPIntrinsic(GI->getIntrinsicID()))
240       return true;
241   }
242 
243   // Do we have an explicit floating point instruction?
244   if (isPreISelGenericFloatingPointOpcode(Op))
245     return true;
246 
247   // No. Check if we have a copy-like instruction. If we do, then we could
248   // still be fed by floating point instructions.
249   if (Op != TargetOpcode::COPY && !MI.isPHI() &&
250       !isPreISelGenericOptimizationHint(Op))
251     return false;
252 
253   // Check if we already know the register bank.
254   auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
255   if (RB == &PPC::FPRRegBank)
256     return true;
257   if (RB == &PPC::GPRRegBank)
258     return false;
259 
260   // We don't know anything.
261   //
262   // If we have a phi, we may be able to infer that it will be assigned a FPR
263   // based off of its inputs.
264   if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
265     return false;
266 
267   return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
268     return Op.isReg() &&
269            onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
270   });
271 }
272 
273 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
274 /// put this function in class RegisterBankInfo.
275 bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
276                                      const MachineRegisterInfo &MRI,
277                                      const TargetRegisterInfo &TRI,
278                                      unsigned Depth) const {
279   switch (MI.getOpcode()) {
280   case TargetOpcode::G_FPTOSI:
281   case TargetOpcode::G_FPTOUI:
282   case TargetOpcode::G_FCMP:
283   case TargetOpcode::G_LROUND:
284   case TargetOpcode::G_LLROUND:
285     return true;
286   default:
287     break;
288   }
289   return hasFPConstraints(MI, MRI, TRI, Depth);
290 }
291 
292 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
293 /// put this function in class RegisterBankInfo.
294 bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
295                                         const MachineRegisterInfo &MRI,
296                                         const TargetRegisterInfo &TRI,
297                                         unsigned Depth) const {
298   switch (MI.getOpcode()) {
299   case TargetOpcode::G_SITOFP:
300   case TargetOpcode::G_UITOFP:
301     return true;
302   default:
303     break;
304   }
305   return hasFPConstraints(MI, MRI, TRI, Depth);
306 }
307 
308 RegisterBankInfo::InstructionMappings
309 PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
310   // TODO Implement.
311   return RegisterBankInfo::getInstrAlternativeMappings(MI);
312 }
313