summaryrefslogtreecommitdiffstats
path: root/llvm/utils
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils')
-rw-r--r--llvm/utils/TableGen/CodeGenRegisters.cpp64
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());
+ }
}
}
}
OpenPOWER on IntegriCloud