[llvm-commits] [dragonegg] r128420 - in /dragonegg/trunk: ADT/ ADT/IntervalList.h ADT/Range.h Makefile

Duncan Sands baldrick at free.fr
Mon Mar 28 12:44:58 PDT 2011


Author: baldrick
Date: Mon Mar 28 14:44:58 2011
New Revision: 128420

URL: http://llvm.org/viewvc/llvm-project?rev=128420&view=rev
Log:
Add some utility classes for manipulating bit ranges.

Added:
    dragonegg/trunk/ADT/
    dragonegg/trunk/ADT/IntervalList.h
    dragonegg/trunk/ADT/Range.h
Modified:
    dragonegg/trunk/Makefile

Added: dragonegg/trunk/ADT/IntervalList.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/ADT/IntervalList.h?rev=128420&view=auto
==============================================================================
--- dragonegg/trunk/ADT/IntervalList.h (added)
+++ dragonegg/trunk/ADT/IntervalList.h Mon Mar 28 14:44:58 2011
@@ -0,0 +1,215 @@
+//=--------- IntervalList.h - List of disjoint intervals ----------*- C++ -*-=//
+//
+// Copyright (C) 2011  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This file declares a utility class for maintaining a collection of pairwise
+// disjoint intervals.
+//===----------------------------------------------------------------------===//
+
+#ifndef DRAGONEGG_INTERVALLIST_H
+#define DRAGONEGG_INTERVALLIST_H
+
+#include "Range.h"
+#include "llvm/ADT/SmallVector.h"
+
+/// IntervalList - Maintains a list of disjoint intervals.  Type 'T' represents
+/// an interval, and should have a getRange method which returns a range of 'U'
+/// values.  In addition it should provide ChangeRangeTo for growing, shrinking
+/// and otherwise changing the shape of the interval; and JoinWith for replacing
+/// the interval with the convex hull of its union with another interval (which
+/// is guaranteed to be disjoint from the original).
+template <class T, typename U, unsigned N>
+class IntervalList {
+  typedef typename llvm::SmallVector<T, N> List;
+  typedef typename List::iterator iterator;
+
+  List Intervals;
+  // The actual intervals.  Always disjoint, sorted and non-empty.
+
+  /// CmpFirst - Compare intervals based on where they start.
+  static bool CmpFirst(const T &L, const T &R) {
+    return L.getRange().getFirst() < R.getRange().getFirst();
+  }
+
+  /// CmpLast - Compare intervals based on where they stop.
+  static bool CmpLast(const T &L, const T &R) {
+    return L.getRange().getLast() < R.getRange().getLast();
+  }
+
+  /// isSane - Return true if the intervals are non-empty, disjoint and
+  /// sorted.
+  bool isSane() const {
+    for (unsigned i = 0, e = Intervals.size(); i < e; ++i) {
+      if (Intervals[i].getRange().empty())
+        return false;
+      if (i && Intervals[i].getRange().getFirst() <
+          Intervals[i-1].getRange().getLast())
+        return false;
+    }
+    return true;
+  }
+
+public:
+
+  /// AddInterval - Add the given interval to the list.  If it overlaps any
+  /// existing intervals then the existing intervals are pruned by removing
+  /// exactly the parts of them that overlap the new interval.  If the added
+  /// interval is empty then it will be discarded.
+  void AddInterval(const T &S);
+
+  /// getNumIntervals - Return the number of intervals in the list.
+  unsigned getNumIntervals() const {
+    return Intervals.size();
+  }
+
+  /// getInterval - Return the interval with the given index.
+  T getInterval(unsigned Idx) {
+    return Intervals[Idx];
+  }
+
+  /// AlignBoundaries - Ensure that all intervals begin and end on a multiple of
+  /// the given value.
+  void AlignBoundaries(unsigned Alignment);
+};
+
+/// AddInterval - Add the given interval to the list.  If it overlaps any
+/// existing intervals then the existing intervals are pruned by removing
+/// exactly the parts of them that overlap the new interval.  If the added
+/// interval is empty then it will be discarded.
+template <class T, typename U, unsigned N>
+void IntervalList<T, U, N>::AddInterval(const T &Interval) {
+  const Range<U> NewRange = Interval.getRange();
+
+  // If the new interval is empty then there is no point in adding it.
+  if (NewRange.empty())
+    return;
+
+  // If this is the first interval then it cannot overlap any others.
+  if (Intervals.empty()) {
+    Intervals.push_back(Interval);
+    return;
+  }
+
+  // Check for overlap with existing intervals.
+  iterator Lo = std::lower_bound(Intervals.begin(), Intervals.end(), Interval,
+                                 CmpFirst);
+  iterator Hi = std::upper_bound(Intervals.begin(), Intervals.end(), Interval,
+                                 CmpLast);
+  if (Lo < Hi) {
+    // Intervals with index in [Lo, Hi) are those completely covered by the new
+    // interval.  Throw them away.
+    for (iterator I = Lo; I != Hi; ++I)
+      assert(NewRange.contains(I->getRange()) && "Old interval not covered!");
+    Intervals.erase(Lo, Hi);
+    Hi = Lo;
+  } else if (Hi < Lo) {
+    // The new interval is contained in Hi with an excedent at each end.  Chop
+    // the old interval into two pieces (the lower and upper parts) and insert
+    // the new interval between them.
+    const Range<U> OldRange = Hi->getRange();
+    assert(OldRange.contains(NewRange) && "New interval not contained in old!");
+    const Range<U> LowerRange(OldRange.getFirst(), NewRange.getFirst());
+    const Range<U> UpperRange(NewRange.getLast(), OldRange.getLast());
+    assert(!LowerRange.empty() && !UpperRange.empty() && "Degenerate end!");
+    T UpperPart = *Hi;
+    Hi->ChangeRangeTo(LowerRange);
+    UpperPart.ChangeRangeTo(UpperRange);
+    Lo = Intervals.insert(Lo, UpperPart);
+    Intervals.insert(Lo, Interval);
+    assert(isSane() && "Interval added wrong!");
+    return;
+  }
+  assert(Lo == Hi);
+  // Check for overlap with the preceding interval.
+  if (Lo != Intervals.begin()) {
+    const iterator Prev = Lo - 1;
+    const Range<U> PrevRange = Prev->getRange();
+    if (NewRange.getFirst() < PrevRange.getLast())
+      // Shrink the previous interval to remove the overlap.
+      Prev->ChangeRangeTo(Range<U>(PrevRange.getFirst(), NewRange.getFirst()));
+  }
+  // Check for overlap with the following interval.
+  if (Lo != Intervals.end()) {
+    const iterator Next = Lo;
+    const Range<U> NextRange = Next->getRange();
+    if (NextRange.getFirst() < NewRange.getLast())
+      // Shrink the next interval to remove the overlap.
+      Next->ChangeRangeTo(Range<U>(NewRange.getLast(), NextRange.getLast()));
+  }
+  // The new interval is now disjoint from any existing intervals.  Insert it.
+  Intervals.insert(Lo, Interval);
+  assert(isSane() && "Interval added wrong!");
+}
+
+/// AlignBoundaries - Ensure that all intervals begin and end on a multiple of
+/// the given value.
+template <class T, typename U, unsigned N>
+void IntervalList<T, U, N>::AlignBoundaries(unsigned Alignment) {
+  assert(Alignment > 0 && "Alignment should be positive!");
+  for (iterator SI = Intervals.begin(); SI != Intervals.end(); ++SI) {
+    T &Interval = *SI;
+    Range<U> OrigRange = Interval.getRange();
+
+    // Round the start of the interval down and the end of the interval up to
+    // the nearest multiple of the alignment.
+    U RoundedFirst = OrigRange.getFirst() - (OrigRange.getFirst() % Alignment);
+    U RoundedLast = OrigRange.getLast() + Alignment - 1;
+    RoundedLast -= RoundedLast % Alignment;
+    Range<U> AlignedRange(RoundedFirst, RoundedLast);
+
+    // There is nothing to do if the interval is already aligned.
+    if (OrigRange == AlignedRange)
+      continue;
+
+    // Merge in all following intervals that start before RoundedLast.
+    iterator Next = SI + 1;
+    for (; Next != Intervals.end() && Next->getRange().getFirst() < RoundedLast;
+         ++Next)
+      Interval.JoinWith(*Next);
+    assert(Interval.getRange().getFirst() == OrigRange.getFirst() &&
+           "Merging at end changed start!");
+
+    // If merging caused the interval to extend beyond RoundedLast then chop the
+    // interval in two at RoundedLast.  This stops intervals getting huge due to
+    // repeated merging.
+    if (Interval.getRange().getLast() > RoundedLast) {
+      Range<U> LowerR(OrigRange.getFirst(), RoundedLast);
+      Range<U> UpperR(RoundedLast, Interval.getRange().getLast());
+      // We must have merged in at least the next interval.  Reuse it to hold
+      // the part we chop off the end.
+      T &J = *(SI + 1) = Interval;
+      // Chop the end off the original interval so that it stops at RoundedLast
+      // and at the same time extend the start of the original interval down to
+      // the alignment boundary.
+      Interval.ChangeRangeTo(AlignedRange);
+      // Chop the start off the new (following) interval so that it begins at
+      // RoundedLast.
+      J.ChangeRangeTo(UpperR);
+      // Delete any other merged intervals.
+      Intervals.erase(SI + 2, Next);
+    } else {
+      // The interval didn't grow beyond the original alignment boundary.  Round
+      // it to those boundaries.
+      Interval.ChangeRangeTo(AlignedRange);
+      // Delete any merged intervals.
+      Intervals.erase(SI + 1, Next);
+    }
+  }
+}
+
+#endif /* DRAGONEGG_INTERVALLIST_H */

