[compiler-rt] bbb73fb - [ORC-RT] Reapply ab59185fbfb (Add IntervalMap/Set), with missing files included.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 17 13:48:36 PST 2023


Author: Lang Hames
Date: 2023-01-17T13:47:47-08:00
New Revision: bbb73fbceb1b35cc9c3ab0c53e4e6128437f2b34

URL: https://github.com/llvm/llvm-project/commit/bbb73fbceb1b35cc9c3ab0c53e4e6128437f2b34
DIFF: https://github.com/llvm/llvm-project/commit/bbb73fbceb1b35cc9c3ab0c53e4e6128437f2b34.diff

LOG: [ORC-RT] Reapply ab59185fbfb (Add IntervalMap/Set), with missing files included.

The original commit was reverted in c151e8428a due missing files (thanks Kazu!).

Added: 
    compiler-rt/lib/orc/interval_map.h
    compiler-rt/lib/orc/interval_set.h
    compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
    compiler-rt/lib/orc/tests/unit/interval_set_test.cpp

Modified: 
    compiler-rt/lib/orc/macho_platform.cpp
    compiler-rt/lib/orc/tests/unit/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/interval_map.h b/compiler-rt/lib/orc/interval_map.h
new file mode 100644
index 000000000000..16f22c63298b
--- /dev/null
+++ b/compiler-rt/lib/orc/interval_map.h
@@ -0,0 +1,153 @@
+//===--------- interval_map.h - A sorted interval map -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a coalescing interval map.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ORC_RT_INTERVAL_MAP_H
+#define ORC_RT_INTERVAL_MAP_H
+
+#include "adt.h"
+#include <cassert>
+#include <map>
+
+namespace __orc_rt {
+
+enum class IntervalCoalescing { Enabled, Disabled };
+
+/// Maps intervals to keys with optional coalescing.
+///
+/// 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 {
+private:
+  using KeyPairT = std::pair<KeyT, KeyT>;
+
+  struct Compare {
+    using is_transparent = std::true_type;
+    bool operator()(const KeyPairT &LHS, const KeyPairT &RHS) const {
+      return LHS < RHS;
+    }
+    bool operator()(const KeyPairT &LHS, const KeyT &RHS) const {
+      return LHS.first < RHS;
+    }
+    bool operator()(const KeyT &LHS, const KeyPairT &RHS) const {
+      return LHS < RHS.first;
+    }
+  };
+
+  using ImplMap = std::map<KeyPairT, ValT, Compare>;
+
+public:
+  using iterator = typename ImplMap::iterator;
+  using const_iterator = typename ImplMap::const_iterator;
+  using size_type = typename ImplMap::size_type;
+
+  bool empty() const { return Impl.empty(); }
+
+  void clear() { Impl.clear(); }
+
+  iterator begin() { return Impl.begin(); }
+  iterator end() { return Impl.end(); }
+
+  const_iterator begin() const { return Impl.begin(); }
+  const_iterator end() const { return Impl.end(); }
+
+  iterator find(KeyT K) {
+    // Early out if the key is clearly outside the range.
+    if (empty() || K < begin()->first.first ||
+        K >= std::prev(end())->first.second)
+      return end();
+
+    auto I = Impl.upper_bound(K);
+    assert(I != begin() && "Should have hit early out above");
+    I = std::prev(I);
+    if (K < I->first.second)
+      return I;
+    return end();
+  }
+
+  const_iterator find(KeyT K) const {
+    return const_cast<IntervalMap<KeyT, ValT, Coalescing> *>(this)->find(K);
+  }
+
+  ValT lookup(KeyT K, ValT NotFound = ValT()) const {
+    auto I = find(K);
+    if (I == end())
+      return NotFound;
+    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) {
+    if (empty())
+      return;
+
+    auto J = Impl.upper_bound(KS);
+
+    // Check previous range. Bail out if range to remove is entirely after
+    // it.
+    auto I = std::prev(J);
+    if (KS >= I->first.second)
+      return;
+
+    // Assert that range is wholly contained.
+    assert(KE <= I->first.second);
+
+    auto Tmp = std::move(*I);
+    Impl.erase(I);
+
+    // Split-right -- introduce right-split range.
+    if (KE < Tmp.first.second) {
+      Impl.insert(
+          J, std::make_pair(std::make_pair(KE, Tmp.first.second), Tmp.second));
+      J = std::prev(J);
+    }
+
+    // Split-left -- introduce left-split range.
+    if (KS > Tmp.first.first)
+      Impl.insert(
+          J, std::make_pair(std::make_pair(Tmp.first.first, KS), Tmp.second));
+  }
+
+private:
+  ImplMap Impl;
+};
+
+} // End namespace __orc_rt
+
+#endif // ORC_RT_INTERVAL_MAP_H

