1317017Sdim//===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==// 2317017Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6317017Sdim// 7317017Sdim//===----------------------------------------------------------------------===// 8317017Sdim/// \file 9317017Sdim/// This file implements the targeting of the RegisterBankInfo class for X86. 10317017Sdim/// \todo This should be generated by TableGen. 11317017Sdim//===----------------------------------------------------------------------===// 12317017Sdim 13317017Sdim#include "X86RegisterBankInfo.h" 14317017Sdim#include "X86InstrInfo.h" 15317017Sdim#include "llvm/CodeGen/GlobalISel/RegisterBank.h" 16317017Sdim#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 17317017Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 18327952Sdim#include "llvm/CodeGen/TargetRegisterInfo.h" 19317017Sdim 20317017Sdim#define GET_TARGET_REGBANK_IMPL 21317017Sdim#include "X86GenRegisterBank.inc" 22317017Sdim 23317017Sdimusing namespace llvm; 24317017Sdim// This file will be TableGen'ed at some point. 25317017Sdim#define GET_TARGET_REGBANK_INFO_IMPL 26317017Sdim#include "X86GenRegisterBankInfo.def" 27317017Sdim 28317017SdimX86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) 29317017Sdim : X86GenRegisterBankInfo() { 30317017Sdim 31317017Sdim // validate RegBank initialization. 32317017Sdim const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID); 33317017Sdim (void)RBGPR; 34317017Sdim assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization."); 35317017Sdim 36317017Sdim // The GPR register bank is fully defined by all the registers in 37317017Sdim // GR64 + its subclasses. 38317017Sdim assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) && 39317017Sdim "Subclass not added?"); 40317017Sdim assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); 41317017Sdim} 42317017Sdim 43360784Sdimconst RegisterBank & 44360784SdimX86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC, 45360784Sdim LLT) const { 46317017Sdim 47317017Sdim if (X86::GR8RegClass.hasSubClassEq(&RC) || 48317017Sdim X86::GR16RegClass.hasSubClassEq(&RC) || 49317017Sdim X86::GR32RegClass.hasSubClassEq(&RC) || 50360784Sdim X86::GR64RegClass.hasSubClassEq(&RC) || 51360784Sdim X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) || 52360784Sdim X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC)) 53317017Sdim return getRegBank(X86::GPRRegBankID); 54317017Sdim 55317017Sdim if (X86::FR32XRegClass.hasSubClassEq(&RC) || 56317017Sdim X86::FR64XRegClass.hasSubClassEq(&RC) || 57317017Sdim X86::VR128XRegClass.hasSubClassEq(&RC) || 58317017Sdim X86::VR256XRegClass.hasSubClassEq(&RC) || 59317017Sdim X86::VR512RegClass.hasSubClassEq(&RC)) 60317017Sdim return getRegBank(X86::VECRRegBankID); 61317017Sdim 62317017Sdim llvm_unreachable("Unsupported register kind yet."); 63317017Sdim} 64317017Sdim 65317017SdimX86GenRegisterBankInfo::PartialMappingIdx 66317017SdimX86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) { 67317017Sdim if ((Ty.isScalar() && !isFP) || Ty.isPointer()) { 68317017Sdim switch (Ty.getSizeInBits()) { 69317230Sdim case 1: 70317017Sdim case 8: 71317017Sdim return PMI_GPR8; 72317017Sdim case 16: 73317017Sdim return PMI_GPR16; 74317017Sdim case 32: 75317017Sdim return PMI_GPR32; 76317017Sdim case 64: 77317017Sdim return PMI_GPR64; 78341825Sdim case 128: 79341825Sdim return PMI_VEC128; 80317017Sdim break; 81317017Sdim default: 82317017Sdim llvm_unreachable("Unsupported register size."); 83317017Sdim } 84317017Sdim } else if (Ty.isScalar()) { 85317017Sdim switch (Ty.getSizeInBits()) { 86317017Sdim case 32: 87317017Sdim return PMI_FP32; 88317017Sdim case 64: 89317017Sdim return PMI_FP64; 90341825Sdim case 128: 91341825Sdim return PMI_VEC128; 92317017Sdim default: 93317017Sdim llvm_unreachable("Unsupported register size."); 94317017Sdim } 95317017Sdim } else { 96317017Sdim switch (Ty.getSizeInBits()) { 97317017Sdim case 128: 98317017Sdim return PMI_VEC128; 99317017Sdim case 256: 100317017Sdim return PMI_VEC256; 101317017Sdim case 512: 102317017Sdim return PMI_VEC512; 103317017Sdim default: 104317017Sdim llvm_unreachable("Unsupported register size."); 105317017Sdim } 106317017Sdim } 107317017Sdim 108317017Sdim return PMI_None; 109317017Sdim} 110317017Sdim 111317017Sdimvoid X86RegisterBankInfo::getInstrPartialMappingIdxs( 112317017Sdim const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP, 113317017Sdim SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) { 114317017Sdim 115317017Sdim unsigned NumOperands = MI.getNumOperands(); 116317017Sdim for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 117317017Sdim auto &MO = MI.getOperand(Idx); 118317017Sdim if (!MO.isReg()) 119317017Sdim OpRegBankIdx[Idx] = PMI_None; 120317017Sdim else 121317017Sdim OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP); 122317017Sdim } 123317017Sdim} 124317017Sdim 125317017Sdimbool X86RegisterBankInfo::getInstrValueMapping( 126317017Sdim const MachineInstr &MI, 127317017Sdim const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx, 128317017Sdim SmallVectorImpl<const ValueMapping *> &OpdsMapping) { 129317017Sdim 130317017Sdim unsigned NumOperands = MI.getNumOperands(); 131317017Sdim for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 132317017Sdim if (!MI.getOperand(Idx).isReg()) 133317017Sdim continue; 134317017Sdim 135317017Sdim auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1); 136317017Sdim if (!Mapping->isValid()) 137317017Sdim return false; 138317017Sdim 139317017Sdim OpdsMapping[Idx] = Mapping; 140317017Sdim } 141317017Sdim return true; 142317017Sdim} 143317017Sdim 144317969Sdimconst RegisterBankInfo::InstructionMapping & 145317969SdimX86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI, 146317969Sdim bool isFP) const { 147317017Sdim const MachineFunction &MF = *MI.getParent()->getParent(); 148317017Sdim const MachineRegisterInfo &MRI = MF.getRegInfo(); 149317017Sdim 150317017Sdim unsigned NumOperands = MI.getNumOperands(); 151317017Sdim LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 152317017Sdim 153317017Sdim if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) || 154317017Sdim (Ty != MRI.getType(MI.getOperand(2).getReg()))) 155317017Sdim llvm_unreachable("Unsupported operand mapping yet."); 156317017Sdim 157317017Sdim auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3); 158317969Sdim return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 159317017Sdim} 160317017Sdim 161317969Sdimconst RegisterBankInfo::InstructionMapping & 162317017SdimX86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 163317017Sdim const MachineFunction &MF = *MI.getParent()->getParent(); 164317017Sdim const MachineRegisterInfo &MRI = MF.getRegInfo(); 165353358Sdim unsigned Opc = MI.getOpcode(); 166317017Sdim 167317017Sdim // Try the default logic for non-generic instructions that are either copies 168317017Sdim // or already have some operands assigned to banks. 169327952Sdim if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) { 170317969Sdim const InstructionMapping &Mapping = getInstrMappingImpl(MI); 171317017Sdim if (Mapping.isValid()) 172317017Sdim return Mapping; 173317017Sdim } 174317017Sdim 175317017Sdim switch (Opc) { 176317017Sdim case TargetOpcode::G_ADD: 177317017Sdim case TargetOpcode::G_SUB: 178341825Sdim case TargetOpcode::G_MUL: 179317017Sdim return getSameOperandsMapping(MI, false); 180317017Sdim case TargetOpcode::G_FADD: 181317017Sdim case TargetOpcode::G_FSUB: 182317017Sdim case TargetOpcode::G_FMUL: 183317017Sdim case TargetOpcode::G_FDIV: 184317017Sdim return getSameOperandsMapping(MI, true); 185353358Sdim case TargetOpcode::G_SHL: 186353358Sdim case TargetOpcode::G_LSHR: 187353358Sdim case TargetOpcode::G_ASHR: { 188353358Sdim unsigned NumOperands = MI.getNumOperands(); 189353358Sdim LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 190353358Sdim 191353358Sdim auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3); 192353358Sdim return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands); 193353358Sdim 194353358Sdim } 195317017Sdim default: 196317017Sdim break; 197317017Sdim } 198317017Sdim 199317017Sdim unsigned NumOperands = MI.getNumOperands(); 200317017Sdim SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 201317017Sdim 202327952Sdim switch (Opc) { 203327952Sdim case TargetOpcode::G_FPEXT: 204344779Sdim case TargetOpcode::G_FPTRUNC: 205327952Sdim case TargetOpcode::G_FCONSTANT: 206327952Sdim // Instruction having only floating-point operands (all scalars in VECRReg) 207327952Sdim getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 208327952Sdim break; 209344779Sdim case TargetOpcode::G_SITOFP: 210344779Sdim case TargetOpcode::G_FPTOSI: { 211341825Sdim // Some of the floating-point instructions have mixed GPR and FP operands: 212341825Sdim // fine-tune the computed mapping. 213341825Sdim auto &Op0 = MI.getOperand(0); 214341825Sdim auto &Op1 = MI.getOperand(1); 215341825Sdim const LLT Ty0 = MRI.getType(Op0.getReg()); 216341825Sdim const LLT Ty1 = MRI.getType(Op1.getReg()); 217344779Sdim 218344779Sdim bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP; 219344779Sdim bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI; 220344779Sdim OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP); 221344779Sdim OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP); 222341825Sdim break; 223341825Sdim } 224344779Sdim case TargetOpcode::G_FCMP: { 225344779Sdim LLT Ty1 = MRI.getType(MI.getOperand(2).getReg()); 226344779Sdim LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 227344779Sdim (void)Ty2; 228344779Sdim assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() && 229344779Sdim "Mismatched operand sizes for G_FCMP"); 230344779Sdim 231344779Sdim unsigned Size = Ty1.getSizeInBits(); 232344779Sdim (void)Size; 233344779Sdim assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP"); 234344779Sdim 235344779Sdim auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true); 236344779Sdim OpRegBankIdx = {PMI_GPR8, 237344779Sdim /* Predicate */ PMI_None, FpRegBank, FpRegBank}; 238344779Sdim break; 239344779Sdim } 240341825Sdim case TargetOpcode::G_TRUNC: 241341825Sdim case TargetOpcode::G_ANYEXT: { 242341825Sdim auto &Op0 = MI.getOperand(0); 243341825Sdim auto &Op1 = MI.getOperand(1); 244341825Sdim const LLT Ty0 = MRI.getType(Op0.getReg()); 245341825Sdim const LLT Ty1 = MRI.getType(Op1.getReg()); 246341825Sdim 247341825Sdim bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) && 248341825Sdim Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC; 249341825Sdim bool isFPAnyExt = 250341825Sdim Ty0.getSizeInBits() == 128 && 251341825Sdim (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) && 252341825Sdim Opc == TargetOpcode::G_ANYEXT; 253341825Sdim 254341825Sdim getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt, 255341825Sdim OpRegBankIdx); 256341825Sdim } break; 257327952Sdim default: 258327952Sdim // Track the bank of each register, use NotFP mapping (all scalars in GPRs) 259327952Sdim getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx); 260327952Sdim break; 261327952Sdim } 262327952Sdim 263317017Sdim // Finally construct the computed mapping. 264317017Sdim SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 265317017Sdim if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 266317969Sdim return getInvalidInstructionMapping(); 267317017Sdim 268317969Sdim return getInstructionMapping(DefaultMappingID, /* Cost */ 1, 269317969Sdim getOperandsMapping(OpdsMapping), NumOperands); 270317017Sdim} 271317017Sdim 272317017Sdimvoid X86RegisterBankInfo::applyMappingImpl( 273317017Sdim const OperandsMapper &OpdMapper) const { 274317017Sdim return applyDefaultMapping(OpdMapper); 275317017Sdim} 276317017Sdim 277317017SdimRegisterBankInfo::InstructionMappings 278317017SdimX86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 279317017Sdim 280317017Sdim const MachineFunction &MF = *MI.getParent()->getParent(); 281317017Sdim const TargetSubtargetInfo &STI = MF.getSubtarget(); 282317017Sdim const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 283317017Sdim const MachineRegisterInfo &MRI = MF.getRegInfo(); 284317017Sdim 285317017Sdim switch (MI.getOpcode()) { 286317017Sdim case TargetOpcode::G_LOAD: 287327952Sdim case TargetOpcode::G_STORE: 288327952Sdim case TargetOpcode::G_IMPLICIT_DEF: { 289317017Sdim // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64 290317017Sdim unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); 291317017Sdim if (Size != 32 && Size != 64) 292317017Sdim break; 293317017Sdim 294317017Sdim unsigned NumOperands = MI.getNumOperands(); 295317017Sdim 296317017Sdim // Track the bank of each register, use FP mapping (all scalars in VEC) 297317017Sdim SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands); 298317017Sdim getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx); 299317017Sdim 300317017Sdim // Finally construct the computed mapping. 301317017Sdim SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands); 302317017Sdim if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping)) 303317017Sdim break; 304317017Sdim 305317969Sdim const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping( 306317969Sdim /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands); 307317017Sdim InstructionMappings AltMappings; 308317969Sdim AltMappings.push_back(&Mapping); 309317017Sdim return AltMappings; 310317017Sdim } 311317017Sdim default: 312317017Sdim break; 313317017Sdim } 314317017Sdim return RegisterBankInfo::getInstrAlternativeMappings(MI); 315317017Sdim} 316