diff options
Diffstat (limited to 'llvm/utils')
-rw-r--r-- | llvm/utils/TableGen/CodeGenRegisters.cpp | 64 |
1 files changed, 59 insertions, 5 deletions
diff --git a/llvm/utils/TableGen/CodeGenRegisters.cpp b/llvm/utils/TableGen/CodeGenRegisters.cpp index e70a79f08af..74a2b078dfb 100644 --- a/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/IntEqClasses.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" @@ -1309,6 +1310,55 @@ getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts) { } void CodeGenRegBank::computeComposites() { + using RegMap = std::map<const CodeGenRegister*, const CodeGenRegister*>; + + // Subreg -> { Reg->Reg }, where the right-hand side is the mapping from + // register to (sub)register associated with the action of the left-hand + // side subregister. + std::map<const CodeGenSubRegIndex*, RegMap> SubRegAction; + for (const CodeGenRegister &R : Registers) { + const CodeGenRegister::SubRegMap &SM = R.getSubRegs(); + for (std::pair<const CodeGenSubRegIndex*, const CodeGenRegister*> P : SM) + SubRegAction[P.first].insert({&R, P.second}); + } + + // Calculate the composition of two subregisters as compositions of their + // associated actions. + auto compose = [&SubRegAction] (const CodeGenSubRegIndex *Sub1, + const CodeGenSubRegIndex *Sub2) { + RegMap C; + const RegMap &Img1 = SubRegAction.at(Sub1); + const RegMap &Img2 = SubRegAction.at(Sub2); + for (std::pair<const CodeGenRegister*, const CodeGenRegister*> P : Img1) { + auto F = Img2.find(P.second); + if (F != Img2.end()) + C.insert({P.first, F->second}); + } + return C; + }; + + // Check if the two maps agree on the intersection of their domains. + auto agree = [] (const RegMap &Map1, const RegMap &Map2) { + // Technically speaking, an empty map agrees with any other map, but + // this could flag false positives. We're interested in non-vacuous + // agreements. + if (Map1.empty() || Map2.empty()) + return false; + for (std::pair<const CodeGenRegister*, const CodeGenRegister*> P : Map1) { + auto F = Map2.find(P.first); + if (F == Map2.end() || P.second != F->second) + return false; + } + return true; + }; + + using CompositePair = std::pair<const CodeGenSubRegIndex*, + const CodeGenSubRegIndex*>; + SmallSet<CompositePair,4> UserDefined; + for (const CodeGenSubRegIndex &Idx : SubRegIndices) + for (auto P : Idx.getComposites()) + UserDefined.insert(std::make_pair(&Idx, P.first)); + // Keep track of TopoSigs visited. We only need to visit each TopoSig once, // and many registers will share TopoSigs on regular architectures. BitVector TopoSigs(getNumTopoSigs()); @@ -1341,11 +1391,15 @@ void CodeGenRegBank::computeComposites() { assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. - if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) - PrintWarning(Twine("SubRegIndex ") + Idx1->getQualifiedName() + - " and " + Idx2->getQualifiedName() + - " compose ambiguously as " + Prev->getQualifiedName() + - " or " + Idx3->getQualifiedName()); + if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3)) { + // If the composition was not user-defined, always emit a warning. + if (!UserDefined.count({Idx1, Idx2}) || + agree(compose(Idx1, Idx2), SubRegAction.at(Idx3))) + PrintWarning(Twine("SubRegIndex ") + Idx1->getQualifiedName() + + " and " + Idx2->getQualifiedName() + + " compose ambiguously as " + Prev->getQualifiedName() + + " or " + Idx3->getQualifiedName()); + } } } } |