diff  --git a/compiler-rt/lib/orc/interval_set.h b/compiler-rt/lib/orc/interval_set.h
new file mode 100644
index 000000000000..20f40f9c7d37
--- /dev/null
+++ b/compiler-rt/lib/orc/interval_set.h
@@ -0,0 +1,87 @@
+//===--------- interval_set.h - A sorted interval set -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implements a coalescing interval set.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ORC_RT_INTERVAL_SET_H
+#define ORC_RT_INTERVAL_SET_H
+
+#include "interval_map.h"
+
+namespace __orc_rt {
+
+/// Implements a coalescing interval set.
+///
+/// Adjacent intervals are coalesced.
+///
+/// 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, IntervalCoalescing Coalescing>
+class IntervalSet {
+private:
+  using ImplMap = IntervalMap<KeyT, std::monostate, Coalescing>;
+public:
+
+  using value_type = std::pair<KeyT, KeyT>;
+
+  class const_iterator {
+    friend class IntervalSet;
+  public:
+    using 
diff erence_type = typename ImplMap::iterator::
diff erence_type;
+    using value_type = IntervalSet::value_type;
+    using pointer = const value_type *;
+    using reference = const value_type &;
+    using iterator_category = std::input_iterator_tag;
+
+    const_iterator() = default;
+    const value_type &operator*() const { return I->first; }
+    const value_type *operator->() const { return &I->first; }
+    const_iterator &operator++() { ++I; return *this; }
+    const_iterator operator++(int) { auto Tmp = I; ++I; return Tmp; }
+    friend bool operator==(const const_iterator &LHS,
+                           const const_iterator &RHS) {
+      return LHS.I == RHS.I;
+    }
+    friend bool operator!=(const const_iterator &LHS,
+                           const const_iterator &RHS) {
+      return LHS.I != RHS.I;
+    }
+  private:
+    const_iterator(typename ImplMap::const_iterator I) : I(std::move(I)) {}
+    typename ImplMap::const_iterator I;
+  };
+
+  bool empty() const { return Map.empty(); }
+
+  void clear() { Map.clear(); }
+
+  const_iterator begin() const { return const_iterator(Map.begin()); }
+  const_iterator end() const { return const_iterator(Map.end()); }
+
+  const_iterator find(KeyT K) const {
+    return const_iterator(Map.find(K));
+  }
+
+  void insert(KeyT KS, KeyT KE) {
+    Map.insert(std::move(KS), std::move(KE), std::monostate());
+  }
+
+  void erase(KeyT KS, KeyT KE) {
+    Map.erase(KS, KE);
+  }
+
+private:
+  ImplMap Map;
+};
+
+} // End namespace __orc_rt
+
+#endif // ORC_RT_INTERVAL_SET_H

diff  --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 7d611e1477bd..5a5c8e49e0b1 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -14,6 +14,7 @@
 #include "common.h"
 #include "debug.h"
 #include "error.h"
+#include "interval_map.h"
 #include "wrapper_function_utils.h"
 
 #include <algorithm>

