Remove unused variable.
[oota-llvm.git] / lib / CodeGen / LiveIntervalUnion.h
index 3953c5930ad80f4119a0bb32c964246c1fa40270..dbf5ac122d5dd68eac7a2b426356e73114f20556 100644 (file)
 #ifndef LLVM_CODEGEN_LIVEINTERVALUNION
 #define LLVM_CODEGEN_LIVEINTERVALUNION
 
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/CodeGen/LiveInterval.h"
-#include <vector>
-#include <set>
 
 namespace llvm {
 
-// 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.
-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);
-  }
-
-  bool operator<(const LiveSegment &ls) const {
-    return start < ls.start || (start == ls.start && end < ls.end);
-  }
-};
-
-/// 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;
-}
+class MachineLoopRange;
+class TargetRegisterInfo;
 
-inline bool operator<(SlotIndex V, const LiveSegment &ls) {
-  return V < ls.start;
-}
+#ifndef NDEBUG
+// forward declaration
+template <unsigned Element> class SparseBitVector;
+typedef SparseBitVector<128> LiveVirtRegBitSet;
+#endif
 
-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 &VRSeg,
+        const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) {
+  return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end;
 }
 
 /// Union of live intervals that are strong candidates for coalescing into a
@@ -70,18 +44,9 @@ inline bool operator<(const LiveSegment &ls, SlotIndex V) {
 /// 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
@@ -89,102 +54,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
-  LiveVirtRegs lvrs_;      // set of live virtual regs in the union
+  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) {}
-  
-  void init(unsigned repReg) { repReg_ = repReg; }
-
-  SegmentIter begin() { return segments_.begin(); }
-  SegmentIter end() { return segments_.end(); }
-
-  /// FIXME: !!!!!!!!!!! Keeps a non-const ref
-  void unify(LiveInterval &lvr);
-
-  // FIXME: needed by RegAllocGreedy
-  //void extract(const LiveInterval &li);
-
-  /// 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) {}
+  LiveIntervalUnion(unsigned r, Allocator &a) : RepReg(r), Tag(0), Segments(a)
+    {}
 
-  public:
-    // Public default ctor.
-    InterferenceResult(): lvrSegI_(), liuSegI_() {}
+  // 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 find(SlotIndex x) { return Segments.find(x); }
+  bool empty() const { return Segments.empty(); }
+  SlotIndex startIndex() const { return Segments.start(); }
 
-    // Note: this interface provides raw access to the iterators because the
-    // result has no way to tell if it's valid to dereference them.
+  // Provide public access to the underlying map to allow overlap iteration.
+  typedef LiveSegments Map;
+  const Map &getMap() { return Segments; }
 
-    // Access the lvr segment. 
-    const LiveInterval::iterator &lvrSegPos() const { return lvrSegI_; }
+  /// getTag - Return an opaque tag representing the current state of the union.
+  unsigned getTag() const { return Tag; }
 
-    // Access the liu segment.
-    const SegmentIter &liuSeg() const { return liuSegI_; }
+  /// changedSince - Return true if the union change since getTag returned tag.
+  bool changedSince(unsigned tag) const { return tag != Tag; }
 
-    bool operator==(const InterferenceResult &ir) const {
-      return lvrSegI_ == ir.lvrSegI_ && liuSegI_ == ir.liuSegI_;
-    }
-    bool operator!=(const InterferenceResult &ir) const {
-      return !operator==(ir);
-    }
-  };
+  // Add a live virtual register to this union and merge its segments.
+  void unify(LiveInterval &VirtReg);
+
+  // Remove a live virtual register's segments from this union.
+  void extract(LiveInterval &VirtReg);
+
+  // 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;
+
+#ifndef NDEBUG
+  // Verify the live intervals in this union and add them to the visited set.
+  void verify(LiveVirtRegBitSet& VisitedVRegs);
+#endif
 
   /// Query interferences between a single live virtual register and a live
   /// interval union.
   class Query {
-    LiveIntervalUnion &liu_;
-    LiveInterval &lvr_;
-    InterferenceResult firstInterference_;
-    // TBD: interfering vregs
+    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(LiveInterval &lvr, LiveIntervalUnion &liu): liu_(liu), lvr_(lvr) {}
-
-    LiveInterval &lvr() const { return lvr_; }
+    Query(): LiveUnion(), VirtReg(), Tag(0), UserTag(0) {}
+
+    Query(LiveInterval *VReg, LiveIntervalUnion *LIU):
+      LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false),
+      SeenAllInterferences(false), SeenUnspillableVReg(false)
+    {}
+
+    void clear() {
+      LiveUnion = NULL;
+      VirtReg = NULL;
+      InterferingVRegs.clear();
+      CheckedFirstInterference = false;
+      SeenAllInterferences = false;
+      SeenUnspillableVReg = false;
+      Tag = 0;
+      UserTag = 0;
+    }
 
-    bool isInterference(const InterferenceResult &ir) const {
-      if (ir.lvrSegI_ != lvr_.end()) {
-        assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) &&
-               "invalid segment iterators");
-        return true;
+    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;
       }
-      return false;
+      clear();
+      LiveUnion = LIU;
+      VirtReg = VReg;
+      Tag = LIU->getTag();
+      UserTag = UTag;
+    }
+
+    LiveInterval &virtReg() const {
+      assert(VirtReg && "uninitialized");
+      return *VirtReg;
     }
 
-    // Does this live virtual register interfere with the union.
-    bool checkInterference() { return isInterference(firstInterference()); }
+    // 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);
+
+    // Was this virtual register visited during collectInterferingVRegs?
+    bool isSeenInterference(LiveInterval *VReg) const;
 
-    // First pair of interfering segments, or a noninterfering result.
-    InterferenceResult firstInterference();
+    // Did collectInterferingVRegs collect all interferences?
+    bool seenAllInterferences() const { return SeenAllInterferences; }
+
+    // Did collectInterferingVRegs encounter an unspillable vreg?
+    bool seenUnspillableVReg() const { return SeenUnspillableVReg; }
+
+    // Vector generated by collectInterferingVRegs.
+    const SmallVectorImpl<LiveInterval*> &interferingVRegs() const {
+      return InterferingVRegs;
+    }
 
-    // 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;
-        
-    // TBD: bool collectInterferingVirtRegs(unsigned maxInterference)
+    /// 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
   };
 };