1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the RegisterBankInfo class for X86.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
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/CodeGen/TargetRegisterInfo.h"
21 #define GET_TARGET_REGBANK_IMPL
22 #include "X86GenRegisterBank.inc"
25 // This file will be TableGen'ed at some point.
26 #define GET_TARGET_REGBANK_INFO_IMPL
27 #include "X86GenRegisterBankInfo.def"
29 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI)
30 : X86GenRegisterBankInfo() {
32 // validate RegBank initialization.
33 const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
35 assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
37 // The GPR register bank is fully defined by all the registers in
38 // GR64 + its subclasses.
39 assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
40 "Subclass not added?");
41 assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
44 const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass(
45 const TargetRegisterClass &RC) const {
47 if (X86::GR8RegClass.hasSubClassEq(&RC) ||
48 X86::GR16RegClass.hasSubClassEq(&RC) ||
49 X86::GR32RegClass.hasSubClassEq(&RC) ||
50 X86::GR64RegClass.hasSubClassEq(&RC))
51 return getRegBank(X86::GPRRegBankID);
53 if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
54 X86::FR64XRegClass.hasSubClassEq(&RC) ||
55 X86::VR128XRegClass.hasSubClassEq(&RC) ||
56 X86::VR256XRegClass.hasSubClassEq(&RC) ||
57 X86::VR512RegClass.hasSubClassEq(&RC))
58 return getRegBank(X86::VECRRegBankID);
60 llvm_unreachable("Unsupported register kind yet.");
63 X86GenRegisterBankInfo::PartialMappingIdx
64 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
65 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
66 switch (Ty.getSizeInBits()) {
78 llvm_unreachable("Unsupported register size.");
80 } else if (Ty.isScalar()) {
81 switch (Ty.getSizeInBits()) {
87 llvm_unreachable("Unsupported register size.");
90 switch (Ty.getSizeInBits()) {
98 llvm_unreachable("Unsupported register size.");
105 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
106 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
107 SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
109 unsigned NumOperands = MI.getNumOperands();
110 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
111 auto &MO = MI.getOperand(Idx);
113 OpRegBankIdx[Idx] = PMI_None;
115 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
119 bool X86RegisterBankInfo::getInstrValueMapping(
120 const MachineInstr &MI,
121 const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
122 SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
124 unsigned NumOperands = MI.getNumOperands();
125 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
126 if (!MI.getOperand(Idx).isReg())
129 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
130 if (!Mapping->isValid())
133 OpdsMapping[Idx] = Mapping;
138 const RegisterBankInfo::InstructionMapping &
139 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
141 const MachineFunction &MF = *MI.getParent()->getParent();
142 const MachineRegisterInfo &MRI = MF.getRegInfo();
144 unsigned NumOperands = MI.getNumOperands();
145 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
147 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
148 (Ty != MRI.getType(MI.getOperand(2).getReg())))
149 llvm_unreachable("Unsupported operand mapping yet.");
151 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
152 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
155 const RegisterBankInfo::InstructionMapping &
156 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
157 const MachineFunction &MF = *MI.getParent()->getParent();
158 const MachineRegisterInfo &MRI = MF.getRegInfo();
159 auto Opc = MI.getOpcode();
161 // Try the default logic for non-generic instructions that are either copies
162 // or already have some operands assigned to banks.
163 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
164 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
165 if (Mapping.isValid())
170 case TargetOpcode::G_ADD:
171 case TargetOpcode::G_SUB:
172 return getSameOperandsMapping(MI, false);
174 case TargetOpcode::G_FADD:
175 case TargetOpcode::G_FSUB:
176 case TargetOpcode::G_FMUL:
177 case TargetOpcode::G_FDIV:
178 return getSameOperandsMapping(MI, true);
184 unsigned NumOperands = MI.getNumOperands();
185 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
188 case TargetOpcode::G_FPEXT:
189 case TargetOpcode::G_FCONSTANT:
190 // Instruction having only floating-point operands (all scalars in VECRReg)
191 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
194 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
195 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
199 // Finally construct the computed mapping.
200 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
201 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
202 return getInvalidInstructionMapping();
204 return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
205 getOperandsMapping(OpdsMapping), NumOperands);
208 void X86RegisterBankInfo::applyMappingImpl(
209 const OperandsMapper &OpdMapper) const {
210 return applyDefaultMapping(OpdMapper);
213 RegisterBankInfo::InstructionMappings
214 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
216 const MachineFunction &MF = *MI.getParent()->getParent();
217 const TargetSubtargetInfo &STI = MF.getSubtarget();
218 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
219 const MachineRegisterInfo &MRI = MF.getRegInfo();
221 switch (MI.getOpcode()) {
222 case TargetOpcode::G_LOAD:
223 case TargetOpcode::G_STORE:
224 case TargetOpcode::G_IMPLICIT_DEF: {
225 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
226 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
227 if (Size != 32 && Size != 64)
230 unsigned NumOperands = MI.getNumOperands();
232 // Track the bank of each register, use FP mapping (all scalars in VEC)
233 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
234 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
236 // Finally construct the computed mapping.
237 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
238 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
241 const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
242 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
243 InstructionMappings AltMappings;
244 AltMappings.push_back(&Mapping);
250 return RegisterBankInfo::getInstrAlternativeMappings(MI);