1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00
llvm-mirror/lib/Target/X86/X86RegisterBankInfo.cpp
David Blaikie e01dc73ad2 Fix a bunch more layering of CodeGen headers that are in Target
All these headers already depend on CodeGen headers so moving them into
CodeGen fixes the layering (since CodeGen depends on Target, not the
other way around).

llvm-svn: 318490
2017-11-17 01:07:10 +00:00

252 lines
8.1 KiB
C++

//===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
/// This file implements the targeting of the RegisterBankInfo class for X86.
/// \todo This should be generated by TableGen.
//===----------------------------------------------------------------------===//
#include "X86RegisterBankInfo.h"
#include "X86InstrInfo.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#define GET_TARGET_REGBANK_IMPL
#include "X86GenRegisterBank.inc"
using namespace llvm;
// This file will be TableGen'ed at some point.
#define GET_TARGET_REGBANK_INFO_IMPL
#include "X86GenRegisterBankInfo.def"
X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI)
: X86GenRegisterBankInfo() {
// validate RegBank initialization.
const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
(void)RBGPR;
assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
// The GPR register bank is fully defined by all the registers in
// GR64 + its subclasses.
assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
"Subclass not added?");
assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
}
const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass(
const TargetRegisterClass &RC) const {
if (X86::GR8RegClass.hasSubClassEq(&RC) ||
X86::GR16RegClass.hasSubClassEq(&RC) ||
X86::GR32RegClass.hasSubClassEq(&RC) ||
X86::GR64RegClass.hasSubClassEq(&RC))
return getRegBank(X86::GPRRegBankID);
if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
X86::FR64XRegClass.hasSubClassEq(&RC) ||
X86::VR128XRegClass.hasSubClassEq(&RC) ||
X86::VR256XRegClass.hasSubClassEq(&RC) ||
X86::VR512RegClass.hasSubClassEq(&RC))
return getRegBank(X86::VECRRegBankID);
llvm_unreachable("Unsupported register kind yet.");
}
X86GenRegisterBankInfo::PartialMappingIdx
X86GenRegisterBankInfo::getPartialMappingIdx(const LLT &Ty, bool isFP) {
if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
switch (Ty.getSizeInBits()) {
case 1:
case 8:
return PMI_GPR8;
case 16:
return PMI_GPR16;
case 32:
return PMI_GPR32;
case 64:
return PMI_GPR64;
break;
default:
llvm_unreachable("Unsupported register size.");
}
} else if (Ty.isScalar()) {
switch (Ty.getSizeInBits()) {
case 32:
return PMI_FP32;
case 64:
return PMI_FP64;
default:
llvm_unreachable("Unsupported register size.");
}
} else {
switch (Ty.getSizeInBits()) {
case 128:
return PMI_VEC128;
case 256:
return PMI_VEC256;
case 512:
return PMI_VEC512;
default:
llvm_unreachable("Unsupported register size.");
}
}
return PMI_None;
}
void X86RegisterBankInfo::getInstrPartialMappingIdxs(
const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
unsigned NumOperands = MI.getNumOperands();
for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
auto &MO = MI.getOperand(Idx);
if (!MO.isReg())
OpRegBankIdx[Idx] = PMI_None;
else
OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
}
}
bool X86RegisterBankInfo::getInstrValueMapping(
const MachineInstr &MI,
const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
unsigned NumOperands = MI.getNumOperands();
for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
if (!MI.getOperand(Idx).isReg())
continue;
auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
if (!Mapping->isValid())
return false;
OpdsMapping[Idx] = Mapping;
}
return true;
}
const RegisterBankInfo::InstructionMapping &
X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
bool isFP) const {
const MachineFunction &MF = *MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF.getRegInfo();
unsigned NumOperands = MI.getNumOperands();
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
(Ty != MRI.getType(MI.getOperand(2).getReg())))
llvm_unreachable("Unsupported operand mapping yet.");
auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
}
const RegisterBankInfo::InstructionMapping &
X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
const MachineFunction &MF = *MI.getParent()->getParent();
const MachineRegisterInfo &MRI = MF.getRegInfo();
auto Opc = MI.getOpcode();
// Try the default logic for non-generic instructions that are either copies
// or already have some operands assigned to banks.
if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
const InstructionMapping &Mapping = getInstrMappingImpl(MI);
if (Mapping.isValid())
return Mapping;
}
switch (Opc) {
case TargetOpcode::G_ADD:
case TargetOpcode::G_SUB:
return getSameOperandsMapping(MI, false);
break;
case TargetOpcode::G_FADD:
case TargetOpcode::G_FSUB:
case TargetOpcode::G_FMUL:
case TargetOpcode::G_FDIV:
return getSameOperandsMapping(MI, true);
break;
default:
break;
}
unsigned NumOperands = MI.getNumOperands();
SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
switch (Opc) {
case TargetOpcode::G_FPEXT:
case TargetOpcode::G_FCONSTANT:
// Instruction having only floating-point operands (all scalars in VECRReg)
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
break;
default:
// Track the bank of each register, use NotFP mapping (all scalars in GPRs)
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
break;
}
// Finally construct the computed mapping.
SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
return getInvalidInstructionMapping();
return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
getOperandsMapping(OpdsMapping), NumOperands);
}
void X86RegisterBankInfo::applyMappingImpl(
const OperandsMapper &OpdMapper) const {
return applyDefaultMapping(OpdMapper);
}
RegisterBankInfo::InstructionMappings
X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
const MachineFunction &MF = *MI.getParent()->getParent();
const TargetSubtargetInfo &STI = MF.getSubtarget();
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
const MachineRegisterInfo &MRI = MF.getRegInfo();
switch (MI.getOpcode()) {
case TargetOpcode::G_LOAD:
case TargetOpcode::G_STORE:
case TargetOpcode::G_IMPLICIT_DEF: {
// we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
if (Size != 32 && Size != 64)
break;
unsigned NumOperands = MI.getNumOperands();
// Track the bank of each register, use FP mapping (all scalars in VEC)
SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
// Finally construct the computed mapping.
SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
break;
const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
/*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
InstructionMappings AltMappings;
AltMappings.push_back(&Mapping);
return AltMappings;
}
default:
break;
}
return RegisterBankInfo::getInstrAlternativeMappings(MI);
}