diff  --git a/compiler-rt/lib/orc/tests/unit/CMakeLists.txt b/compiler-rt/lib/orc/tests/unit/CMakeLists.txt
index e8cd2f9fef87..7792d21bfa7c 100644
--- a/compiler-rt/lib/orc/tests/unit/CMakeLists.txt
+++ b/compiler-rt/lib/orc/tests/unit/CMakeLists.txt
@@ -5,6 +5,8 @@ set(UNITTEST_SOURCES
   error_test.cpp
   executor_address_test.cpp
   extensible_rtti_test.cpp
+  interval_map_test.cpp
+  interval_set_test.cpp
   orc_unit_test_main.cpp
   wrapper_function_utils_test.cpp
   simple_packed_serialization_test.cpp

diff  --git a/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp b/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
new file mode 100644
index 000000000000..6f6474b81bca
--- /dev/null
+++ b/compiler-rt/lib/orc/tests/unit/interval_map_test.cpp
@@ -0,0 +1,188 @@
+//===-- interval_map_test.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of the ORC runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interval_map.h"
+#include "gtest/gtest.h"
+
+using namespace __orc_rt;
+
+TEST(IntervalMapTest, DefaultConstructed) {
+  // Check that a default-constructed IntervalMap behaves as expected.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  EXPECT_TRUE(M.empty());
+  EXPECT_TRUE(M.begin() == M.end());
+  EXPECT_TRUE(M.find(0) == M.end());
+}
+
+TEST(IntervalMapTest, InsertSingleElement) {
+  // Check that a map with a single element inserted behaves as expected.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  M.insert(7, 8, 42);
+
+  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());
+  EXPECT_EQ(M.lookup(7), 42U);
+  EXPECT_EQ(M.lookup(8), 0U); // 8 not present, so should return unsigned().
+}
+
+TEST(IntervalMapTest, InsertCoalesceWithPrevious) {
+  // Check that insertions coalesce with previous ranges that share the same
+  // value. Also check that they _don't_ coalesce if the values are 
diff erent.
+
+  // Check that insertion coalesces with previous range when values are equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M1;
+
+  M1.insert(7, 8, 42);
+  M1.insert(8, 9, 42);
+
+  EXPECT_FALSE(M1.empty());
+  EXPECT_EQ(std::next(M1.begin()), M1.end()); // Should see just one range.
+  EXPECT_EQ(M1.find(7), M1.find(8)); // 7 and 8 should point to same range.
+  EXPECT_EQ(M1.lookup(7), 42U);      // Value should be preserved.
+
+  // Check that insertion does not coalesce with previous range when values are
+  // not equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M2;
+
+  M2.insert(7, 8, 42);
+  M2.insert(8, 9, 7);
+
+  EXPECT_FALSE(M2.empty());
+  EXPECT_EQ(std::next(std::next(M2.begin())), M2.end()); // Expect two ranges.
+  EXPECT_NE(M2.find(7), M2.find(8)); // 7 and 8 should be 
diff erent ranges.
+  EXPECT_EQ(M2.lookup(7), 42U); // Keys 7 and 8 should map to 
diff erent values.
+  EXPECT_EQ(M2.lookup(8), 7U);
+}
+
+TEST(IntervalMapTest, InsertCoalesceWithFollowing) {
+  // Check that insertions coalesce with following ranges that share the same
+  // value. Also check that they _don't_ coalesce if the values are 
diff erent.
+
+  // Check that insertion coalesces with following range when values are equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M1;
+
+  M1.insert(8, 9, 42);
+  M1.insert(7, 8, 42);
+
+  EXPECT_FALSE(M1.empty());
+  EXPECT_EQ(std::next(M1.begin()), M1.end()); // Should see just one range.
+  EXPECT_EQ(M1.find(7), M1.find(8)); // 7 and 8 should point to same range.
+  EXPECT_EQ(M1.lookup(7), 42U);      // Value should be preserved.
+
+  // Check that insertion does not coalesce with previous range when values are
+  // not equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M2;
+
+  M2.insert(8, 9, 42);
+  M2.insert(7, 8, 7);
+
+  EXPECT_FALSE(M2.empty());
+  EXPECT_EQ(std::next(std::next(M2.begin())), M2.end()); // Expect two ranges.
+  EXPECT_EQ(M2.lookup(7), 7U); // Keys 7 and 8 should map to 
diff erent values.
+  EXPECT_EQ(M2.lookup(8), 42U);
+}
+
+TEST(IntervalMapTest, InsertCoalesceBoth) {
+  // Check that insertions coalesce with ranges on both sides where posssible.
+  // Also check that they _don't_ coalesce if the values are 
diff erent.
+
+  // Check that insertion coalesces with both previous and following ranges
+  // when values are equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M1;
+
+  M1.insert(7, 8, 42);
+  M1.insert(9, 10, 42);
+
+  // Check no coalescing yet.
+  EXPECT_NE(M1.find(7), M1.find(9));
+
+  // Insert a 3rd range to trigger coalescing on both sides.
+  M1.insert(8, 9, 42);
+
+  EXPECT_FALSE(M1.empty());
+  EXPECT_EQ(std::next(M1.begin()), M1.end()); // Should see just one range.
+  EXPECT_EQ(M1.find(7), M1.find(8)); // 7, 8, and 9 should point to same range.
+  EXPECT_EQ(M1.find(8), M1.find(9));
+  EXPECT_EQ(M1.lookup(7), 42U); // Value should be preserved.
+
+  // Check that insertion does not coalesce with previous range when values are
+  // not equal.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M2;
+
+  M2.insert(7, 8, 42);
+  M2.insert(8, 9, 7);
+  M2.insert(9, 10, 42);
+
+  EXPECT_FALSE(M2.empty());
+  // Expect three ranges.
+  EXPECT_EQ(std::next(std::next(std::next(M2.begin()))), M2.end());
+  EXPECT_NE(M2.find(7), M2.find(8)); // All keys should map to 
diff erent ranges.
+  EXPECT_NE(M2.find(8), M2.find(9));
+  EXPECT_EQ(M2.lookup(7), 42U); // Key 7, 8, and 9 should map to 
diff erent vals.
+  EXPECT_EQ(M2.lookup(8), 7U);
+  EXPECT_EQ(M2.lookup(9), 42U);
+}
+
+TEST(IntervalMapTest, EraseSingleElement) {
+  // Check that we can insert and then remove a single range.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  M.insert(7, 10, 42);
+  EXPECT_FALSE(M.empty());
+  M.erase(7, 10);
+  EXPECT_TRUE(M.empty());
+}
+
+TEST(IntervalMapTest, EraseSplittingLeft) {
+  // Check that removal of a trailing subrange succeeds, but leaves the
+  // residual range in-place.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  M.insert(7, 10, 42);
+  EXPECT_FALSE(M.empty());
+  M.erase(9, 10);
+  EXPECT_EQ(std::next(M.begin()), M.end());
+  EXPECT_EQ(M.begin()->first.first, 7U);
+  EXPECT_EQ(M.begin()->first.second, 9U);
+}
+
+TEST(IntervalMapTest, EraseSplittingRight) {
+  // Check that removal of a leading subrange succeeds, but leaves the
+  // residual range in-place.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  M.insert(7, 10, 42);
+  EXPECT_FALSE(M.empty());
+  M.erase(7, 8);
+  EXPECT_EQ(std::next(M.begin()), M.end());
+  EXPECT_EQ(M.begin()->first.first, 8U);
+  EXPECT_EQ(M.begin()->first.second, 10U);
+}
+
+TEST(IntervalMapTest, EraseSplittingBoth) {
+  // Check that removal of an interior subrange leaves both the leading and
+  // trailing residual subranges in-place.
+  IntervalMap<unsigned, unsigned, IntervalCoalescing::Enabled> M;
+
+  M.insert(7, 10, 42);
+  EXPECT_FALSE(M.empty());
+  M.erase(8, 9);
+  EXPECT_EQ(std::next(std::next(M.begin())), M.end());
+  EXPECT_EQ(M.begin()->first.first, 7U);
+  EXPECT_EQ(M.begin()->first.second, 8U);
+  EXPECT_EQ(std::next(M.begin())->first.first, 9U);
+  EXPECT_EQ(std::next(M.begin())->first.second, 10U);
+}

