aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp157
1 files changed, 81 insertions, 76 deletions
diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index ca6aa4b..076d042 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -41,7 +41,6 @@ static inline bool isIntegerOrPtr(MVT VT) {
static inline bool isFloatingPoint(MVT VT) { return VT.isFloatingPoint(); }
static inline bool isVector(MVT VT) { return VT.isVector(); }
static inline bool isScalar(MVT VT) { return !VT.isVector(); }
-static inline bool isScalarInteger(MVT VT) { return VT.isScalarInteger(); }
template <typename Predicate>
static bool berase_if(MachineValueTypeSet &S, Predicate P) {
@@ -262,85 +261,91 @@ LLVM_DUMP_METHOD
void TypeSetByHwMode::dump() const { dbgs() << *this << '\n'; }
bool TypeSetByHwMode::intersect(SetType &Out, const SetType &In) {
- bool OutP = Out.count(MVT::iPTR), InP = In.count(MVT::iPTR);
- // Complement of In.
- auto CompIn = [&In](MVT T) -> bool { return !In.count(T); };
-
- if (OutP == InP)
- return berase_if(Out, CompIn);
-
- // Compute the intersection of scalars separately to account for only
- // one set containing iPTR.
- // The intersection of iPTR with a set of integer scalar types that does not
- // include iPTR will result in the most specific scalar type:
- // - iPTR is more specific than any set with two elements or more
- // - iPTR is less specific than any single integer scalar type.
- // For example
- // { iPTR } * { i32 } -> { i32 }
- // { iPTR } * { i32 i64 } -> { iPTR }
- // and
- // { iPTR i32 } * { i32 } -> { i32 }
- // { iPTR i32 } * { i32 i64 } -> { i32 i64 }
- // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 }
-
- // Let In' = elements only in In, Out' = elements only in Out, and
- // IO = elements common to both. Normally IO would be returned as the result
- // of the intersection, but we need to account for iPTR being a "wildcard" of
- // sorts. Since elements in IO are those that match both sets exactly, they
- // will all belong to the output. If any of the "leftovers" (i.e. In' or
- // Out') contain iPTR, it means that the other set doesn't have it, but it
- // could have (1) a more specific type, or (2) a set of types that is less
- // specific. The "leftovers" from the other set is what we want to examine
- // more closely.
-
- auto subtract = [](const SetType &A, const SetType &B) {
- SetType Diff = A;
- berase_if(Diff, [&B](MVT T) { return B.count(T); });
- return Diff;
- };
-
- if (InP) {
- SetType OutOnly = subtract(Out, In);
- if (OutOnly.empty()) {
- // This means that Out \subset In, so no change to Out.
- return false;
- }
- unsigned NumI = llvm::count_if(OutOnly, isScalarInteger);
- if (NumI == 1 && OutOnly.size() == 1) {
- // There is only one element in Out', and it happens to be a scalar
- // integer that should be kept as a match for iPTR in In.
- return false;
+ auto IntersectP = [&](std::optional<MVT> WildVT, function_ref<bool(MVT)> P) {
+ // Complement of In within this partition.
+ auto CompIn = [&](MVT T) -> bool { return !In.count(T) && P(T); };
+
+ if (!WildVT)
+ return berase_if(Out, CompIn);
+
+ bool OutW = Out.count(*WildVT), InW = In.count(*WildVT);
+ if (OutW == InW)
+ return berase_if(Out, CompIn);
+
+ // Compute the intersection of scalars separately to account for only one
+ // set containing WildVT.
+ // The intersection of WildVT with a set of corresponding types that does
+ // not include WildVT will result in the most specific type:
+ // - WildVT is more specific than any set with two elements or more
+ // - WildVT is less specific than any single type.
+ // For example, for iPTR and scalar integer types
+ // { iPTR } * { i32 } -> { i32 }
+ // { iPTR } * { i32 i64 } -> { iPTR }
+ // and
+ // { iPTR i32 } * { i32 } -> { i32 }
+ // { iPTR i32 } * { i32 i64 } -> { i32 i64 }
+ // { iPTR i32 } * { i32 i64 i128 } -> { iPTR i32 }
+
+ // Looking at just this partition, let In' = elements only in In,
+ // Out' = elements only in Out, and IO = elements common to both. Normally
+ // IO would be returned as the result of the intersection, but we need to
+ // account for WildVT being a "wildcard" of sorts. Since elements in IO are
+ // those that match both sets exactly, they will all belong to the output.
+ // If any of the "leftovers" (i.e. In' or Out') contain WildVT, it means
+ // that the other set doesn't have it, but it could have (1) a more
+ // specific type, or (2) a set of types that is less specific. The
+ // "leftovers" from the other set is what we want to examine more closely.
+
+ auto Leftovers = [&](const SetType &A, const SetType &B) {
+ SetType Diff = A;
+ berase_if(Diff, [&](MVT T) { return B.count(T) || !P(T); });
+ return Diff;
+ };
+
+ if (InW) {
+ SetType OutLeftovers = Leftovers(Out, In);
+ if (OutLeftovers.size() < 2) {
+ // WildVT not added to Out. Keep the possible single leftover.
+ return false;
+ }
+ // WildVT replaces the leftovers.
+ berase_if(Out, CompIn);
+ Out.insert(*WildVT);
+ return true;
}
- berase_if(Out, CompIn);
- if (NumI == 1) {
- // Replace the iPTR with the leftover scalar integer.
- Out.insert(*llvm::find_if(OutOnly, isScalarInteger));
- } else if (NumI > 1) {
- Out.insert(MVT::iPTR);
+
+ // OutW == true
+ SetType InLeftovers = Leftovers(In, Out);
+ unsigned SizeOut = Out.size();
+ berase_if(Out, CompIn); // This will remove at least the WildVT.
+ if (InLeftovers.size() < 2) {
+ // WildVT deleted from Out. Add back the possible single leftover.
+ Out.insert(InLeftovers);
+ return true;
}
- return true;
- }
- // OutP == true
- SetType InOnly = subtract(In, Out);
- unsigned SizeOut = Out.size();
- berase_if(Out, CompIn); // This will remove at least the iPTR.
- unsigned NumI = llvm::count_if(InOnly, isScalarInteger);
- if (NumI == 0) {
- // iPTR deleted from Out.
- return true;
- }
- if (NumI == 1) {
- // Replace the iPTR with the leftover scalar integer.
- Out.insert(*llvm::find_if(InOnly, isScalarInteger));
- return true;
- }
+ // Keep the WildVT in Out.
+ Out.insert(*WildVT);
+ // If WildVT was the only element initially removed from Out, then Out
+ // has not changed.
+ return SizeOut != Out.size();
+ };
- // NumI > 1: Keep the iPTR in Out.
- Out.insert(MVT::iPTR);
- // If iPTR was the only element initially removed from Out, then Out
- // has not changed.
- return SizeOut != Out.size();
+ // Note: must be non-overlapping
+ using WildPartT = std::pair<MVT, std::function<bool(MVT)>>;
+ static const WildPartT WildParts[] = {
+ {MVT::iPTR, [](MVT T) { return T.isScalarInteger() || T == MVT::iPTR; }},
+ };
+
+ bool Changed = false;
+ for (const auto &I : WildParts)
+ Changed |= IntersectP(I.first, I.second);
+
+ Changed |= IntersectP(std::nullopt, [&](MVT T) {
+ return !any_of(WildParts, [=](const WildPartT &I) { return I.second(T); });
+ });
+
+ return Changed;
}
bool TypeSetByHwMode::validate() const {