1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the RegisterBankInfo class for X86.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
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"
20 #define GET_TARGET_REGBANK_IMPL
21 #include "X86GenRegisterBank.inc"
24 // This file will be TableGen'ed at some point.
25 #define GET_TARGET_REGBANK_INFO_IMPL
26 #include "X86GenRegisterBankInfo.def"
28 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI)
29 : X86GenRegisterBankInfo() {
31 // validate RegBank initialization.
32 const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
34 assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
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");
44 X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
47 if (X86::GR8RegClass.hasSubClassEq(&RC) ||
48 X86::GR16RegClass.hasSubClassEq(&RC) ||
49 X86::GR32RegClass.hasSubClassEq(&RC) ||
50 X86::GR64RegClass.hasSubClassEq(&RC) ||
51 X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) ||
52 X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC))
53 return getRegBank(X86::GPRRegBankID);
55 if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
56 X86::FR64XRegClass.hasSubClassEq(&RC) ||
57 X86::VR128XRegClass.hasSubClassEq(&RC) ||
58 X86::VR256XRegClass.hasSubClassEq(&RC) ||
59 X86::VR512RegClass.hasSubClassEq(&RC))
60 return getRegBank(X86::VECRRegBankID);
62 llvm_unreachable("Unsupported register kind yet.");
65 X86GenRegisterBankInfo::PartialMappingIdx
66 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
67 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
68 switch (Ty.getSizeInBits()) {
82 llvm_unreachable("Unsupported register size.");
84 } else if (Ty.isScalar()) {
85 switch (Ty.getSizeInBits()) {
93 llvm_unreachable("Unsupported register size.");
96 switch (Ty.getSizeInBits()) {
104 llvm_unreachable("Unsupported register size.");
111 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
112 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
113 SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
115 unsigned NumOperands = MI.getNumOperands();
116 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
117 auto &MO = MI.getOperand(Idx);
119 OpRegBankIdx[Idx] = PMI_None;
121 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
125 bool X86RegisterBankInfo::getInstrValueMapping(
126 const MachineInstr &MI,
127 const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
128 SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
130 unsigned NumOperands = MI.getNumOperands();
131 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
132 if (!MI.getOperand(Idx).isReg())
135 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
136 if (!Mapping->isValid())
139 OpdsMapping[Idx] = Mapping;
144 const RegisterBankInfo::InstructionMapping &
145 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
147 const MachineFunction &MF = *MI.getParent()->getParent();
148 const MachineRegisterInfo &MRI = MF.getRegInfo();
150 unsigned NumOperands = MI.getNumOperands();
151 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
153 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
154 (Ty != MRI.getType(MI.getOperand(2).getReg())))
155 llvm_unreachable("Unsupported operand mapping yet.");
157 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
158 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
161 const RegisterBankInfo::InstructionMapping &
162 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
163 const MachineFunction &MF = *MI.getParent()->getParent();
164 const MachineRegisterInfo &MRI = MF.getRegInfo();
165 unsigned Opc = MI.getOpcode();
167 // Try the default logic for non-generic instructions that are either copies
168 // or already have some operands assigned to banks.
169 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
170 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
171 if (Mapping.isValid())
176 case TargetOpcode::G_ADD:
177 case TargetOpcode::G_SUB:
178 case TargetOpcode::G_MUL:
179 return getSameOperandsMapping(MI, false);
180 case TargetOpcode::G_FADD:
181 case TargetOpcode::G_FSUB:
182 case TargetOpcode::G_FMUL:
183 case TargetOpcode::G_FDIV:
184 return getSameOperandsMapping(MI, true);
185 case TargetOpcode::G_SHL:
186 case TargetOpcode::G_LSHR:
187 case TargetOpcode::G_ASHR: {
188 unsigned NumOperands = MI.getNumOperands();
189 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
191 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
192 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
199 unsigned NumOperands = MI.getNumOperands();
200 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
203 case TargetOpcode::G_FPEXT:
204 case TargetOpcode::G_FPTRUNC:
205 case TargetOpcode::G_FCONSTANT:
206 // Instruction having only floating-point operands (all scalars in VECRReg)
207 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
209 case TargetOpcode::G_SITOFP:
210 case TargetOpcode::G_FPTOSI: {
211 // Some of the floating-point instructions have mixed GPR and FP operands:
212 // fine-tune the computed mapping.
213 auto &Op0 = MI.getOperand(0);
214 auto &Op1 = MI.getOperand(1);
215 const LLT Ty0 = MRI.getType(Op0.getReg());
216 const LLT Ty1 = MRI.getType(Op1.getReg());
218 bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
219 bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
220 OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
221 OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
224 case TargetOpcode::G_FCMP: {
225 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
226 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
228 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
229 "Mismatched operand sizes for G_FCMP");
231 unsigned Size = Ty1.getSizeInBits();
233 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
235 auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
236 OpRegBankIdx = {PMI_GPR8,
237 /* Predicate */ PMI_None, FpRegBank, FpRegBank};
240 case TargetOpcode::G_TRUNC:
241 case TargetOpcode::G_ANYEXT: {
242 auto &Op0 = MI.getOperand(0);
243 auto &Op1 = MI.getOperand(1);
244 const LLT Ty0 = MRI.getType(Op0.getReg());
245 const LLT Ty1 = MRI.getType(Op1.getReg());
247 bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
248 Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
250 Ty0.getSizeInBits() == 128 &&
251 (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
252 Opc == TargetOpcode::G_ANYEXT;
254 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
258 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
259 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
263 // Finally construct the computed mapping.
264 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
265 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
266 return getInvalidInstructionMapping();
268 return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
269 getOperandsMapping(OpdsMapping), NumOperands);
272 void X86RegisterBankInfo::applyMappingImpl(
273 const OperandsMapper &OpdMapper) const {
274 return applyDefaultMapping(OpdMapper);
277 RegisterBankInfo::InstructionMappings
278 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
280 const MachineFunction &MF = *MI.getParent()->getParent();
281 const TargetSubtargetInfo &STI = MF.getSubtarget();
282 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
283 const MachineRegisterInfo &MRI = MF.getRegInfo();
285 switch (MI.getOpcode()) {
286 case TargetOpcode::G_LOAD:
287 case TargetOpcode::G_STORE:
288 case TargetOpcode::G_IMPLICIT_DEF: {
289 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
290 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
291 if (Size != 32 && Size != 64)
294 unsigned NumOperands = MI.getNumOperands();
296 // Track the bank of each register, use FP mapping (all scalars in VEC)
297 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
298 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
300 // Finally construct the computed mapping.
301 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
302 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
305 const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
306 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
307 InstructionMappings AltMappings;
308 AltMappings.push_back(&Mapping);
314 return RegisterBankInfo::getInstrAlternativeMappings(MI);