mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-18 14:31:27 +00: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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146873 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a9f65b9a1f
commit
570f9a972e
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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*
|
||||
|
@ -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() +
|
||||
|
@ -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.
|
||||
|
@ -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";
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user