Added: dragonegg/trunk/ADT/Range.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/ADT/Range.h?rev=128420&view=auto
==============================================================================
--- dragonegg/trunk/ADT/Range.h (added)
+++ dragonegg/trunk/ADT/Range.h Mon Mar 28 14:44:58 2011
@@ -0,0 +1,106 @@
+//=------------------ Range.h - Interval of values ----------------*- C++ -*-=//
+//
+// Copyright (C) 2011  Duncan Sands.
+//
+// This file is part of DragonEgg.
+//
+// DragonEgg is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later version.
+//
+// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// DragonEgg; see the file COPYING.  If not, write to the Free Software
+// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
+//
+//===----------------------------------------------------------------------===//
+// This file declares a utility class for representing an interval of values.
+//===----------------------------------------------------------------------===//
+
+#ifndef DRAGONEGG_RANGE_H
+#define DRAGONEGG_RANGE_H
+
+/// Range - Represents the interval [First, Last).
+template<typename T>
+class Range {
+  T First, Last;
+public:
+  Range() : First(0), Last(0) {}
+  Range(T first, T last) : First(first), Last(last) {}
+
+  bool operator==(const Range &other) const {
+    return (empty() && other.empty()) ||
+      (First == other.First && Last == other.Last);
+  }
+
+  /// empty - Return whether the range is empty.
+  bool empty() const {
+    return Last <= First;
+  }
+
+  /// getFirst - Return the value defining the start of the range.
+  T getFirst() const {
+    assert(!empty() && "An empty range has no starting value!");
+    return First;
+  }
+
+  /// getLast - Return the value defining the end of the range.
+  T getLast() const {
+    assert(!empty() && "An empty range has no ending value!");
+    return Last;
+  }
+
+  /// getWidth - Return the number of values in the range.
+  T getWidth() const {
+    return empty() ? 0 : Last - First;
+  }
+
+  /// contains - Return true if the given range is contained in this one.
+  bool contains(Range r) const {
+    if (r.empty())
+      return true;
+    if (empty())
+      return false;
+    return First <= r.First && Last >= r.Last;
+  }
+
+  /// intersects - Return true if the given range intersects this one.
+  bool intersects(Range r) const {
+    if (empty() || r.empty())
+      return false;
+    return r.First < Last && r.Last > First;
+  }
+
+  /// Displace - Return the range obtained by adding the given offset.
+  Range Displace(T Offset) const {
+    if (empty())
+      return Range();
+    assert(((Offset >= 0 && First + Offset >= First && Last + Offset >= Last) ||
+            (Offset < 0 && First + Offset < First && Last + Offset < Last)) &&
+           "Displacement wrapped range!");
+    return Range(First + Offset, Last + Offset);
+  }
+
+  /// Join - Return the smallest range containing this range and the given one.
+  Range Join(Range other) const {
+    if (empty())
+      return other;
+    if (other.empty())
+      return *this;
+    return Range(First < other.First ? First : other.First,
+                 Last > other.Last ? Last : other.Last);
+  }
+
+  /// Meet - Return the intersection of this range and the given one.
+  Range Meet(Range other) const {
+    if (empty() || other.empty())
+      return Range();
+    return Range(First > other.First ? First : other.First,
+                 Last < other.Last ? Last : other.Last);
+  }
+};
+
+#endif /* DRAGONEGG_RANGE_H */

Modified: dragonegg/trunk/Makefile
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=128420&r1=128419&r2=128420&view=diff
==============================================================================
--- dragonegg/trunk/Makefile (original)
+++ dragonegg/trunk/Makefile Mon Mar 28 14:44:58 2011
@@ -52,7 +52,7 @@
 	     -MD -MP \
 	     -DIN_GCC -DREVISION=\"$(REVISION)\" \
 	     -DGCC_MAJOR=$(GCC_MAJOR) -DGCC_MINOR=$(GCC_MINOR) \
-	     -I$(SRC_DIR) -I$(GCC_PLUGIN_DIR)/include
+	     -I$(SRC_DIR) -I$(SRC_DIR)/ADT -I$(GCC_PLUGIN_DIR)/include
 
 LD_OPTIONS+=$(shell $(LLVM_CONFIG) --ldflags) $(LDFLAGS)
 





More information about the llvm-commits mailing list