[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