summaryrefslogtreecommitdiff
path: root/utils/TableGen/CodeGenRegisters.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/CodeGenRegisters.cpp')
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp78
1 files changed, 78 insertions, 0 deletions
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 3907336221a4..d4a21a986c58 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -915,6 +915,84 @@ void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
RC.inheritProperties(RegBank);
}
+Optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
+CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
+ CodeGenRegBank &RegBank, const CodeGenSubRegIndex *SubIdx) const {
+ auto SizeOrder = [](const CodeGenRegisterClass *A,
+ const CodeGenRegisterClass *B) {
+ return A->getMembers().size() > B->getMembers().size();
+ };
+
+ auto &RegClasses = RegBank.getRegClasses();
+
+ // Find all the subclasses of this one that fully support the sub-register
+ // index and order them by size. BiggestSuperRC should always be first.
+ CodeGenRegisterClass *BiggestSuperRegRC = getSubClassWithSubReg(SubIdx);
+ if (!BiggestSuperRegRC)
+ return None;
+ BitVector SuperRegRCsBV = BiggestSuperRegRC->getSubClasses();
+ std::vector<CodeGenRegisterClass *> SuperRegRCs;
+ for (auto &RC : RegClasses)
+ if (SuperRegRCsBV[RC.EnumValue])
+ SuperRegRCs.emplace_back(&RC);
+ std::sort(SuperRegRCs.begin(), SuperRegRCs.end(), SizeOrder);
+ assert(SuperRegRCs.front() == BiggestSuperRegRC && "Biggest class wasn't first");
+
+ // Find all the subreg classes and order them by size too.
+ std::vector<std::pair<CodeGenRegisterClass *, BitVector>> SuperRegClasses;
+ for (auto &RC: RegClasses) {
+ BitVector SuperRegClassesBV(RegClasses.size());
+ RC.getSuperRegClasses(SubIdx, SuperRegClassesBV);
+ if (SuperRegClassesBV.any())
+ SuperRegClasses.push_back(std::make_pair(&RC, SuperRegClassesBV));
+ }
+ std::sort(SuperRegClasses.begin(), SuperRegClasses.end(),
+ [&](const std::pair<CodeGenRegisterClass *, BitVector> &A,
+ const std::pair<CodeGenRegisterClass *, BitVector> &B) {
+ return SizeOrder(A.first, B.first);
+ });
+
+ // Find the biggest subclass and subreg class such that R:subidx is in the
+ // subreg class for all R in subclass.
+ //
+ // For example:
+ // All registers in X86's GR64 have a sub_32bit subregister but no class
+ // exists that contains all the 32-bit subregisters because GR64 contains RIP
+ // but GR32 does not contain EIP. Instead, we constrain SuperRegRC to
+ // GR32_with_sub_8bit (which is identical to GR32_with_sub_32bit) and then,
+ // having excluded RIP, we are able to find a SubRegRC (GR32).
+ CodeGenRegisterClass *ChosenSuperRegClass = nullptr;
+ CodeGenRegisterClass *SubRegRC = nullptr;
+ for (auto *SuperRegRC : SuperRegRCs) {
+ for (const auto &SuperRegClassPair : SuperRegClasses) {
+ const BitVector &SuperRegClassBV = SuperRegClassPair.second;
+ if (SuperRegClassBV[SuperRegRC->EnumValue]) {
+ SubRegRC = SuperRegClassPair.first;
+ ChosenSuperRegClass = SuperRegRC;
+
+ // If SubRegRC is bigger than SuperRegRC then there are members of
+ // SubRegRC that don't have super registers via SubIdx. Keep looking to
+ // find a better fit and fall back on this one if there isn't one.
+ //
+ // This is intended to prevent X86 from making odd choices such as
+ // picking LOW32_ADDR_ACCESS_RBP instead of GR32 in the example above.
+ // LOW32_ADDR_ACCESS_RBP is a valid choice but contains registers that
+ // aren't subregisters of SuperRegRC whereas GR32 has a direct 1:1
+ // mapping.
+ if (SuperRegRC->getMembers().size() >= SubRegRC->getMembers().size())
+ return std::make_pair(ChosenSuperRegClass, SubRegRC);
+ }
+ }
+
+ // If we found a fit but it wasn't quite ideal because SubRegRC had excess
+ // registers, then we're done.
+ if (ChosenSuperRegClass)
+ return std::make_pair(ChosenSuperRegClass, SubRegRC);
+ }
+
+ return None;
+}
+
void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
BitVector &Out) const {
auto FindI = SuperRegClasses.find(SubIdx);