1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

Emit a getMatchingSuperRegClass() implementation for every target.

Use information computed while inferring new register classes to emit
accurate, table-driven implementations of getMatchingSuperRegClass().

Delete the old manual, error-prone implementations in the targets.

llvm-svn: 146873
This commit is contained in:
Jakob Stoklund Olesen 2011-12-19 16:53:34 +00:00
parent 78291d0bac
commit 0aa2f7755a
8 changed files with 90 additions and 231 deletions

View File

@ -402,11 +402,11 @@ public:
/// getMatchingSuperRegClass - Return a subclass of the specified register
/// class A so that each register in it has a sub-register of the
/// specified sub-register index which is in the specified register class B.
///
/// TableGen will synthesize missing A sub-classes.
virtual const TargetRegisterClass *
getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B, unsigned Idx) const {
return 0;
}
const TargetRegisterClass *B, unsigned Idx) const =0;
/// getSubClassWithSubReg - Returns the largest legal sub-class of RC that
/// supports the sub-register index Idx.
@ -419,6 +419,7 @@ public:
/// supported by the full GR32 register class in 64-bit mode, but only by the
/// GR32_ABCD regiister class in 32-bit mode.
///
/// TableGen will synthesize missing RC sub-classes.
virtual const TargetRegisterClass *
getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx) const =0;

View File

@ -135,104 +135,6 @@ bool ARMBaseRegisterInfo::isReservedReg(const MachineFunction &MF,
return false;
}
const TargetRegisterClass *
ARMBaseRegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B,
unsigned SubIdx) const {
switch (SubIdx) {
default: return 0;
case ARM::ssub_0:
case ARM::ssub_1:
case ARM::ssub_2:
case ARM::ssub_3: {
// S sub-registers.
if (A->getSize() == 8) {
if (B == &ARM::SPR_8RegClass)
return &ARM::DPR_8RegClass;
assert(B == &ARM::SPRRegClass && "Expecting SPR register class!");
if (A == &ARM::DPR_8RegClass)
return A;
return &ARM::DPR_VFP2RegClass;
}
if (A->getSize() == 16) {
if (B == &ARM::SPR_8RegClass)
return &ARM::QPR_8RegClass;
return &ARM::QPR_VFP2RegClass;
}
if (A->getSize() == 32) {
if (B == &ARM::SPR_8RegClass)
return 0; // Do not allow coalescing!
return &ARM::QQPR_VFP2RegClass;
}
assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
return 0; // Do not allow coalescing!
}
case ARM::dsub_0:
case ARM::dsub_1:
case ARM::dsub_2:
case ARM::dsub_3: {
// D sub-registers.
if (A->getSize() == 16) {
if (B == &ARM::DPR_VFP2RegClass)
return &ARM::QPR_VFP2RegClass;
if (B == &ARM::DPR_8RegClass)
return 0; // Do not allow coalescing!
return A;
}
if (A->getSize() == 32) {
if (B == &ARM::DPR_VFP2RegClass)
return &ARM::QQPR_VFP2RegClass;
if (B == &ARM::DPR_8RegClass)
return 0; // Do not allow coalescing!
return A;
}
assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
if (B != &ARM::DPRRegClass)
return 0; // Do not allow coalescing!
return A;
}
case ARM::dsub_4:
case ARM::dsub_5:
case ARM::dsub_6:
case ARM::dsub_7: {
// D sub-registers of QQQQ registers.
if (A->getSize() == 64 && B == &ARM::DPRRegClass)
return A;
return 0; // Do not allow coalescing!
}
case ARM::qsub_0:
case ARM::qsub_1: {
// Q sub-registers.
if (A->getSize() == 32) {
if (B == &ARM::QPR_VFP2RegClass)
return &ARM::QQPR_VFP2RegClass;
if (B == &ARM::QPR_8RegClass)
return 0; // Do not allow coalescing!
return A;
}
assert(A->getSize() == 64 && "Expecting a QQQQ register class!");
if (B == &ARM::QPRRegClass)
return A;
return 0; // Do not allow coalescing!
}
case ARM::qsub_2:
case ARM::qsub_3: {
// Q sub-registers of QQQQ registers.
if (A->getSize() == 64 && B == &ARM::QPRRegClass)
return A;
return 0; // Do not allow coalescing!
}
}
return 0;
}
bool
ARMBaseRegisterInfo::canCombineSubRegIndices(const TargetRegisterClass *RC,
SmallVectorImpl<unsigned> &SubIndices,

View File

@ -98,13 +98,6 @@ public:
BitVector getReservedRegs(const MachineFunction &MF) const;
/// getMatchingSuperRegClass - Return a subclass of the specified register
/// class A so that each register in it has a sub-register of the
/// specified sub-register index which is in the specified register class B.
virtual const TargetRegisterClass *
getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B, unsigned Idx) const;
/// canCombineSubRegIndices - Given a register class and a list of
/// subregister indices, return true if it's possible to combine the
/// subregister indices into one that corresponds to a larger

View File

