Legalize support for fpextend of vector. PR9309.
[oota-llvm.git] / lib / CodeGen / LiveIntervalUnion.h
index 74499f68215bf4013dcfef3956684fe9ff36a3e6..6f9c5f4455e9eb5bd62c09c4e7f137304c38fb6e 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,45 +56,51 @@ public:
   // to reach the current segment's containing virtual register.
   typedef LiveSegments::iterator SegmentIter;
 
+  // LiveIntervalUnions share an external allocator.
+  typedef LiveSegments::Allocator Allocator;
+
   class InterferenceResult;
   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(); }
+
+  // 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; }
 
-  // Return an iterator to the first segment after or including begin that
-  // intersects with lvrSeg.
-  SegmentIter upperBound(SegmentIter begin, const LiveSegment &seg);
+  /// 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;
+  // 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
@@ -159,95 +110,146 @@ public:
   class InterferenceResult {
     friend class Query;
 
-    LiveInterval::iterator lvrSegI_; // current position in _lvr
-    SegmentIter liuSegI_;            // current position in _liu
-    
+    LiveInterval::iterator VirtRegI; // current position in VirtReg
+    SegmentIter LiveUnionI;          // current position in LiveUnion
+
     // Internal ctor.
-    InterferenceResult(LiveInterval::iterator lvrSegI, SegmentIter liuSegI)
-      : lvrSegI_(lvrSegI), liuSegI_(liuSegI) {}
+    InterferenceResult(LiveInterval::iterator VRegI, SegmentIter UnionI)
+      : VirtRegI(VRegI), LiveUnionI(UnionI) {}
 
   public:
     // Public default ctor.
-    InterferenceResult(): lvrSegI_(), liuSegI_() {}
+    InterferenceResult(): VirtRegI(), LiveUnionI() {}
+
+    /// start - Return the start of the current overlap.
+    SlotIndex start() const {
+      return std::max(VirtRegI->start, LiveUnionI.start());
+    }
+
+    /// stop - Return the end of the current overlap.
+    SlotIndex stop() const {
+      return std::min(VirtRegI->end, LiveUnionI.stop());
+    }
+
+    /// interference - Return the register that is interfering here.
+    LiveInterval *interference() const { return LiveUnionI.value(); }
 
     // 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. 
-    const LiveInterval::iterator &lvrSegPos() const { return lvrSegI_; }
+    // Access the VirtReg segment.
+    LiveInterval::iterator virtRegPos() const { return VirtRegI; }
 
-    // Access the liu segment.
-    const SegmentIter &liuSegPos() const { return liuSegI_; }
+    // Access the LiveUnion segment.
+    const SegmentIter &liveUnionPos() const { return LiveUnionI; }
 
-    bool operator==(const InterferenceResult &ir) const {
-      return lvrSegI_ == ir.lvrSegI_ && liuSegI_ == ir.liuSegI_;
+    bool operator==(const InterferenceResult &IR) const {
+      return VirtRegI == IR.VirtRegI && LiveUnionI == IR.LiveUnionI;
     }
-    bool operator!=(const InterferenceResult &ir) const {
-      return !operator==(ir);
+    bool operator!=(const InterferenceResult &IR) const {
+      return !operator==(IR);
     }
+
+    void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const;
   };
 
   /// 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;
+    InterferenceResult FirstInterference;
+    SmallVector<LiveInterval*,4> InterferingVRegs;
+    bool CheckedFirstInterference;
+    bool SeenAllInterferences;
+    bool SeenUnspillableVReg;
+    unsigned Tag;
 
   public:
-    Query(): liu_(), lvr_() {}
+    Query(): LiveUnion(), VirtReg() {}
 
-    Query(LiveInterval *lvr, LiveIntervalUnion *liu): liu_(liu), lvr_(lvr) {}
+    Query(LiveInterval *VReg, LiveIntervalUnion *LIU):
+      LiveUnion(LIU), VirtReg(VReg), CheckedFirstInterference(false),
+      SeenAllInterferences(false), SeenUnspillableVReg(false)
+    {}
 
     void clear() {
-      liu_ = NULL;
-      lvr_ = NULL;
-      firstInterference_ = InterferenceResult();
+      LiveUnion = NULL;
+      VirtReg = NULL;
+      InterferingVRegs.clear();
+      CheckedFirstInterference = false;
+      SeenAllInterferences = false;
+      SeenUnspillableVReg = false;
+      Tag = 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(LiveInterval *VReg, LiveIntervalUnion *LIU) {
+      assert(VReg && LIU && "Invalid arguments");
+      if (VirtReg == VReg && LiveUnion == LIU && !LIU->changedSince(Tag)) {
         // Retain cached results, e.g. firstInterference.
         return;
       }
-      liu_ = liu;
-      lvr_ = lvr;
-      // Clear cached results.
-      firstInterference_ = InterferenceResult();
+      clear();
+      LiveUnion = LIU;
+      VirtReg = VReg;
+      Tag = LIU->getTag();
     }
 
-    LiveInterval &lvr() const { assert(lvr_ && "uninitialized"); return *lvr_; }
+    LiveInterval &virtReg() const {
+      assert(VirtReg && "uninitialized");
+      return *VirtReg;
+    }
 
-    bool isInterference(const InterferenceResult &ir) const {
-      if (ir.lvrSegI_ != lvr_->end()) {
-        assert(overlap(*ir.lvrSegI_, *ir.liuSegI_) &&
+    bool isInterference(const InterferenceResult &IR) const {
+      if (IR.VirtRegI != VirtReg->end()) {
+        assert(overlap(*IR.VirtRegI, IR.LiveUnionI) &&
                "invalid segment iterators");
         return true;
       }
       return false;
     }
 
-    // Does this live virtual register interfere with the union.
+    // 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();
+    const 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;
-        
-    // TBD: bool collectInterferingVirtRegs(unsigned maxInterference)
+    // VirtReg or LiveUnion segment may be visited multiple times.
+    bool nextInterference(InterferenceResult &IR) const;
 
+    // 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;
+
+    // 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;
+    }
+
+    /// checkLoopInterference - Return true if there is interference overlapping
+    /// Loop.
+    bool checkLoopInterference(MachineLoopRange*);
+
+    void print(raw_ostream &OS, const TargetRegisterInfo *TRI);
   private:
+    Query(const Query&);          // DO NOT IMPLEMENT
+    void operator=(const Query&); // DO NOT IMPLEMENT
+
     // Private interface for queries
-    void findIntersection(InterferenceResult &ir) const;
+    void findIntersection(InterferenceResult &IR) const;
   };
 };