We need to verify that the machine instruction we're using as a replacement for
[oota-llvm.git] / lib / CodeGen / LiveIntervalUnion.h
index b6eaa71cfaa41d16dd7f5e249e3fa86ffd091293..5d64d285f39aa7644004d4739a94d1c24a2ecccf 100644 (file)
 #ifndef LLVM_CODEGEN_LIVEINTERVALUNION
 #define LLVM_CODEGEN_LIVEINTERVALUNION
 
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/CodeGen/LiveInterval.h"
-#include <vector>
-#include <set>
+
+#include <algorithm>
 
 namespace llvm {
 
+class MachineLoopRange;
+class TargetRegisterInfo;
+
 #ifndef NDEBUG
 // forward declaration
 template <unsigned Element> class SparseBitVector;
-typedef SparseBitVector<128> LvrBitSet;
+typedef SparseBitVector<128> LiveVirtRegBitSet;
 #endif
 
-/// A LiveSegment is a copy of a LiveRange object used within
-/// LiveIntervalUnion. LiveSegment additionally contains a pointer to its
-/// original live virtual register (LiveInterval). This allows quick lookup of
-/// the live virtual register as we iterate over live segments in a union. Note
-/// that LiveRange is misnamed and actually represents only a single contiguous
-/// interval within a virtual register's liveness. To limit confusion, in this
-/// file we refer it as a live segment.
-///
-/// Note: This currently represents a half-open interval [start,end).
-/// If LiveRange is modified to represent a closed interval, so should this.
-struct LiveSegment {
-  SlotIndex start;
-  SlotIndex end;
-  LiveInterval *liveVirtReg;
-
-  LiveSegment(SlotIndex s, SlotIndex e, LiveInterval *lvr)
-    : start(s), end(e), liveVirtReg(lvr) {}
-
-  bool operator==(const LiveSegment &ls) const {
-    return start == ls.start && end == ls.end && liveVirtReg == ls.liveVirtReg;
-  }
-
-  bool operator!=(const LiveSegment &ls) const {
-    return !operator==(ls);
-  }
-
-  // Order segments by starting point only--we expect them to be disjoint.
-  bool operator<(const LiveSegment &ls) const { return start < ls.start; }
-
-  void dump() const;
-  void print(raw_ostream &os) const;
-};
-
-inline bool operator<(SlotIndex V, const LiveSegment &ls) {
-  return V < ls.start;
-}
-
-inline bool operator<(const LiveSegment &ls, SlotIndex V) {
-  return ls.start < V;
-}
-
 /// Compare a live virtual register segment to a LiveIntervalUnion segment.
-inline bool overlap(const LiveRange &lvrSeg, const LiveSegment &liuSeg) {
-  return lvrSeg.start < liuSeg.end && liuSeg.start < lvrSeg.end;
+inline bool
+overlap(const LiveRange &VRSeg,
+        const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) {
+  return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end;
 }
 
-template <> struct isPodLike<LiveSegment> { static const bool value = true; };
-
-raw_ostream& operator<<(raw_ostream& os, const LiveSegment &ls);
-
-/// Abstraction to provide info for the representative register.
-class AbstractRegisterDescription {
-public:
-  virtual const char *getName(unsigned reg) const = 0;
-  virtual ~AbstractRegisterDescription() {}
-};
-
 /// Union of live intervals that are strong candidates for coalescing into a
 /// single register (either physical or virtual depending on the context).  We
 /// expect the constituent live intervals to be disjoint, although we may
 /// eventually make exceptions to handle value-based interference.
 class LiveIntervalUnion {
   // A set of live virtual register segments that supports fast insertion,
-  // intersection, and removal. 
-  //
-  // FIXME: std::set is a placeholder until we decide how to
-  // efficiently represent it. Probably need to roll our own B-tree.
-  typedef std::set<LiveSegment> LiveSegments;
-
-  // A set of live virtual registers. Elements have type LiveInterval, where
-  // each element represents the liveness of a single live virtual register.
-  // This is traditionally known as a live range, but we refer is as a live
-  // virtual register to avoid confusing it with the misnamed LiveRange
-  // class.
-  typedef std::vector<LiveInterval*> LiveVirtRegs;
+  // intersection, and removal.
+  // Mapping SlotIndex intervals to virtual register numbers.
+  typedef IntervalMap<SlotIndex, LiveInterval*> LiveSegments;
 
 public:
   // SegmentIter can advance to the next segment ordered by starting position
@@ -111,164 +56,134 @@ public:
   // to reach the current segment's containing virtual register.
   typedef LiveSegments::iterator SegmentIter;
 
-  class InterferenceResult;
+  // LiveIntervalUnions share an external allocator.
+  typedef LiveSegments::Allocator Allocator;
+
   class Query;
 
 private:
-  unsigned repReg_;        // representative register number
-  LiveSegments segments_;  // union of virtual reg segements
+  const unsigned RepReg;  // representative register number
+  unsigned Tag;           // unique tag for current contents.
+  LiveSegments Segments;  // union of virtual reg segments
 
 public:
-  // default ctor avoids placement new
-  LiveIntervalUnion() : repReg_(0) {}
-
-  // Initialize the union by associating it with a representative register
-  // number.
-  void init(unsigned repReg) { repReg_ = repReg; }
+  LiveIntervalUnion(unsigned r, Allocator &a) : RepReg(r), Tag(0), Segments(a)
+    {}
 
   // Iterate over all segments in the union of live virtual registers ordered
   // by their starting position.
-  SegmentIter begin() { return segments_.begin(); }
-  SegmentIter end() { return segments_.end(); }
+  SegmentIter begin() { return Segments.begin(); }
+  SegmentIter end() { return Segments.end(); }
+  SegmentIter find(SlotIndex x) { return Segments.find(x); }
+  bool empty() const { return Segments.empty(); }
+  SlotIndex startIndex() const { return Segments.start(); }
 
-  // Return an iterator to the first segment after or including begin that
-  // intersects with lvrSeg.
-  SegmentIter upperBound(SegmentIter begin, const LiveSegment &seg);
+  // Provide public access to the underlying map to allow overlap iteration.
+  typedef LiveSegments Map;
+  const Map &getMap() { return Segments; }
+
+  /// getTag - Return an opaque tag representing the current state of the union.
+  unsigned getTag() const { return Tag; }
+
+  /// changedSince - Return true if the union change since getTag returned tag.
+  bool changedSince(unsigned tag) const { return tag != Tag; }
 
   // Add a live virtual register to this union and merge its segments.
-  // Holds a nonconst reference to the LVR for later maniplution.
-  void unify(LiveInterval &lvr);
+  void unify(LiveInterval &VirtReg);
 
   // Remove a live virtual register's segments from this union.
-  void extract(const LiveInterval &lvr);
+  void extract(LiveInterval &VirtReg);
 
-  void dump(const AbstractRegisterDescription *regInfo) const;
+  // Remove all inserted virtual registers.
+  void clear() { Segments.clear(); ++Tag; }
+
+  // Print union, using TRI to translate register names
+  void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const;
 
-  // If tri != NULL, use it to decode repReg_
-  void print(raw_ostream &os, const AbstractRegisterDescription *rdesc) const;
-  
 #ifndef NDEBUG
   // Verify the live intervals in this union and add them to the visited set.
-  void verify(LvrBitSet& visitedVRegs);
+  void verify(LiveVirtRegBitSet& VisitedVRegs);
 #endif
 
-  /// Cache a single interference test result in the form of two intersecting
-  /// segments. This allows efficiently iterating over the interferences. The
-  /// iteration logic is handled by LiveIntervalUnion::Query which may
-  /// filter interferences depending on the type of query.
-  class InterferenceResult {
-    friend class Query;
-
-    LiveInterval::iterator lvrSegI_; // current position in _lvr
-    SegmentIter liuSegI_;            // current position in _liu
-    
-    // Internal ctor.
-    InterferenceResult(LiveInterval::iterator lvrSegI, SegmentIter liuSegI)
-      : lvrSegI_(lvrSegI), liuSegI_(liuSegI) {}
-
-  public:
-    // Public default ctor.
-    InterferenceResult(): lvrSegI_(), liuSegI_() {}
-
-    // Note: this interface provides raw access to the iterators because the
-    // result has no way to tell if it's valid to dereference them.
-
-    // Access the lvr segment. 
-    LiveInterval::iterator lvrSegPos() const { return lvrSegI_; }
-
-    // Access the liu segment.
-    SegmentIter liuSegPos() const { return liuSegI_; }
-
-    bool operator==(const InterferenceResult &ir) const {
-      return lvrSegI_ == ir.lvrSegI_ && liuSegI_ == ir.liuSegI_;
-    }
-    bool operator!=(const InterferenceResult &ir) const {
-      return !operator==(ir);
-    }
-  };
-
   /// Query interferences between a single live virtual register and a live
   /// interval union.
   class Query {
-    LiveIntervalUnion *liu_;
-    LiveInterval *lvr_;
-    InterferenceResult firstInterference_;
-    SmallVector<LiveInterval*,4> interferingVRegs_;
-    bool seenUnspillableVReg_;
+    LiveIntervalUnion *LiveUnion;
+    LiveInterval *VirtReg;
+    LiveInterval::iterator VirtRegI; // current position in VirtReg
+    SegmentIter LiveUnionI;          // current position in LiveUnion
+    SmallVector<LiveInterval*,4> InterferingVRegs;
+    bool CheckedFirstInterference;
+    bool SeenAllInterferences;
+    bool SeenUnspillableVReg;
+    unsigned Tag, UserTag;
 
   public:
-    Query(): liu_(), lvr_() {}
+    Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {}
 
-    Query(LiveInterval *lvr, LiveIntervalUnion *liu):
-      liu_(liu), lvr_(lvr), seenUnspillableVReg_(false) {}
+    Query(LiveInterval *VReg, LiveIntervalUnion *LIU):
+      LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false),
+      SeenAllInterferences(false), SeenUnspillableVReg(false)
+    {}
 
     void clear() {
-      liu_ = NULL;
-      lvr_ = NULL;
-      firstInterference_ = InterferenceResult();
-      interferingVRegs_.clear();
-      seenUnspillableVReg_ = false;
+      LiveUnion = NULL;
+      VirtReg = NULL;
+      InterferingVRegs.clear();
+      CheckedFirstInterference = false;
+      SeenAllInterferences = false;
+      SeenUnspillableVReg = false;
+      Tag = 0;
+      UserTag = 0;
     }
-    
-    void init(LiveInterval *lvr, LiveIntervalUnion *liu) {
-      if (lvr_ == lvr) {
-        // We currently allow query objects to be reused acrossed live virtual
-        // registers, but always for the same live interval union.
-        assert(liu_ == liu && "inconsistent initialization");
+
+    void init(unsigned UTag, LiveInterval *VReg, LiveIntervalUnion *LIU) {
+      assert(VReg && LIU && "Invalid arguments");
+      if (UserTag == UTag && VirtReg == VReg &&
+          LiveUnion == LIU && !LIU->changedSince(Tag)) {
         // Retain cached results, e.g. firstInterference.
         return;
       }
-      liu_ = liu;
-      lvr_ = lvr;
-      // Clear cached results.
-      firstInterference_ = InterferenceResult();
-      interferingVRegs_.clear();
-      seenUnspillableVReg_ = false;
+      clear();
+      LiveUnion = LIU;
+      VirtReg = VReg;
+      Tag = LIU->getTag();
+      UserTag = UTag;
     }
 
-    LiveInterval &lvr() const { assert(lvr_ && "uninitialized"); return *lvr_; }
-
-    bool isInterference(const InterferenceResult &ir) const {
-      if (ir.lvrSegI_ != lvr_->end()) {
-        assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) &&
-               "invalid segment iterators");
-        return true;
-      }
-      return false;
+    LiveInterval &virtReg() const {
+      assert(VirtReg && "uninitialized");
+      return *VirtReg;
     }
 
-    // Does this live virtual register interfere with the union.
-    bool checkInterference() { return isInterference(firstInterference()); }
-
-    // Get the first pair of interfering segments, or a noninterfering result.
-    // This initializes the firstInterference_ cache.
-    InterferenceResult firstInterference();
-
-    // Treat the result as an iterator and advance to the next interfering pair
-    // of segments. Visiting each unique interfering pairs means that the same
-    // lvr or liu segment may be visited multiple times.
-    bool nextInterference(InterferenceResult &ir) const;
+    // Does this live virtual register interfere with the union?
+    bool checkInterference() { return collectInterferingVRegs(1); }
 
     // Count the virtual registers in this union that interfere with this
     // query's live virtual register, up to maxInterferingRegs.
-    unsigned collectInterferingVRegs(unsigned maxInterferingRegs = UINT_MAX);
+    unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX);
 
     // Was this virtual register visited during collectInterferingVRegs?
-    bool isSeenInterference(LiveInterval *lvr) const;
+    bool isSeenInterference(LiveInterval *VReg) const;
+
+    // Did collectInterferingVRegs collect all interferences?
+    bool seenAllInterferences() const { return SeenAllInterferences; }
 
     // Did collectInterferingVRegs encounter an unspillable vreg?
-    bool seenUnspillableVReg() const {
-      return seenUnspillableVReg_;
-    }
+    bool seenUnspillableVReg() const { return SeenUnspillableVReg; }
 
     // Vector generated by collectInterferingVRegs.
     const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
-      return interferingVRegs_;
+      return InterferingVRegs;
     }
-    
+
+    /// checkLoopInterference - Return true if there is interference overlapping
+    /// Loop.
+    bool checkLoopInterference(MachineLoopRange*);
+
   private:
-    // Private interface for queries
-    void findIntersection(InterferenceResult &ir) const;
+    Query(const Query&);          // DO NOT IMPLEMENT
+    void operator=(const Query&); // DO NOT IMPLEMENT
   };
 };