1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the RegisterBankInfo class for X86.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86RegisterBankInfo.h"
15 #include "X86InstrInfo.h"
16 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/Target/TargetRegisterInfo.h"
20 
21 #define GET_TARGET_REGBANK_IMPL
22 #include "X86GenRegisterBank.inc"
23 
24 using namespace llvm;
25 // This file will be TableGen'ed at some point.
26 #define GET_TARGET_REGBANK_INFO_IMPL
27 #include "X86GenRegisterBankInfo.def"
28 
29 #ifndef LLVM_BUILD_GLOBAL_ISEL
30 #error "You shouldn't build this"
31 #endif
32 
33 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI)
34     : X86GenRegisterBankInfo() {
35 
36   // validate RegBank initialization.
37   const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
38   (void)RBGPR;
39   assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
40 
41   // The GPR register bank is fully defined by all the registers in
42   // GR64 + its subclasses.
43   assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
44          "Subclass not added?");
45   assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
46 }
47 
48 const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass(
49     const TargetRegisterClass &RC) const {
50 
51   if (X86::GR8RegClass.hasSubClassEq(&RC) ||
52       X86::GR16RegClass.hasSubClassEq(&RC) ||
53       X86::GR32RegClass.hasSubClassEq(&RC) ||
54       X86::GR64RegClass.hasSubClassEq(&RC))
55     return getRegBank(X86::GPRRegBankID);
56 
57   if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
58       X86::FR64XRegClass.hasSubClassEq(&RC) ||
59       X86::VR128XRegClass.hasSubClassEq(&RC) ||
60       X86::VR256XRegClass.hasSubClassEq(&RC) ||
61       X86::VR512RegClass.hasSubClassEq(&RC))
62     return getRegBank(X86::VECRRegBankID);
63 
64   llvm_unreachable("Unsupported register kind yet.");
65 }
66 
67 X86GenRegisterBankInfo::PartialMappingIdx
68 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
69   if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
70     switch (Ty.getSizeInBits()) {
71     case 1:
72     case 8:
73       return PMI_GPR8;
74     case 16:
75       return PMI_GPR16;
76     case 32:
77       return PMI_GPR32;
78     case 64:
79       return PMI_GPR64;
80       break;
81     default:
82       llvm_unreachable("Unsupported register size.");
83     }
84   } else if (Ty.isScalar()) {
85     switch (Ty.getSizeInBits()) {
86     case 32:
87       return PMI_FP32;
88     case 64:
89       return PMI_FP64;
90     default:
91       llvm_unreachable("Unsupported register size.");
92     }
93   } else {
94     switch (Ty.getSizeInBits()) {
95     case 128:
96       return PMI_VEC128;
97     case 256:
98       return PMI_VEC256;
99     case 512:
100       return PMI_VEC512;
101     default:
102       llvm_unreachable("Unsupported register size.");
103     }
104   }
105 
106   return PMI_None;
107 }
108 
109 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
110     const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
111     SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
112 
113   unsigned NumOperands = MI.getNumOperands();
114   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
115     auto &MO = MI.getOperand(Idx);
116     if (!MO.isReg())
117       OpRegBankIdx[Idx] = PMI_None;
118     else
119       OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
120   }
121 }
122 
123 bool X86RegisterBankInfo::getInstrValueMapping(
124     const MachineInstr &MI,
125     const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
126     SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
127 
128   unsigned NumOperands = MI.getNumOperands();
129   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
130     if (!MI.getOperand(Idx).isReg())
131       continue;
132 
133     auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
134     if (!Mapping->isValid())
135       return false;
136 
137     OpdsMapping[Idx] = Mapping;
138   }
139   return true;
140 }
141 
142 RegisterBankInfo::InstructionMapping
143 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, bool isFP) {
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 InstructionMapping{DefaultMappingID, 1, Mapping, NumOperands};
156 }
157 
158 RegisterBankInfo::InstructionMapping
159 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
160   const MachineFunction &MF = *MI.getParent()->getParent();
161   const MachineRegisterInfo &MRI = MF.getRegInfo();
162   auto 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)) {
167     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     return getSameOperandsMapping(MI, false);
176     break;
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     break;
183   default:
184     break;
185   }
186 
187   unsigned NumOperands = MI.getNumOperands();
188 
189   // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
190   SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
191   getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
192 
193   // Finally construct the computed mapping.
194   SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
195   if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
196     return InstructionMapping();
197 
198   return InstructionMapping{DefaultMappingID, /* Cost */ 1,
199                             getOperandsMapping(OpdsMapping), NumOperands};
200 }
201 
202 void X86RegisterBankInfo::applyMappingImpl(
203     const OperandsMapper &OpdMapper) const {
204   return applyDefaultMapping(OpdMapper);
205 }
206 
207 RegisterBankInfo::InstructionMappings
208 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
209 
210   const MachineFunction &MF = *MI.getParent()->getParent();
211   const TargetSubtargetInfo &STI = MF.getSubtarget();
212   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
213   const MachineRegisterInfo &MRI = MF.getRegInfo();
214 
215   switch (MI.getOpcode()) {
216   case TargetOpcode::G_LOAD:
217   case TargetOpcode::G_STORE: {
218     // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
219     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
220     if (Size != 32 && Size != 64)
221       break;
222 
223     unsigned NumOperands = MI.getNumOperands();
224 
225     // Track the bank of each register, use FP mapping (all scalars in VEC)
226     SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
227     getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
228 
229     // Finally construct the computed mapping.
230     SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
231     if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
232       break;
233 
234     RegisterBankInfo::InstructionMapping Mapping = InstructionMapping{
235         /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands};
236     InstructionMappings AltMappings;
237     AltMappings.emplace_back(std::move(Mapping));
238     return AltMappings;
239   }
240   default:
241     break;
242   }
243   return RegisterBankInfo::getInstrAlternativeMappings(MI);
244 }
245