[compiler-rt] ad4b66f - [ORC-RT] Specialize non-coalescing-IntervalMap to allow non-comparable values.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 18 17:39:52 PST 2023
Author: Lang Hames
Date: 2023-01-18T17:39:45-08:00
New Revision: ad4b66fd9b3ef3f78e3f594b32b0ca952453ea68
URL: https://github.com/llvm/llvm-project/commit/ad4b66fd9b3ef3f78e3f594b32b0ca952453ea68
DIFF: https://github.com/llvm/llvm-project/commit/ad4b66fd9b3ef3f78e3f594b32b0ca952453ea68.diff
LOG: [ORC-RT] Specialize non-coalescing-IntervalMap to allow non-comparable values.
In non-coalescing IntervalMaps the value type should not be requried to be
equality-comparable.
Added:
Modified:
compiler-rt/lib/orc/interval_map.h
compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/orc/interval_map.h b/compiler-rt/lib/orc/interval_map.h
index 16f22c63298b0..8c1609d72f57f 100644
--- a/compiler-rt/lib/orc/interval_map.h
+++ b/compiler-rt/lib/orc/interval_map.h
@@ -26,8 +26,7 @@ enum class IntervalCoalescing { Enabled, Disabled };
/// NOTE: The interface is kept mostly compatible with LLVM's IntervalMap
/// collection to make it easy to swap over in the future if we choose
/// to.
-template <typename KeyT, typename ValT, IntervalCoalescing Coalescing>
-class IntervalMap {
+template <typename KeyT, typename ValT> class IntervalMapBase {
private:
using KeyPairT = std::pair<KeyT, KeyT>;
@@ -76,7 +75,7 @@ class IntervalMap {
}
const_iterator find(KeyT K) const {
- return const_cast<IntervalMap<KeyT, ValT, Coalescing> *>(this)->find(K);
+ return const_cast<IntervalMapBase<KeyT, ValT> *>(this)->find(K);
}
ValT lookup(KeyT K, ValT NotFound = ValT()) const {
@@ -86,31 +85,6 @@ class IntervalMap {
return I->second;
}
- void insert(KeyT KS, KeyT KE, ValT V) {
- if (Coalescing == IntervalCoalescing::Enabled) {
- auto J = Impl.upper_bound(KS);
-
- // Coalesce-right if possible. Either way, J points at our insertion
- // point.
- if (J != end() && KE == J->first.first && J->second == V) {
- KE = J->first.second;
- auto Tmp = J++;
- Impl.erase(Tmp);
- }
-
- // Coalesce-left if possible.
- if (J != begin()) {
- auto I = std::prev(J);
- if (I->first.second == KS && I->second == V) {
- KS = I->first.first;
- Impl.erase(I);
- }
- }
- Impl.insert(J, std::make_pair(std::make_pair(KS, KE), std::move(V)));
- } else
- Impl.insert(std::make_pair(std::make_pair(KS, KE), std::move(V)));
- }
-
// Erase [KS, KE), which must be entirely containing within one existing
// range in the map. Removal is allowed to split the range.
void erase(KeyT KS, KeyT KE) {
@@ -144,10 +118,51 @@ class IntervalMap {
J, std::make_pair(std::make_pair(Tmp.first.first, KS), Tmp.second));
}
-private:
+protected:
ImplMap Impl;
};
+template <typename KeyT, typename ValT, IntervalCoalescing Coalescing>
+class IntervalMap;
+
+template <typename KeyT, typename ValT>
+class IntervalMap<KeyT, ValT, IntervalCoalescing::Enabled>
+ : public IntervalMapBase<KeyT, ValT> {
+public:
+ // Coalescing insert. Requires that ValTs be equality-comparable.
+ void insert(KeyT KS, KeyT KE, ValT V) {
+ auto J = this->Impl.upper_bound(KS);
+
+ // Coalesce-right if possible. Either way, J points at our insertion
+ // point.
+ if (J != this->end() && KE == J->first.first && J->second == V) {
+ KE = J->first.second;
+ auto Tmp = J++;
+ this->Impl.erase(Tmp);
+ }
+
+ // Coalesce-left if possible.
+ if (J != this->begin()) {
+ auto I = std::prev(J);
+ if (I->first.second == KS && I->second == V) {
+ KS = I->first.first;
+ this->Impl.erase(I);
+ }
+ }
+ this->Impl.insert(J, std::make_pair(std::make_pair(KS, KE), std::move(V)));
+ }
+};
+
+template <typename KeyT, typename ValT>
+class IntervalMap<KeyT, ValT, IntervalCoalescing::Disabled>
+ : public IntervalMapBase<KeyT, ValT> {
+public:
+ // Non-coalescing insert. Does not require ValT to be equality-comparable.
+ void insert(KeyT KS, KeyT KE, ValT V) {
+ this->Impl.insert(std::make_pair(std::make_pair(KS, KE), std::move(V)));
+ }
+};
+
} // End namespace __orc_rt
#endif // ORC_RT_INTERVAL_MAP_H
diff --git a/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp b/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
index 6f6474b81bca0..a1c6958fcd526 100644
--- a/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
+++ b/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
@@ -186,3 +186,19 @@ TEST(IntervalMapTest, EraseSplittingBoth) {
EXPECT_EQ(std::next(M.begin())->first.first, 9U);
EXPECT_EQ(std::next(M.begin())->first.second, 10U);
}
+
+TEST(IntervalMapTest, NonCoalescingMapPermitsNonComparableKeys) {
+ // Test that values that can't be equality-compared are still usable when
+ // coalescing is disabled and behave as expected.
+
+ struct S {}; // Struct with no equality comparison.
+
+ IntervalMap<unsigned, S, IntervalCoalescing::Disabled> M;
+
+ M.insert(7, 8, S());
+
+ EXPECT_FALSE(M.empty());
+ EXPECT_EQ(std::next(M.begin()), M.end());
+ EXPECT_EQ(M.find(7), M.begin());
+ EXPECT_EQ(M.find(8), M.end());
+}
More information about the llvm-commits
mailing list