@ -41,13 +41,6 @@ public:
BitVector getReservedRegs(const MachineFunction &MF) const;
const TargetRegisterClass* getPointerRegClass(unsigned Kind = 0) const;
const TargetRegisterClass *
getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B, unsigned Idx) const {
// No sub-classes makes this really easy.
return A;
}
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;

View File

@ -127,121 +127,13 @@ const TargetRegisterClass *
X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
const TargetRegisterClass *B,
unsigned SubIdx) const {
switch (SubIdx) {
default: return 0;
case X86::sub_8bit:
if (B == &X86::GR8RegClass) {
if (A->getSize() == 2 || A->getSize() == 4 || A->getSize() == 8)
return A;
} else if (B == &X86::GR8_ABCD_LRegClass || B == &X86::GR8_ABCD_HRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass ||
A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass ||
A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_ABCDRegClass;
else if (A == &X86::GR32RegClass || A == &X86::GR32_ABCDRegClass ||
A == &X86::GR32_NOREXRegClass ||
A == &X86::GR32_NOSPRegClass)
return &X86::GR32_ABCDRegClass;
else if (A == &X86::GR16RegClass || A == &X86::GR16_ABCDRegClass ||
A == &X86::GR16_NOREXRegClass)
return &X86::GR16_ABCDRegClass;
} else if (B == &X86::GR8_NOREXRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_NOREXRegClass;
else if (A == &X86::GR64_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
else if (A == &X86::GR32RegClass || A == &X86::GR32_NOREXRegClass ||
A == &X86::GR32_NOSPRegClass)
return &X86::GR32_NOREXRegClass;
else if (A == &X86::GR32_ABCDRegClass)
return &X86::GR32_ABCDRegClass;
else if (A == &X86::GR16RegClass || A == &X86::GR16_NOREXRegClass)
return &X86::GR16_NOREXRegClass;
else if (A == &X86::GR16_ABCDRegClass)
return &X86::GR16_ABCDRegClass;
}
break;
case X86::sub_8bit_hi:
if (B->hasSubClassEq(&X86::GR8_ABCD_HRegClass))
switch (A->getSize()) {
case 2: return getCommonSubClass(A, &X86::GR16_ABCDRegClass);
case 4: return getCommonSubClass(A, &X86::GR32_ABCDRegClass);
case 8: return getCommonSubClass(A, &X86::GR64_ABCDRegClass);
default: return 0;
}
break;
case X86::sub_16bit:
if (B == &X86::GR16RegClass) {
if (A->getSize() == 4 || A->getSize() == 8)
return A;
} else if (B == &X86::GR16_ABCDRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass ||
A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass ||
A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_ABCDRegClass;
else if (A == &X86::GR32RegClass || A == &X86::GR32_ABCDRegClass ||
A == &X86::GR32_NOREXRegClass || A == &X86::GR32_NOSPRegClass)
return &X86::GR32_ABCDRegClass;
} else if (B == &X86::GR16_NOREXRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_NOREXRegClass;
else if (A == &X86::GR64_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
else if (A == &X86::GR32RegClass || A == &X86::GR32_NOREXRegClass ||
A == &X86::GR32_NOSPRegClass)
return &X86::GR32_NOREXRegClass;
else if (A == &X86::GR32_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
}
break;
case X86::sub_32bit:
if (B == &X86::GR32RegClass) {
if (A->getSize() == 8)
return A;
} else if (B == &X86::GR32_NOSPRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_NOSPRegClass)
return &X86::GR64_NOSPRegClass;
if (A->getSize() == 8)
return getCommonSubClass(A, &X86::GR64_NOSPRegClass);
} else if (B == &X86::GR32_ABCDRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_ABCDRegClass ||
A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass ||
A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_ABCDRegClass;
} else if (B == &X86::GR32_NOREXRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass)
return &X86::GR64_NOREXRegClass;
else if (A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_NOREX_NOSPRegClass;
else if (A == &X86::GR64_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
} else if (B == &X86::GR32_NOREX_NOSPRegClass) {
if (A == &X86::GR64RegClass || A == &X86::GR64_NOREXRegClass ||
A == &X86::GR64_NOSPRegClass || A == &X86::GR64_NOREX_NOSPRegClass)
return &X86::GR64_NOREX_NOSPRegClass;
else if (A == &X86::GR64_ABCDRegClass)
return &X86::GR64_ABCDRegClass;
}
break;
case X86::sub_ss:
if (B == &X86::FR32RegClass)
return A;
break;
case X86::sub_sd:
if (B == &X86::FR64RegClass)
return A;
break;
case X86::sub_xmm:
if (B == &X86::VR128RegClass)
return A;
break;
// The sub_8bit sub-register index is more constrained in 32-bit mode.
if (!Is64Bit && SubIdx == X86::sub_8bit) {
A = X86GenRegisterInfo::getSubClassWithSubReg(A, X86::sub_8bit_hi);
if (!A)
return 0;
}
return 0;
return X86GenRegisterInfo::getMatchingSuperRegClass(A, B, SubIdx);
}
const TargetRegisterClass*

View File

@ -504,6 +504,18 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
RegClasses[rci]->inheritProperties(RegBank);
}
void
CodeGenRegisterClass::getSuperRegClasses(Record *SubIdx, BitVector &Out) const {
DenseMap<Record*, SmallPtrSet<CodeGenRegisterClass*, 8> >::const_iterator
FindI = SuperRegClasses.find(SubIdx);
if (FindI == SuperRegClasses.end())
return;
for (SmallPtrSet<CodeGenRegisterClass*, 8>::const_iterator I =
FindI->second.begin(), E = FindI->second.end(); I != E; ++I)
Out.set((*I)->EnumValue);
}
//===----------------------------------------------------------------------===//
// CodeGenRegBank
//===----------------------------------------------------------------------===//
@ -879,8 +891,10 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
if (SubSet.empty())
continue;
// RC injects completely into SubRC.
if (SubSet.size() == SSPairs.size())
if (SubSet.size() == SSPairs.size()) {
SubRC->addSuperRegClass(SubIdx, RC);
continue;
}
// Only a subset of RC maps into SubRC. Make sure it is represented by a
// class.
getOrCreateSubClass(RC, &SubSet, RC->getName() +

View File

@ -101,9 +101,16 @@ namespace llvm {
// super-class.
void inheritProperties(CodeGenRegBank&);
// Map SubRegIndex -> sub-class
// Map SubRegIndex -> sub-class. This is the largest sub-class where all
// registers have a SubRegIndex sub-register.
DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg;
// Map SubRegIndex -> set of super-reg classes. This is all register
// classes SuperRC such that:
//
// R:SubRegIndex in this RC for all R in SuperRC.
//
DenseMap<Record*, SmallPtrSet<CodeGenRegisterClass*, 8> > SuperRegClasses;
public:
unsigned EnumValue;
std::string Namespace;
@ -158,6 +165,15 @@ namespace llvm {
SubClassWithSubReg[SubIdx] = SubRC;
}
// getSuperRegClasses - Returns a bit vector of all register classes
// containing only SubIdx super-registers of this class.
void getSuperRegClasses(Record *SubIdx, BitVector &Out) const;
// addSuperRegClass - Add a class containing only SudIdx super-registers.
void addSuperRegClass(Record *SubIdx, CodeGenRegisterClass *SuperRC) {
SuperRegClasses[SubIdx].insert(SuperRC);
}
// getSubClasses - Returns a constant BitVector of subclasses indexed by
// EnumValue.
// The SubClasses vector includs an entry for this class.

View File

@ -426,6 +426,9 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
<< " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
<< " const TargetRegisterClass *"
"getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"
<< " const TargetRegisterClass *getMatchingSuperRegClass("
"const TargetRegisterClass*, const TargetRegisterClass*, "
"unsigned) const;\n"
<< "};\n\n";
const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
@ -815,6 +818,51 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "}\n\n";
// Emit getMatchingSuperRegClass.
OS << "const TargetRegisterClass *" << ClassName
<< "::getMatchingSuperRegClass(const TargetRegisterClass *A,"
" const TargetRegisterClass *B, unsigned Idx) const {\n";
if (SubRegIndices.empty()) {
OS << " llvm_unreachable(\"Target has no sub-registers\");\n";
} else {
// We need to find the largest sub-class of A such that every register has
// an Idx sub-register in B. Map (B, Idx) to a bit-vector of
// super-register classes that map into B. Then compute the largest common
// sub-class with A by taking advantage of the register class ordering,
// like getCommonSubClass().
// Bitvector table is NumRCs x NumSubIndexes x BVWords, where BVWords is
// the number of 32-bit words required to represent all register classes.
const unsigned BVWords = (RegisterClasses.size()+31)/32;
BitVector BV(RegisterClasses.size());
OS << " static const unsigned Table[" << RegisterClasses.size()
<< "][" << SubRegIndices.size() << "][" << BVWords << "] = {\n";
for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
const CodeGenRegisterClass &RC = *RegisterClasses[rci];
OS << " {\t// " << RC.getName() << "\n";
for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
Record *Idx = SubRegIndices[sri];
BV.reset();
RC.getSuperRegClasses(Idx, BV);
OS << " { ";
printBitVectorAsHex(OS, BV, 32);
OS << "},\t// " << Idx->getName() << '\n';
}
OS << " },\n";
}
OS << " };\n assert(A && B && \"Missing regclass\");\n"
<< " --Idx;\n"
<< " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n"
<< " const unsigned *TV = Table[B->getID()][Idx];\n"
<< " const unsigned *SC = A->getSubClassMask();\n"
<< " for (unsigned i = 0; i != " << BVWords << "; ++i)\n"
<< " if (unsigned Common = TV[i] & SC[i])\n"
<< " return getRegClass(32*i + CountTrailingZeros_32(Common));\n"
<< " return 0;\n";
}
OS << "}\n\n";
// Emit the constructor of the class...
OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";