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 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) 30 : X86GenRegisterBankInfo() { 31 32 // validate RegBank initialization. 33 const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID); 34 (void)RBGPR; 35 assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization."); 36 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"); 42 } 43 44 const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass( 45 const TargetRegisterClass &RC) const { 46 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); 52 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); 59 60 llvm_unreachable("Unsupported register kind yet."); 61 } 62 63 X86GenRegisterBankInfo::PartialMappingIdx 64 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) { 65 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) { 66 switch (Ty.getSizeInBits()) { 67 case 1: 68 case 8: 69 return PMI_GPR8; 70 case 16: 71 return PMI_GPR16; 72 case 32: 73 return PMI_GPR32; 74 case 64: 75 return PMI_GPR64; 76 break; 77 default: 78 llvm_unreachable("Unsupported register size."); 79 } 80 } else if (Ty.isScalar()) { 81 switch (Ty.getSizeInBits()) { 82 case 32: 83 return PMI_FP32; 84 case 64: 85 return PMI_FP64; 86 default: 87 llvm_unreachable("Unsupported register size."); 88 } 89 } else { 90 switch (Ty.getSizeInBits()) { 91 case 128: 92 return PMI_VEC128; 93 case 256: 94 return PMI_VEC256; 95 case 512: 96 return PMI_VEC512; 97 default: 98 llvm_unreachable("Unsupported register size."); 99 } 100 } 101 102 return PMI_None; 103 } 104 105 void X86RegisterBankInfo::getInstrPartialMappingIdxs( 106 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP, 107 SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) { 108 109 unsigned NumOperands = MI.getNumOperands(); 110 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 111 auto &MO = MI.getOperand(Idx); 112 if (!MO.isReg()) 113 OpRegBankIdx[Idx] = PMI_None; 114 else 115 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP); 116 } 117 } 118 119 bool X86RegisterBankInfo::getInstrValueMapping( 120 const MachineInstr &MI, 121 const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx, 122 SmallVectorImpl<const ValueMapping *> &OpdsMapping) { 123 124 unsigned NumOperands = MI.getNumOperands(); 125 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 126 if (!MI.getOperand(Idx).isReg()) 127 continue; 128 129 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1); 130 if (!Mapping->isValid()) 131 return false; 132 133 OpdsMapping[Idx] = Mapping; 134 } 135 return true; 136 } 137 138 const RegisterBankInfo::InstructionMapping & 139 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, 140 bool isFP) const { 141 const MachineFunction &MF = *MI.getParent()->getParent(); 142 const MachineRegisterInfo &MRI = MF.getRegInfo(); 143 144 unsigned NumOperands = MI.getNumOperands(); 145 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 146 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."); 150 151 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3); 152 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 153 } 154 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(); 160 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()) 166 return Mapping; 167 } 168 169 switch (Opc) { 170 case TargetOpcode::G_ADD: 171 case TargetOpcode::G_SUB: 172 return getSameOperandsMapping(MI, false); 173 break; 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); 179 break; 180 default: 181 break; 182 } 183 184 unsigned NumOperands = MI.getNumOperands(); 185 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 186 187 switch (Opc) { 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); 192 break; 193 default: 194 // Track the bank of each register, use NotFP mapping (all scalars in GPRs) 195 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); 196 break; 197 } 198 199 // Finally construct the computed mapping. 200 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 201 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 202 return getInvalidInstructionMapping(); 203 204 return getInstructionMapping(DefaultMappingID, /* Cost */ 1, 205 getOperandsMapping(OpdsMapping), NumOperands); 206 } 207 208 void X86RegisterBankInfo::applyMappingImpl( 209 const OperandsMapper &OpdMapper) const { 210 return applyDefaultMapping(OpdMapper); 211 } 212 213 RegisterBankInfo::InstructionMappings 214 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 215 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(); 220 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) 228 break; 229 230 unsigned NumOperands = MI.getNumOperands(); 231 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); 235 236 // Finally construct the computed mapping. 237 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 238 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 239 break; 240 241 const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping( 242 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands); 243 InstructionMappings AltMappings; 244 AltMappings.push_back(&Mapping); 245 return AltMappings; 246 } 247 default: 248 break; 249 } 250 return RegisterBankInfo::getInstrAlternativeMappings(MI); 251 } 252