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