diff  --git a/compiler-rt/lib/orc/tests/unit/interval_set_test.cpp b/compiler-rt/lib/orc/tests/unit/interval_set_test.cpp
new file mode 100644
index 000000000000..7971a55f271f
--- /dev/null
+++ b/compiler-rt/lib/orc/tests/unit/interval_set_test.cpp
@@ -0,0 +1,121 @@
+//===-- interval_set_test.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of the ORC runtime.
+//
+//===----------------------------------------------------------------------===//
+
+#include "interval_set.h"
+#include "gtest/gtest.h"
+
+using namespace __orc_rt;
+
+TEST(IntervalSetTest, DefaultConstructed) {
+  // Check that a default-constructed IntervalSet behaves as expected.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  EXPECT_TRUE(S.empty());
+  EXPECT_TRUE(S.begin() == S.end());
+  EXPECT_TRUE(S.find(0) == S.end());
+}
+
+TEST(IntervalSetTest, InsertSingleElement) {
+  // Check that a set with a single element inserted behaves as expected.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 8);
+
+  EXPECT_FALSE(S.empty());
+  EXPECT_EQ(std::next(S.begin()), S.end());
+  EXPECT_EQ(S.find(7), S.begin());
+  EXPECT_EQ(S.find(8), S.end());
+}
+
+TEST(IntervalSetTest, InsertCoalesceWithPrevious) {
+  // Check that insertions coalesce with previous ranges.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 8);
+  S.insert(8, 9);
+
+  EXPECT_FALSE(S.empty());
+  EXPECT_EQ(std::next(S.begin()), S.end()); // Should see just one range.
+  EXPECT_EQ(S.find(7), S.find(8)); // 7 and 8 should point to same range.
+}
+
+TEST(IntervalSetTest, InsertCoalesceWithFollowing) {
+  // Check that insertions coalesce with following ranges.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(8, 9);
+  S.insert(7, 8);
+
+  EXPECT_FALSE(S.empty());
+  EXPECT_EQ(std::next(S.begin()), S.end()); // Should see just one range.
+  EXPECT_EQ(S.find(7), S.find(8)); // 7 and 8 should point to same range.
+}
+
+TEST(IntervalSetTest, InsertCoalesceBoth) {
+  // Check that insertions coalesce with ranges on both sides.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 8);
+  S.insert(9, 10);
+
+  // Check no coalescing yet.
+  EXPECT_NE(S.find(7), S.find(9));
+
+  // Insert a 3rd range to trigger coalescing on both sides.
+  S.insert(8, 9);
+
+  EXPECT_FALSE(S.empty());
+  EXPECT_EQ(std::next(S.begin()), S.end()); // Should see just one range.
+  EXPECT_EQ(S.find(7), S.find(8)); // 7, 8, and 9 should point to same range.
+  EXPECT_EQ(S.find(8), S.find(9));
+}
+
+TEST(IntervalSetTest, EraseSplittingLeft) {
+  // Check that removal of a trailing subrange succeeds, but leaves the
+  // residual range in-place.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 10);
+  EXPECT_FALSE(S.empty());
+  S.erase(9, 10);
+  EXPECT_EQ(std::next(S.begin()), S.end());
+  EXPECT_EQ(S.begin()->first, 7U);
+  EXPECT_EQ(S.begin()->second, 9U);
+}
+
+TEST(IntervalSetTest, EraseSplittingRight) {
+  // Check that removal of a leading subrange succeeds, but leaves the
+  // residual range in-place.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 10);
+  EXPECT_FALSE(S.empty());
+  S.erase(7, 8);
+  EXPECT_EQ(std::next(S.begin()), S.end());
+  EXPECT_EQ(S.begin()->first, 8U);
+  EXPECT_EQ(S.begin()->second, 10U);
+}
+
+TEST(IntervalSetTest, EraseSplittingBoth) {
+  // Check that removal of an interior subrange leaves both the leading and
+  // trailing residual subranges in-place.
+  IntervalSet<unsigned, IntervalCoalescing::Enabled> S;
+
+  S.insert(7, 10);
+  EXPECT_FALSE(S.empty());
+  S.erase(8, 9);
+  EXPECT_EQ(std::next(std::next(S.begin())), S.end());
+  EXPECT_EQ(S.begin()->first, 7U);
+  EXPECT_EQ(S.begin()->second, 8U);
+  EXPECT_EQ(std::next(S.begin())->first, 9U);
+  EXPECT_EQ(std::next(S.begin())->second, 10U);
+}


        


More information about the llvm-commits mailing list