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 #ifndef LLVM_BUILD_GLOBAL_ISEL 30 #error "You shouldn't build this" 31 #endif 32 33 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) 34 : X86GenRegisterBankInfo() { 35 36 // validate RegBank initialization. 37 const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID); 38 (void)RBGPR; 39 assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization."); 40 41 // The GPR register bank is fully defined by all the registers in 42 // GR64 + its subclasses. 43 assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) && 44 "Subclass not added?"); 45 assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); 46 } 47 48 const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass( 49 const TargetRegisterClass &RC) const { 50 51 if (X86::GR8RegClass.hasSubClassEq(&RC) || 52 X86::GR16RegClass.hasSubClassEq(&RC) || 53 X86::GR32RegClass.hasSubClassEq(&RC) || 54 X86::GR64RegClass.hasSubClassEq(&RC)) 55 return getRegBank(X86::GPRRegBankID); 56 57 if (X86::FR32XRegClass.hasSubClassEq(&RC) || 58 X86::FR64XRegClass.hasSubClassEq(&RC) || 59 X86::VR128XRegClass.hasSubClassEq(&RC) || 60 X86::VR256XRegClass.hasSubClassEq(&RC) || 61 X86::VR512RegClass.hasSubClassEq(&RC)) 62 return getRegBank(X86::VECRRegBankID); 63 64 llvm_unreachable("Unsupported register kind yet."); 65 } 66 67 X86GenRegisterBankInfo::PartialMappingIdx 68 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) { 69 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) { 70 switch (Ty.getSizeInBits()) { 71 case 1: 72 case 8: 73 return PMI_GPR8; 74 case 16: 75 return PMI_GPR16; 76 case 32: 77 return PMI_GPR32; 78 case 64: 79 return PMI_GPR64; 80 break; 81 default: 82 llvm_unreachable("Unsupported register size."); 83 } 84 } else if (Ty.isScalar()) { 85 switch (Ty.getSizeInBits()) { 86 case 32: 87 return PMI_FP32; 88 case 64: 89 return PMI_FP64; 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 RegisterBankInfo::InstructionMapping 143 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, bool isFP) { 144 const MachineFunction &MF = *MI.getParent()->getParent(); 145 const MachineRegisterInfo &MRI = MF.getRegInfo(); 146 147 unsigned NumOperands = MI.getNumOperands(); 148 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 149 150 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) || 151 (Ty != MRI.getType(MI.getOperand(2).getReg()))) 152 llvm_unreachable("Unsupported operand mapping yet."); 153 154 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3); 155 return InstructionMapping{DefaultMappingID, 1, Mapping, NumOperands}; 156 } 157 158 RegisterBankInfo::InstructionMapping 159 X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 160 const MachineFunction &MF = *MI.getParent()->getParent(); 161 const MachineRegisterInfo &MRI = MF.getRegInfo(); 162 auto Opc = MI.getOpcode(); 163 164 // Try the default logic for non-generic instructions that are either copies 165 // or already have some operands assigned to banks. 166 if (!isPreISelGenericOpcode(Opc)) { 167 InstructionMapping Mapping = getInstrMappingImpl(MI); 168 if (Mapping.isValid()) 169 return Mapping; 170 } 171 172 switch (Opc) { 173 case TargetOpcode::G_ADD: 174 case TargetOpcode::G_SUB: 175 return getSameOperandsMapping(MI, false); 176 break; 177 case TargetOpcode::G_FADD: 178 case TargetOpcode::G_FSUB: 179 case TargetOpcode::G_FMUL: 180 case TargetOpcode::G_FDIV: 181 return getSameOperandsMapping(MI, true); 182 break; 183 default: 184 break; 185 } 186 187 unsigned NumOperands = MI.getNumOperands(); 188 189 // Track the bank of each register, use NotFP mapping (all scalars in GPRs) 190 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 191 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); 192 193 // Finally construct the computed mapping. 194 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 195 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 196 return InstructionMapping(); 197 198 return InstructionMapping{DefaultMappingID, /* Cost */ 1, 199 getOperandsMapping(OpdsMapping), NumOperands}; 200 } 201 202 void X86RegisterBankInfo::applyMappingImpl( 203 const OperandsMapper &OpdMapper) const { 204 return applyDefaultMapping(OpdMapper); 205 } 206 207 RegisterBankInfo::InstructionMappings 208 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 209 210 const MachineFunction &MF = *MI.getParent()->getParent(); 211 const TargetSubtargetInfo &STI = MF.getSubtarget(); 212 const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 213 const MachineRegisterInfo &MRI = MF.getRegInfo(); 214 215 switch (MI.getOpcode()) { 216 case TargetOpcode::G_LOAD: 217 case TargetOpcode::G_STORE: { 218 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64 219 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 220 if (Size != 32 && Size != 64) 221 break; 222 223 unsigned NumOperands = MI.getNumOperands(); 224 225 // Track the bank of each register, use FP mapping (all scalars in VEC) 226 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 227 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 228 229 // Finally construct the computed mapping. 230 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 231 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 232 break; 233 234 RegisterBankInfo::InstructionMapping Mapping = InstructionMapping{ 235 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands}; 236 InstructionMappings AltMappings; 237 AltMappings.emplace_back(std::move(Mapping)); 238 return AltMappings; 239 } 240 default: 241 break; 242 } 243 return RegisterBankInfo::getInstrAlternativeMappings(MI); 244 } 245