That's it, I am declaring this a failure of the C++03 STL.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 12 Mar 2011 01:50:35 +0000 (01:50 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Sat, 12 Mar 2011 01:50:35 +0000 (01:50 +0000)
There are too many compatibility problems with using mixed types in
std::upper_bound, and I don't want to spend 110 lines of boilerplate setting up
a call to a 10-line function. Binary search is not /that/ hard to implement
correctly.

I tried terminating the binary search with a linear search, but that actually
made the algorithm slower against my expectation. Most live intervals have less
than 4 segments. The early test against endIndex() does pay, and this version is
25% faster than plain std::upper_bound().

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127522 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/LiveInterval.cpp

index 1b446e69d3d12467d26ee846aea2a2fda62f814d..18ec9d5667293a349dc103aebd1ca509907d7ef6 100644 (file)
 #include <algorithm>
 using namespace llvm;
 
-// SlotIndexIterator - adapt an iterator over LiveRanges to look
-// like an iterator over SlotIndexes by accessing the .end member.
-namespace {
-struct SlotIndexIterator
-  : std::iterator<std::random_access_iterator_tag, SlotIndex> {
-
-  SlotIndexIterator() {
-  }
-
-  explicit SlotIndexIterator(LiveInterval::iterator it)
-    : it(it) {
-  }
-
-  SlotIndexIterator(const SlotIndexIterator & that)
-    : it(that.it) {
-  }
-
-  SlotIndexIterator & operator=(const SlotIndexIterator & that) {
-    it = that.it;
-    return *this;
-  }
-
-  SlotIndexIterator & operator++() {
-    ++it;
-    return *this;
-  }
-
-  SlotIndexIterator operator++(int) {
-    SlotIndexIterator that(*this);
-    ++*this;
-    return that;
-  }
-
-  SlotIndexIterator & operator--() {
-    --it;
-    return *this;
-  }
-
-  SlotIndexIterator operator--(int) {
-    SlotIndexIterator that(*this);
-    --*this;
-    return that;
-  }
-
-  SlotIndexIterator & operator+=(std::ptrdiff_t n) {
-    it += n;
-    return *this;
-  }
-
-  SlotIndexIterator & operator-=(std::ptrdiff_t n) {
-    it -= n;
-    return *this;
-  }
-
-  friend bool operator==(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it == rhs.it;
-  }
-
-  friend bool operator!=(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it != rhs.it;
-  }
-
-  friend bool operator<(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it < rhs.it;
-  }
-
-  friend bool operator<=(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it <= rhs.it;
-  }
-
-  friend bool operator>(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it > rhs.it;
-  }
-
-  friend bool operator>=(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it >= rhs.it;
-  }
-
-  friend SlotIndexIterator operator+(SlotIndexIterator that, std::ptrdiff_t n) {
-    return SlotIndexIterator(that.it + n);
-  }
-
-  friend SlotIndexIterator operator+(std::ptrdiff_t n, SlotIndexIterator that) {
-    return SlotIndexIterator(n + that.it);
-  }
-
-  friend SlotIndexIterator operator-(SlotIndexIterator that, std::ptrdiff_t n) {
-    return SlotIndexIterator(that.it - n);
-  }
-
-  friend std::ptrdiff_t operator-(SlotIndexIterator lhs, SlotIndexIterator rhs) {
-    return lhs.it - rhs.it;
-  }
-
-  reference operator*() const {
-    return it->end;
-  }
-
-  reference operator[](std::ptrdiff_t n) const {
-    return it[n].end;
-  }
-
-  pointer operator->() const {
-    return &it->end;
-  }
-
-  LiveInterval::iterator base() const {
-    return it;
-  }
-
-private:
-  LiveInterval::iterator it;
-};
-}
-
 LiveInterval::iterator LiveInterval::find(SlotIndex Pos) {
-  assert(Pos.isValid() && "Cannot search for an invalid index");
-  return std::upper_bound(
-    SlotIndexIterator(begin()),
-    SlotIndexIterator(end()), Pos).base();
+  // This algorithm is basically std::upper_bound.
+  // Unfortunately, std::upper_bound cannot be used with mixed types until we
+  // adopt C++0x. Many libraries can do it, but not all.
+  if (empty() || Pos >= endIndex())
+    return end();
+  iterator I = begin();
+  size_t Len = ranges.size();
+  do {
+    size_t Mid = Len >> 1;
+    if (Pos < I[Mid].end)
+      Len = Mid;
+    else
+      I += Mid + 1, Len -= Mid + 1;
+  } while (Len);
+  return I;
 }
 
 /// killedInRange - Return true if the interval has kills in [Start,End).