[Darwin][Driver][clang] apple-none-macho orders the resource directory after internal...
[llvm-project.git] / llvm / lib / Target / PowerPC / GISel / PPCRegisterBankInfo.cpp
blob3370dedbecb16bf885756ab5c5d7f4eb724a69c6
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 //===----------------------------------------------------------------------===//
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"
20 #define DEBUG_TYPE "ppc-reg-bank-info"
22 #define GET_TARGET_REGBANK_IMPL
23 #include "PPCGenRegisterBank.inc"
25 // This file will be TableGen'ed at some point.
26 #include "PPCGenRegisterBankInfo.def"
28 using namespace llvm;
30 PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}
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);
50 const RegisterBankInfo::InstructionMapping &
51 PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
52 const unsigned Opc = MI.getOpcode();
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;
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();
68 unsigned NumOperands = MI.getNumOperands();
69 const ValueMapping *OperandsMapping = nullptr;
70 unsigned Cost = 1;
71 unsigned MappingID = DefaultMappingID;
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;
97 break;
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);
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;
119 break;
121 case TargetOpcode::G_FCMP: {
122 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
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;
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);
141 OperandsMapping = getOperandsMapping(
142 {getValueMapping(PMI_GPR64),
143 getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});
144 break;
146 case TargetOpcode::G_UITOFP:
147 case TargetOpcode::G_SITOFP: {
148 Register SrcReg = MI.getOperand(0).getReg();
149 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
151 OperandsMapping =
152 getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),
153 getValueMapping(PMI_GPR64)});
154 break;
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.
166 // Int->FP conversion operations are also captured in
167 // onlyDefinesFP().
168 return onlyUsesFP(UseMI, MRI, TRI);
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;
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;
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;
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();
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;
213 return getInstructionMapping(
214 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
215 NumOperands);
217 default:
218 return getInvalidInstructionMapping();
221 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
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;
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();
238 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
239 if (isFPIntrinsic(GI->getIntrinsicID()))
240 return true;
243 // Do we have an explicit floating point instruction?
244 if (isPreISelGenericFloatingPointOpcode(Op))
245 return true;
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;
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;
260 // We don't know anything.
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;
267 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
268 return Op.isReg() &&
269 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
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;
289 return hasFPConstraints(MI, MRI, TRI, Depth);
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;
305 return hasFPConstraints(MI, MRI, TRI, Depth);
308 RegisterBankInfo::InstructionMappings
309 PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
310 // TODO Implement.
311 return RegisterBankInfo::getInstrAlternativeMappings(MI);