1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements the targeting of the RegisterBankInfo class for X86. 10 /// \todo This should be generated by TableGen. 11 //===----------------------------------------------------------------------===// 12 13 #include "X86RegisterBankInfo.h" 14 #include "X86InstrInfo.h" 15 #include "llvm/CodeGen/MachineRegisterInfo.h" 16 #include "llvm/CodeGen/RegisterBank.h" 17 #include "llvm/CodeGen/RegisterBankInfo.h" 18 #include "llvm/CodeGen/TargetRegisterInfo.h" 19 20 #define GET_TARGET_REGBANK_IMPL 21 #include "X86GenRegisterBank.inc" 22 23 using namespace llvm; 24 // This file will be TableGen'ed at some point. 25 #define GET_TARGET_REGBANK_INFO_IMPL 26 #include "X86GenRegisterBankInfo.def" 27 28 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) { 29 30 // validate RegBank initialization. 31 const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID); 32 (void)RBGPR; 33 assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization."); 34 35 // The GPR register bank is fully defined by all the registers in 36 // GR64 + its subclasses. 37 assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) && 38 "Subclass not added?"); 39 assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); 40 } 41 42 const RegisterBank & 43 X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 44 LLT) const { 45 46 if (X86::GR8RegClass.hasSubClassEq(&RC) || 47 X86::GR16RegClass.hasSubClassEq(&RC) || 48 X86::GR32RegClass.hasSubClassEq(&RC) || 49 X86::GR64RegClass.hasSubClassEq(&RC) || 50 X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) || 51 X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC)) 52 return getRegBank(X86::GPRRegBankID); 53 54 if (X86::FR32XRegClass.hasSubClassEq(&RC) || 55 X86::FR64XRegClass.hasSubClassEq(&RC) || 56 X86::VR128XRegClass.hasSubClassEq(&RC) || 57 X86::VR256XRegClass.hasSubClassEq(&RC) || 58 X86::VR512RegClass.hasSubClassEq(&RC)) 59 return getRegBank(X86::VECRRegBankID); 60 61 llvm_unreachable("Unsupported register kind yet."); 62 } 63 64 X86GenRegisterBankInfo::PartialMappingIdx 65 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) { 66 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) { 67 switch (Ty.getSizeInBits()) { 68 case 1: 69 case 8: 70 return PMI_GPR8; 71 case 16: 72 return PMI_GPR16; 73 case 32: 74 return PMI_GPR32; 75 case 64: 76 return PMI_GPR64; 77 case 128: 78 return PMI_VEC128; 79 break; 80 default: 81 llvm_unreachable("Unsupported register size."); 82 } 83 } else if (Ty.isScalar()) { 84 switch (Ty.getSizeInBits()) { 85 case 32: 86 return PMI_FP32; 87 case 64: 88 return PMI_FP64; 89 case 128: 90 return PMI_VEC128; 91 default: 92 llvm_unreachable("Unsupported register size."); 93 } 94 } else { 95 switch (Ty.getSizeInBits()) { 96 case 128: 97 return PMI_VEC128; 98 case 256: 99 return PMI_VEC256; 100 case 512: 101 return PMI_VEC512; 102 default: 103 llvm_unreachable("Unsupported register size."); 104 } 105 } 106 107 return PMI_None; 108 } 109 110 void X86RegisterBankInfo::getInstrPartialMappingIdxs( 111 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP, 112 SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) { 113 114 unsigned NumOperands = MI.getNumOperands(); 115 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 116 auto &MO = MI.getOperand(Idx); 117 if (!MO.isReg()) 118 OpRegBankIdx[Idx] = PMI_None; 119 else 120 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP); 121 } 122 } 123 124 bool X86RegisterBankInfo::getInstrValueMapping( 125 const MachineInstr &MI, 126 const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx, 127 SmallVectorImpl<const ValueMapping *> &OpdsMapping) { 128 129 unsigned NumOperands = MI.getNumOperands(); 130 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 131 if (!MI.getOperand(Idx).isReg()) 132 continue; 133 134 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1); 135 if (!Mapping->isValid()) 136 return false; 137 138 OpdsMapping[Idx] = Mapping; 139 } 140 return true; 141 } 142 143 const RegisterBankInfo::InstructionMapping & 144 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, 145 bool isFP) const { 146 const MachineFunction &MF = *MI.getParent()->getParent(); 147 const MachineRegisterInfo &MRI = MF.getRegInfo(); 148 149 unsigned NumOperands = MI.getNumOperands(); 150 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 151 152 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) || 153 (Ty != MRI.getType(MI.getOperand(2).getReg()))) 154 llvm_unreachable("Unsupported operand mapping yet."); 155 156 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3); 157 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 158 } 159 160 const RegisterBankInfo::InstructionMapping & 161 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 162 const MachineFunction &MF = *MI.getParent()->getParent(); 163 const MachineRegisterInfo &MRI = MF.getRegInfo(); 164 unsigned Opc = MI.getOpcode(); 165 166 // Try the default logic for non-generic instructions that are either copies 167 // or already have some operands assigned to banks. 168 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 169 const InstructionMapping &Mapping = getInstrMappingImpl(MI); 170 if (Mapping.isValid()) 171 return Mapping; 172 } 173 174 switch (Opc) { 175 case TargetOpcode::G_ADD: 176 case TargetOpcode::G_SUB: 177 case TargetOpcode::G_MUL: 178 return getSameOperandsMapping(MI, false); 179 case TargetOpcode::G_FADD: 180 case TargetOpcode::G_FSUB: 181 case TargetOpcode::G_FMUL: 182 case TargetOpcode::G_FDIV: 183 return getSameOperandsMapping(MI, true); 184 case TargetOpcode::G_SHL: 185 case TargetOpcode::G_LSHR: 186 case TargetOpcode::G_ASHR: { 187 unsigned NumOperands = MI.getNumOperands(); 188 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 189 190 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3); 191 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 192 193 } 194 default: 195 break; 196 } 197 198 unsigned NumOperands = MI.getNumOperands(); 199 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 200 201 switch (Opc) { 202 case TargetOpcode::G_FPEXT: 203 case TargetOpcode::G_FPTRUNC: 204 case TargetOpcode::G_FCONSTANT: 205 // Instruction having only floating-point operands (all scalars in VECRReg) 206 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 207 break; 208 case TargetOpcode::G_SITOFP: 209 case TargetOpcode::G_FPTOSI: { 210 // Some of the floating-point instructions have mixed GPR and FP operands: 211 // fine-tune the computed mapping. 212 auto &Op0 = MI.getOperand(0); 213 auto &Op1 = MI.getOperand(1); 214 const LLT Ty0 = MRI.getType(Op0.getReg()); 215 const LLT Ty1 = MRI.getType(Op1.getReg()); 216 217 bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP; 218 bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI; 219 OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP); 220 OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP); 221 break; 222 } 223 case TargetOpcode::G_FCMP: { 224 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 225 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 226 (void)Ty2; 227 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 228 "Mismatched operand sizes for G_FCMP"); 229 230 unsigned Size = Ty1.getSizeInBits(); 231 (void)Size; 232 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 233 234 auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true); 235 OpRegBankIdx = {PMI_GPR8, 236 /* Predicate */ PMI_None, FpRegBank, FpRegBank}; 237 break; 238 } 239 case TargetOpcode::G_TRUNC: 240 case TargetOpcode::G_ANYEXT: { 241 auto &Op0 = MI.getOperand(0); 242 auto &Op1 = MI.getOperand(1); 243 const LLT Ty0 = MRI.getType(Op0.getReg()); 244 const LLT Ty1 = MRI.getType(Op1.getReg()); 245 246 bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) && 247 Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC; 248 bool isFPAnyExt = 249 Ty0.getSizeInBits() == 128 && 250 (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) && 251 Opc == TargetOpcode::G_ANYEXT; 252 253 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt, 254 OpRegBankIdx); 255 } break; 256 default: 257 // Track the bank of each register, use NotFP mapping (all scalars in GPRs) 258 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); 259 break; 260 } 261 262 // Finally construct the computed mapping. 263 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 264 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 265 return getInvalidInstructionMapping(); 266 267 return getInstructionMapping(DefaultMappingID, /* Cost */ 1, 268 getOperandsMapping(OpdsMapping), NumOperands); 269 } 270 271 void X86RegisterBankInfo::applyMappingImpl( 272 const OperandsMapper &OpdMapper) const { 273 return applyDefaultMapping(OpdMapper); 274 } 275 276 RegisterBankInfo::InstructionMappings 277 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 278 279 const MachineFunction &MF = *MI.getParent()->getParent(); 280 const TargetSubtargetInfo &STI = MF.getSubtarget(); 281 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 282 const MachineRegisterInfo &MRI = MF.getRegInfo(); 283 284 switch (MI.getOpcode()) { 285 case TargetOpcode::G_LOAD: 286 case TargetOpcode::G_STORE: 287 case TargetOpcode::G_IMPLICIT_DEF: { 288 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64 289 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 290 if (Size != 32 && Size != 64) 291 break; 292 293 unsigned NumOperands = MI.getNumOperands(); 294 295 // Track the bank of each register, use FP mapping (all scalars in VEC) 296 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 297 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 298 299 // Finally construct the computed mapping. 300 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 301 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 302 break; 303 304 const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping( 305 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands); 306 InstructionMappings AltMappings; 307 AltMappings.push_back(&Mapping); 308 return AltMappings; 309 } 310 default: 311 break; 312 } 313 return RegisterBankInfo::getInstrAlternativeMappings(MI); 314 } 315