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/CodeGen/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 case 128: 77 return PMI_VEC128; 78 break; 79 default: 80 llvm_unreachable("Unsupported register size."); 81 } 82 } else if (Ty.isScalar()) { 83 switch (Ty.getSizeInBits()) { 84 case 32: 85 return PMI_FP32; 86 case 64: 87 return PMI_FP64; 88 case 128: 89 return PMI_VEC128; 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 const RegisterBankInfo::InstructionMapping & 143 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, 144 bool isFP) const { 145 const MachineFunction &MF = *MI.getParent()->getParent(); 146 const MachineRegisterInfo &MRI = MF.getRegInfo(); 147 148 unsigned NumOperands = MI.getNumOperands(); 149 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 150 151 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) || 152 (Ty != MRI.getType(MI.getOperand(2).getReg()))) 153 llvm_unreachable("Unsupported operand mapping yet."); 154 155 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3); 156 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 157 } 158 159 const RegisterBankInfo::InstructionMapping & 160 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 161 const MachineFunction &MF = *MI.getParent()->getParent(); 162 const MachineRegisterInfo &MRI = MF.getRegInfo(); 163 auto Opc = MI.getOpcode(); 164 165 // Try the default logic for non-generic instructions that are either copies 166 // or already have some operands assigned to banks. 167 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 168 const InstructionMapping &Mapping = getInstrMappingImpl(MI); 169 if (Mapping.isValid()) 170 return Mapping; 171 } 172 173 switch (Opc) { 174 case TargetOpcode::G_ADD: 175 case TargetOpcode::G_SUB: 176 case TargetOpcode::G_MUL: 177 case TargetOpcode::G_SHL: 178 case TargetOpcode::G_LSHR: 179 case TargetOpcode::G_ASHR: 180 return getSameOperandsMapping(MI, false); 181 break; 182 case TargetOpcode::G_FADD: 183 case TargetOpcode::G_FSUB: 184 case TargetOpcode::G_FMUL: 185 case TargetOpcode::G_FDIV: 186 return getSameOperandsMapping(MI, true); 187 break; 188 default: 189 break; 190 } 191 192 unsigned NumOperands = MI.getNumOperands(); 193 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 194 195 switch (Opc) { 196 case TargetOpcode::G_FPEXT: 197 case TargetOpcode::G_FPTRUNC: 198 case TargetOpcode::G_FCONSTANT: 199 // Instruction having only floating-point operands (all scalars in VECRReg) 200 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 201 break; 202 case TargetOpcode::G_SITOFP: 203 case TargetOpcode::G_FPTOSI: { 204 // Some of the floating-point instructions have mixed GPR and FP operands: 205 // fine-tune the computed mapping. 206 auto &Op0 = MI.getOperand(0); 207 auto &Op1 = MI.getOperand(1); 208 const LLT Ty0 = MRI.getType(Op0.getReg()); 209 const LLT Ty1 = MRI.getType(Op1.getReg()); 210 211 bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP; 212 bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI; 213 OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP); 214 OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP); 215 break; 216 } 217 case TargetOpcode::G_FCMP: { 218 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 219 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 220 (void)Ty2; 221 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 222 "Mismatched operand sizes for G_FCMP"); 223 224 unsigned Size = Ty1.getSizeInBits(); 225 (void)Size; 226 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 227 228 auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true); 229 OpRegBankIdx = {PMI_GPR8, 230 /* Predicate */ PMI_None, FpRegBank, FpRegBank}; 231 break; 232 } 233 case TargetOpcode::G_TRUNC: 234 case TargetOpcode::G_ANYEXT: { 235 auto &Op0 = MI.getOperand(0); 236 auto &Op1 = MI.getOperand(1); 237 const LLT Ty0 = MRI.getType(Op0.getReg()); 238 const LLT Ty1 = MRI.getType(Op1.getReg()); 239 240 bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) && 241 Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC; 242 bool isFPAnyExt = 243 Ty0.getSizeInBits() == 128 && 244 (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) && 245 Opc == TargetOpcode::G_ANYEXT; 246 247 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt, 248 OpRegBankIdx); 249 } break; 250 default: 251 // Track the bank of each register, use NotFP mapping (all scalars in GPRs) 252 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); 253 break; 254 } 255 256 // Finally construct the computed mapping. 257 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 258 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 259 return getInvalidInstructionMapping(); 260 261 return getInstructionMapping(DefaultMappingID, /* Cost */ 1, 262 getOperandsMapping(OpdsMapping), NumOperands); 263 } 264 265 void X86RegisterBankInfo::applyMappingImpl( 266 const OperandsMapper &OpdMapper) const { 267 return applyDefaultMapping(OpdMapper); 268 } 269 270 RegisterBankInfo::InstructionMappings 271 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 272 273 const MachineFunction &MF = *MI.getParent()->getParent(); 274 const TargetSubtargetInfo &STI = MF.getSubtarget(); 275 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 276 const MachineRegisterInfo &MRI = MF.getRegInfo(); 277 278 switch (MI.getOpcode()) { 279 case TargetOpcode::G_LOAD: 280 case TargetOpcode::G_STORE: 281 case TargetOpcode::G_IMPLICIT_DEF: { 282 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64 283 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 284 if (Size != 32 && Size != 64) 285 break; 286 287 unsigned NumOperands = MI.getNumOperands(); 288 289 // Track the bank of each register, use FP mapping (all scalars in VEC) 290 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 291 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 292 293 // Finally construct the computed mapping. 294 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 295 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 296 break; 297 298 const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping( 299 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands); 300 InstructionMappings AltMappings; 301 AltMappings.push_back(&Mapping); 302 return AltMappings; 303 } 304 default: 305 break; 306 } 307 return RegisterBankInfo::getInstrAlternativeMappings(MI); 308 } 309