]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/X86/X86RegisterBankInfo.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / X86 / X86RegisterBankInfo.cpp
1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
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 X86.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12
13 #include "X86RegisterBankInfo.h"
14 #include "X86InstrInfo.h"
15 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
16 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/TargetRegisterInfo.h"
19
20 #define GET_TARGET_REGBANK_IMPL
21 #include "X86GenRegisterBank.inc"
22
23 using namespace llvm;
24 // This file will be TableGen'ed at some point.
25 #define GET_TARGET_REGBANK_INFO_IMPL
26 #include "X86GenRegisterBankInfo.def"
27
28 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI)
29     : X86GenRegisterBankInfo() {
30
31   // validate RegBank initialization.
32   const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
33   (void)RBGPR;
34   assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
35
36   // The GPR register bank is fully defined by all the registers in
37   // GR64 + its subclasses.
38   assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
39          "Subclass not added?");
40   assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
41 }
42
43 const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass(
44     const TargetRegisterClass &RC) const {
45
46   if (X86::GR8RegClass.hasSubClassEq(&RC) ||
47       X86::GR16RegClass.hasSubClassEq(&RC) ||
48       X86::GR32RegClass.hasSubClassEq(&RC) ||
49       X86::GR64RegClass.hasSubClassEq(&RC))
50     return getRegBank(X86::GPRRegBankID);
51
52   if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
53       X86::FR64XRegClass.hasSubClassEq(&RC) ||
54       X86::VR128XRegClass.hasSubClassEq(&RC) ||
55       X86::VR256XRegClass.hasSubClassEq(&RC) ||
56       X86::VR512RegClass.hasSubClassEq(&RC))
57     return getRegBank(X86::VECRRegBankID);
58
59   llvm_unreachable("Unsupported register kind yet.");
60 }
61
62 X86GenRegisterBankInfo::PartialMappingIdx
63 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
64   if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
65     switch (Ty.getSizeInBits()) {
66     case 1:
67     case 8:
68       return PMI_GPR8;
69     case 16:
70       return PMI_GPR16;
71     case 32:
72       return PMI_GPR32;
73     case 64:
74       return PMI_GPR64;
75     case 128:
76       return PMI_VEC128;
77       break;
78     default:
79       llvm_unreachable("Unsupported register size.");
80     }
81   } else if (Ty.isScalar()) {
82     switch (Ty.getSizeInBits()) {
83     case 32:
84       return PMI_FP32;
85     case 64:
86       return PMI_FP64;
87     case 128:
88       return PMI_VEC128;
89     default:
90       llvm_unreachable("Unsupported register size.");
91     }
92   } else {
93     switch (Ty.getSizeInBits()) {
94     case 128:
95       return PMI_VEC128;
96     case 256:
97       return PMI_VEC256;
98     case 512:
99       return PMI_VEC512;
100     default:
101       llvm_unreachable("Unsupported register size.");
102     }
103   }
104
105   return PMI_None;
106 }
107
108 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
109     const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
110     SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
111
112   unsigned NumOperands = MI.getNumOperands();
113   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
114     auto &MO = MI.getOperand(Idx);
115     if (!MO.isReg())
116       OpRegBankIdx[Idx] = PMI_None;
117     else
118       OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
119   }
120 }
121
122 bool X86RegisterBankInfo::getInstrValueMapping(
123     const MachineInstr &MI,
124     const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
125     SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
126
127   unsigned NumOperands = MI.getNumOperands();
128   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
129     if (!MI.getOperand(Idx).isReg())
130       continue;
131
132     auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
133     if (!Mapping->isValid())
134       return false;
135
136     OpdsMapping[Idx] = Mapping;
137   }
138   return true;
139 }
140
141 const RegisterBankInfo::InstructionMapping &
142 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
143                                             bool isFP) const {
144   const MachineFunction &MF = *MI.getParent()->getParent();
145   const MachineRegisterInfo &MRI = MF.getRegInfo();
146
147   unsigned NumOperands = MI.getNumOperands();
148   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
149
150   if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
151       (Ty != MRI.getType(MI.getOperand(2).getReg())))
152     llvm_unreachable("Unsupported operand mapping yet.");
153
154   auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
155   return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
156 }
157
158 const RegisterBankInfo::InstructionMapping &
159 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
160   const MachineFunction &MF = *MI.getParent()->getParent();
161   const MachineRegisterInfo &MRI = MF.getRegInfo();
162   unsigned Opc = MI.getOpcode();
163
164   // Try the default logic for non-generic instructions that are either copies
165   // or already have some operands assigned to banks.
166   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
167     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
168     if (Mapping.isValid())
169       return Mapping;
170   }
171
172   switch (Opc) {
173   case TargetOpcode::G_ADD:
174   case TargetOpcode::G_SUB:
175   case TargetOpcode::G_MUL:
176     return getSameOperandsMapping(MI, false);
177   case TargetOpcode::G_FADD:
178   case TargetOpcode::G_FSUB:
179   case TargetOpcode::G_FMUL:
180   case TargetOpcode::G_FDIV:
181     return getSameOperandsMapping(MI, true);
182   case TargetOpcode::G_SHL:
183   case TargetOpcode::G_LSHR:
184   case TargetOpcode::G_ASHR: {
185     unsigned NumOperands = MI.getNumOperands();
186     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
187
188     auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
189     return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
190
191   }
192   default:
193     break;
194   }
195
196   unsigned NumOperands = MI.getNumOperands();
197   SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
198
199   switch (Opc) {
200   case TargetOpcode::G_FPEXT:
201   case TargetOpcode::G_FPTRUNC:
202   case TargetOpcode::G_FCONSTANT:
203     // Instruction having only floating-point operands (all scalars in VECRReg)
204     getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
205     break;
206   case TargetOpcode::G_SITOFP:
207   case TargetOpcode::G_FPTOSI: {
208     // Some of the floating-point instructions have mixed GPR and FP operands:
209     // fine-tune the computed mapping.
210     auto &Op0 = MI.getOperand(0);
211     auto &Op1 = MI.getOperand(1);
212     const LLT Ty0 = MRI.getType(Op0.getReg());
213     const LLT Ty1 = MRI.getType(Op1.getReg());
214
215     bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
216     bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
217     OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
218     OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
219     break;
220   }
221   case TargetOpcode::G_FCMP: {
222     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
223     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
224     (void)Ty2;
225     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
226            "Mismatched operand sizes for G_FCMP");
227
228     unsigned Size = Ty1.getSizeInBits();
229     (void)Size;
230     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
231
232     auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
233     OpRegBankIdx = {PMI_GPR8,
234                     /* Predicate */ PMI_None, FpRegBank, FpRegBank};
235     break;
236   }
237   case TargetOpcode::G_TRUNC:
238   case TargetOpcode::G_ANYEXT: {
239     auto &Op0 = MI.getOperand(0);
240     auto &Op1 = MI.getOperand(1);
241     const LLT Ty0 = MRI.getType(Op0.getReg());
242     const LLT Ty1 = MRI.getType(Op1.getReg());
243
244     bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
245                      Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
246     bool isFPAnyExt =
247         Ty0.getSizeInBits() == 128 &&
248         (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
249         Opc == TargetOpcode::G_ANYEXT;
250
251     getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
252                                OpRegBankIdx);
253   } break;
254   default:
255     // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
256     getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
257     break;
258   }
259
260   // Finally construct the computed mapping.
261   SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
262   if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
263     return getInvalidInstructionMapping();
264
265   return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
266                                getOperandsMapping(OpdsMapping), NumOperands);
267 }
268
269 void X86RegisterBankInfo::applyMappingImpl(
270     const OperandsMapper &OpdMapper) const {
271   return applyDefaultMapping(OpdMapper);
272 }
273
274 RegisterBankInfo::InstructionMappings
275 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
276
277   const MachineFunction &MF = *MI.getParent()->getParent();
278   const TargetSubtargetInfo &STI = MF.getSubtarget();
279   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
280   const MachineRegisterInfo &MRI = MF.getRegInfo();
281
282   switch (MI.getOpcode()) {
283   case TargetOpcode::G_LOAD:
284   case TargetOpcode::G_STORE:
285   case TargetOpcode::G_IMPLICIT_DEF: {
286     // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
287     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
288     if (Size != 32 && Size != 64)
289       break;
290
291     unsigned NumOperands = MI.getNumOperands();
292
293     // Track the bank of each register, use FP mapping (all scalars in VEC)
294     SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
295     getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
296
297     // Finally construct the computed mapping.
298     SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
299     if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
300       break;
301
302     const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
303         /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
304     InstructionMappings AltMappings;
305     AltMappings.push_back(&Mapping);
306     return AltMappings;
307   }
308   default:
309     break;
310   }
311   return RegisterBankInfo::getInstrAlternativeMappings(MI);
312 }