LiveInterval.h revision 52c1afcaea61440950a11a4ccadac4354420d727
1//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the LiveRange and LiveInterval classes.  Given some
11// numbering of each the machine instructions an interval [i, j) is said to be a
12// live interval for register v if there is no instruction with number j' >= j
13// such that v is live at j' and there is no instruction with number i' < i such
14// that v is live at i'. In this implementation intervals can have holes,
15// i.e. an interval might look like [1,20), [50,65), [1000,1001).  Each
16// individual range is represented as an instance of LiveRange, and the whole
17// interval is represented as an instance of LiveInterval.
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_CODEGEN_LIVEINTERVAL_H
22#define LLVM_CODEGEN_LIVEINTERVAL_H
23
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/Support/Allocator.h"
26#include "llvm/Support/AlignOf.h"
27#include <iosfwd>
28#include <cassert>
29#include <climits>
30
31namespace llvm {
32  class MachineInstr;
33  class MachineRegisterInfo;
34  class TargetRegisterInfo;
35  class raw_ostream;
36
37  /// VNInfo - Value Number Information.
38  /// This class holds information about a machine level values, including
39  /// definition and use points.
40  ///
41  /// Care must be taken in interpreting the def index of the value. The
42  /// following rules apply:
43  ///
44  /// If the isDefAccurate() method returns false then def does not contain the
45  /// index of the defining MachineInstr, or even (necessarily) to a
46  /// MachineInstr at all. In general such a def index is not meaningful
47  /// and should not be used. The exception is that, for values originally
48  /// defined by PHI instructions, after PHI elimination def will contain the
49  /// index of the MBB in which the PHI originally existed. This can be used
50  /// to insert code (spills or copies) which deals with the value, which will
51  /// be live in to the block.
52
53  class VNInfo {
54  private:
55    enum {
56      HAS_PHI_KILL    = 1,
57      REDEF_BY_EC     = 1 << 1,
58      IS_PHI_DEF      = 1 << 2,
59      IS_UNUSED       = 1 << 3,
60      IS_DEF_ACCURATE = 1 << 4
61    };
62
63    unsigned char flags;
64    union {
65      MachineInstr *copy;
66      unsigned reg;
67    } cr;
68
69  public:
70    /// Holds information about individual kills.
71    struct KillInfo {
72      bool isPHIKill : 1;
73      unsigned killIdx : 31;
74
75      KillInfo(bool isPHIKill, unsigned killIdx)
76        : isPHIKill(isPHIKill), killIdx(killIdx) {
77
78        assert(killIdx != 0 && "Zero kill indices are no longer permitted.");
79      }
80
81    };
82
83    typedef SmallVector<KillInfo, 4> KillSet;
84
85    /// The ID number of this value.
86    unsigned id;
87
88    /// The index of the defining instruction (if isDefAccurate() returns true).
89    unsigned def;
90
91    KillSet kills;
92
93    VNInfo()
94      : flags(IS_UNUSED), id(~1U), def(0) { cr.copy = 0; }
95
96    /// VNInfo constructor.
97    /// d is presumed to point to the actual defining instr. If it doesn't
98    /// setIsDefAccurate(false) should be called after construction.
99    VNInfo(unsigned i, unsigned d, MachineInstr *c)
100      : flags(IS_DEF_ACCURATE), id(i), def(d) { cr.copy = c; }
101
102    /// VNInfo construtor, copies values from orig, except for the value number.
103    VNInfo(unsigned i, const VNInfo &orig)
104      : flags(orig.flags), cr(orig.cr), id(i), def(orig.def), kills(orig.kills)
105    { }
106
107    /// Copy from the parameter into this VNInfo.
108    void copyFrom(VNInfo &src) {
109      flags = src.flags;
110      cr = src.cr;
111      def = src.def;
112      kills = src.kills;
113    }
114
115    /// Used for copying value number info.
116    unsigned getFlags() const { return flags; }
117    void setFlags(unsigned flags) { this->flags = flags; }
118
119    /// For a register interval, if this VN was definied by a copy instr
120    /// getCopy() returns a pointer to it, otherwise returns 0.
121    /// For a stack interval the behaviour of this method is undefined.
122    MachineInstr* getCopy() const { return cr.copy; }
123    /// For a register interval, set the copy member.
124    /// This method should not be called on stack intervals as it may lead to
125    /// undefined behavior.
126    void setCopy(MachineInstr *c) { cr.copy = c; }
127
128    /// For a stack interval, returns the reg which this stack interval was
129    /// defined from.
130    /// For a register interval the behaviour of this method is undefined.
131    unsigned getReg() const { return cr.reg; }
132    /// For a stack interval, set the defining register.
133    /// This method should not be called on register intervals as it may lead
134    /// to undefined behaviour.
135    void setReg(unsigned reg) { cr.reg = reg; }
136
137    /// Returns true if one or more kills are PHI nodes.
138    bool hasPHIKill() const { return flags & HAS_PHI_KILL; }
139    void setHasPHIKill(bool hasKill) {
140      if (hasKill)
141        flags |= HAS_PHI_KILL;
142      else
143        flags &= ~HAS_PHI_KILL;
144    }
145
146    /// Returns true if this value is re-defined by an early clobber somewhere
147    /// during the live range.
148    bool hasRedefByEC() const { return flags & REDEF_BY_EC; }
149    void setHasRedefByEC(bool hasRedef) {
150      if (hasRedef)
151        flags |= REDEF_BY_EC;
152      else
153        flags &= ~REDEF_BY_EC;
154    }
155
156    /// Returns true if this value is defined by a PHI instruction (or was,
157    /// PHI instrucions may have been eliminated).
158    bool isPHIDef() const { return flags & IS_PHI_DEF; }
159    void setIsPHIDef(bool phiDef) {
160      if (phiDef)
161        flags |= IS_PHI_DEF;
162      else
163        flags &= ~IS_PHI_DEF;
164    }
165
166    /// Returns true if this value is unused.
167    bool isUnused() const { return flags & IS_UNUSED; }
168    void setIsUnused(bool unused) {
169      if (unused)
170        flags |= IS_UNUSED;
171      else
172        flags &= ~IS_UNUSED;
173    }
174
175    /// Returns true if the def is accurate.
176    bool isDefAccurate() const { return flags & IS_DEF_ACCURATE; }
177    void setIsDefAccurate(bool defAccurate) {
178      if (defAccurate)
179        flags |= IS_DEF_ACCURATE;
180      else
181        flags &= ~IS_DEF_ACCURATE;
182    }
183
184  };
185
186  inline bool operator<(const VNInfo::KillInfo &k1, const VNInfo::KillInfo &k2) {
187    return k1.killIdx < k2.killIdx;
188  }
189
190  inline bool operator<(const VNInfo::KillInfo &k, unsigned idx) {
191    return k.killIdx < idx;
192  }
193
194  inline bool operator<(unsigned idx, const VNInfo::KillInfo &k) {
195    return idx < k.killIdx;
196  }
197
198  /// LiveRange structure - This represents a simple register range in the
199  /// program, with an inclusive start point and an exclusive end point.
200  /// These ranges are rendered as [start,end).
201  struct LiveRange {
202    unsigned start;  // Start point of the interval (inclusive)
203    unsigned end;    // End point of the interval (exclusive)
204    VNInfo *valno;   // identifier for the value contained in this interval.
205
206    LiveRange(unsigned S, unsigned E, VNInfo *V) : start(S), end(E), valno(V) {
207      assert(S < E && "Cannot create empty or backwards range");
208    }
209
210    /// contains - Return true if the index is covered by this range.
211    ///
212    bool contains(unsigned I) const {
213      return start <= I && I < end;
214    }
215
216    bool operator<(const LiveRange &LR) const {
217      return start < LR.start || (start == LR.start && end < LR.end);
218    }
219    bool operator==(const LiveRange &LR) const {
220      return start == LR.start && end == LR.end;
221    }
222
223    void dump() const;
224    void print(std::ostream &os) const;
225    void print(std::ostream *os) const { if (os) print(*os); }
226    void print(raw_ostream &os) const;
227    void print(raw_ostream *os) const { if (os) print(*os); }
228
229  private:
230    LiveRange(); // DO NOT IMPLEMENT
231  };
232
233  std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
234  raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR);
235
236
237  inline bool operator<(unsigned V, const LiveRange &LR) {
238    return V < LR.start;
239  }
240
241  inline bool operator<(const LiveRange &LR, unsigned V) {
242    return LR.start < V;
243  }
244
245  /// LiveInterval - This class represents some number of live ranges for a
246  /// register or value.  This class also contains a bit of register allocator
247  /// state.
248  class LiveInterval {
249  public:
250
251    typedef SmallVector<LiveRange,4> Ranges;
252    typedef SmallVector<VNInfo*,4> VNInfoList;
253
254    unsigned reg;        // the register or stack slot of this interval
255                         // if the top bits is set, it represents a stack slot.
256    float weight;        // weight of this interval
257    Ranges ranges;       // the ranges in which this register is live
258    VNInfoList valnos;   // value#'s
259
260    struct InstrSlots {
261      enum {
262        LOAD  = 0,
263        USE   = 1,
264        DEF   = 2,
265        STORE = 3,
266        NUM   = 4
267      };
268
269      static unsigned scale(unsigned slot, unsigned factor) {
270        unsigned index = slot / NUM,
271                 offset = slot % NUM;
272        assert(index <= ~0U / (factor * NUM) &&
273               "Rescaled interval would overflow");
274        return index * NUM * factor + offset;
275      }
276
277    };
278
279    LiveInterval(unsigned Reg, float Weight, bool IsSS = false)
280      : reg(Reg), weight(Weight) {
281      if (IsSS)
282        reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1));
283    }
284
285    typedef Ranges::iterator iterator;
286    iterator begin() { return ranges.begin(); }
287    iterator end()   { return ranges.end(); }
288
289    typedef Ranges::const_iterator const_iterator;
290    const_iterator begin() const { return ranges.begin(); }
291    const_iterator end() const  { return ranges.end(); }
292
293    typedef VNInfoList::iterator vni_iterator;
294    vni_iterator vni_begin() { return valnos.begin(); }
295    vni_iterator vni_end() { return valnos.end(); }
296
297    typedef VNInfoList::const_iterator const_vni_iterator;
298    const_vni_iterator vni_begin() const { return valnos.begin(); }
299    const_vni_iterator vni_end() const { return valnos.end(); }
300
301    /// advanceTo - Advance the specified iterator to point to the LiveRange
302    /// containing the specified position, or end() if the position is past the
303    /// end of the interval.  If no LiveRange contains this position, but the
304    /// position is in a hole, this method returns an iterator pointing the the
305    /// LiveRange immediately after the hole.
306    iterator advanceTo(iterator I, unsigned Pos) {
307      if (Pos >= endNumber())
308        return end();
309      while (I->end <= Pos) ++I;
310      return I;
311    }
312
313    void clear() {
314      while (!valnos.empty()) {
315        VNInfo *VNI = valnos.back();
316        valnos.pop_back();
317        VNI->~VNInfo();
318      }
319
320      ranges.clear();
321    }
322
323    /// isStackSlot - Return true if this is a stack slot interval.
324    ///
325    bool isStackSlot() const {
326      return reg & (1U << (sizeof(unsigned)*CHAR_BIT-1));
327    }
328
329    /// getStackSlotIndex - Return stack slot index if this is a stack slot
330    /// interval.
331    int getStackSlotIndex() const {
332      assert(isStackSlot() && "Interval is not a stack slot interval!");
333      return reg & ~(1U << (sizeof(unsigned)*CHAR_BIT-1));
334    }
335
336    bool hasAtLeastOneValue() const { return !valnos.empty(); }
337
338    bool containsOneValue() const { return valnos.size() == 1; }
339
340    unsigned getNumValNums() const { return (unsigned)valnos.size(); }
341
342    /// getValNumInfo - Returns pointer to the specified val#.
343    ///
344    inline VNInfo *getValNumInfo(unsigned ValNo) {
345      return valnos[ValNo];
346    }
347    inline const VNInfo *getValNumInfo(unsigned ValNo) const {
348      return valnos[ValNo];
349    }
350
351    /// getNextValue - Create a new value number and return it.  MIIdx specifies
352    /// the instruction that defines the value number.
353    VNInfo *getNextValue(unsigned MIIdx, MachineInstr *CopyMI,
354                         bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator) {
355
356      assert(MIIdx != ~0u && MIIdx != ~1u &&
357             "PHI def / unused flags should now be passed explicitly.");
358      VNInfo *VNI =
359        static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
360                                                      alignof<VNInfo>()));
361      new (VNI) VNInfo((unsigned)valnos.size(), MIIdx, CopyMI);
362      VNI->setIsDefAccurate(isDefAccurate);
363      valnos.push_back(VNI);
364      return VNI;
365    }
366
367    /// Create a copy of the given value. The new value will be identical except
368    /// for the Value number.
369    VNInfo *createValueCopy(const VNInfo *orig, BumpPtrAllocator &VNInfoAllocator) {
370
371      VNInfo *VNI =
372        static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
373                                                      alignof<VNInfo>()));
374
375      new (VNI) VNInfo((unsigned)valnos.size(), *orig);
376      valnos.push_back(VNI);
377      return VNI;
378    }
379
380    /// addKill - Add a kill instruction index to the specified value
381    /// number.
382    static void addKill(VNInfo *VNI, unsigned KillIdx, bool phiKill) {
383      VNInfo::KillSet &kills = VNI->kills;
384      VNInfo::KillInfo newKill(phiKill, KillIdx);
385      if (kills.empty()) {
386        kills.push_back(newKill);
387      } else {
388        VNInfo::KillSet::iterator
389          I = std::lower_bound(kills.begin(), kills.end(), newKill);
390        kills.insert(I, newKill);
391      }
392    }
393
394    /// addKills - Add a number of kills into the VNInfo kill vector. If this
395    /// interval is live at a kill point, then the kill is not added.
396    void addKills(VNInfo *VNI, const VNInfo::KillSet &kills) {
397      for (unsigned i = 0, e = static_cast<unsigned>(kills.size());
398           i != e; ++i) {
399        const VNInfo::KillInfo &Kill = kills[i];
400        if (!liveBeforeAndAt(Kill.killIdx)) {
401          VNInfo::KillSet::iterator
402            I = std::lower_bound(VNI->kills.begin(), VNI->kills.end(), Kill);
403          VNI->kills.insert(I, Kill);
404        }
405      }
406    }
407
408    /// removeKill - Remove the specified kill from the list of kills of
409    /// the specified val#.
410    static bool removeKill(VNInfo *VNI, unsigned KillIdx) {
411      VNInfo::KillSet &kills = VNI->kills;
412      VNInfo::KillSet::iterator
413        I = std::lower_bound(kills.begin(), kills.end(), KillIdx);
414      if (I != kills.end() && I->killIdx == KillIdx) {
415        kills.erase(I);
416        return true;
417      }
418      return false;
419    }
420
421    /// removeKills - Remove all the kills in specified range
422    /// [Start, End] of the specified val#.
423    static void removeKills(VNInfo *VNI, unsigned Start, unsigned End) {
424      VNInfo::KillSet &kills = VNI->kills;
425
426      VNInfo::KillSet::iterator
427        I = std::lower_bound(kills.begin(), kills.end(), Start);
428      VNInfo::KillSet::iterator
429        E = std::upper_bound(kills.begin(), kills.end(), End);
430      kills.erase(I, E);
431    }
432
433    /// isKill - Return true if the specified index is a kill of the
434    /// specified val#.
435    static bool isKill(const VNInfo *VNI, unsigned KillIdx) {
436      const VNInfo::KillSet &kills = VNI->kills;
437      VNInfo::KillSet::const_iterator
438        I = std::lower_bound(kills.begin(), kills.end(), KillIdx);
439      return I != kills.end() && I->killIdx == KillIdx;
440    }
441
442    /// isOnlyLROfValNo - Return true if the specified live range is the only
443    /// one defined by the its val#.
444    bool isOnlyLROfValNo(const LiveRange *LR) {
445      for (const_iterator I = begin(), E = end(); I != E; ++I) {
446        const LiveRange *Tmp = I;
447        if (Tmp != LR && Tmp->valno == LR->valno)
448          return false;
449      }
450      return true;
451    }
452
453    /// MergeValueNumberInto - This method is called when two value nubmers
454    /// are found to be equivalent.  This eliminates V1, replacing all
455    /// LiveRanges with the V1 value number with the V2 value number.  This can
456    /// cause merging of V1/V2 values numbers and compaction of the value space.
457    VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2);
458
459    /// MergeInClobberRanges - For any live ranges that are not defined in the
460    /// current interval, but are defined in the Clobbers interval, mark them
461    /// used with an unknown definition value. Caller must pass in reference to
462    /// VNInfoAllocator since it will create a new val#.
463    void MergeInClobberRanges(const LiveInterval &Clobbers,
464                              BumpPtrAllocator &VNInfoAllocator);
465
466    /// MergeInClobberRange - Same as MergeInClobberRanges except it merge in a
467    /// single LiveRange only.
468    void MergeInClobberRange(unsigned Start, unsigned End,
469                             BumpPtrAllocator &VNInfoAllocator);
470
471    /// MergeValueInAsValue - Merge all of the live ranges of a specific val#
472    /// in RHS into this live interval as the specified value number.
473    /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the
474    /// current interval, it will replace the value numbers of the overlaped
475    /// live ranges with the specified value number.
476    void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo);
477
478    /// MergeValueInAsValue - Merge all of the live ranges of a specific val#
479    /// in RHS into this live interval as the specified value number.
480    /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the
481    /// current interval, but only if the overlapping LiveRanges have the
482    /// specified value number.
483    void MergeValueInAsValue(const LiveInterval &RHS,
484                             const VNInfo *RHSValNo, VNInfo *LHSValNo);
485
486    /// Copy - Copy the specified live interval. This copies all the fields
487    /// except for the register of the interval.
488    void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI,
489              BumpPtrAllocator &VNInfoAllocator);
490
491    bool empty() const { return ranges.empty(); }
492
493    /// beginNumber - Return the lowest numbered slot covered by interval.
494    unsigned beginNumber() const {
495      if (empty())
496        return 0;
497      return ranges.front().start;
498    }
499
500    /// endNumber - return the maximum point of the interval of the whole,
501    /// exclusive.
502    unsigned endNumber() const {
503      if (empty())
504        return 0;
505      return ranges.back().end;
506    }
507
508    bool expiredAt(unsigned index) const {
509      return index >= endNumber();
510    }
511
512    bool liveAt(unsigned index) const;
513
514    // liveBeforeAndAt - Check if the interval is live at the index and the
515    // index just before it. If index is liveAt, check if it starts a new live
516    // range.If it does, then check if the previous live range ends at index-1.
517    bool liveBeforeAndAt(unsigned index) const;
518
519    /// getLiveRangeContaining - Return the live range that contains the
520    /// specified index, or null if there is none.
521    const LiveRange *getLiveRangeContaining(unsigned Idx) const {
522      const_iterator I = FindLiveRangeContaining(Idx);
523      return I == end() ? 0 : &*I;
524    }
525
526    /// getLiveRangeContaining - Return the live range that contains the
527    /// specified index, or null if there is none.
528    LiveRange *getLiveRangeContaining(unsigned Idx) {
529      iterator I = FindLiveRangeContaining(Idx);
530      return I == end() ? 0 : &*I;
531    }
532
533    /// FindLiveRangeContaining - Return an iterator to the live range that
534    /// contains the specified index, or end() if there is none.
535    const_iterator FindLiveRangeContaining(unsigned Idx) const;
536
537    /// FindLiveRangeContaining - Return an iterator to the live range that
538    /// contains the specified index, or end() if there is none.
539    iterator FindLiveRangeContaining(unsigned Idx);
540
541    /// findDefinedVNInfo - Find the VNInfo that's defined at the specified
542    /// index (register interval) or defined by the specified register (stack
543    /// inteval).
544    VNInfo *findDefinedVNInfo(unsigned DefIdxOrReg) const;
545
546    /// overlaps - Return true if the intersection of the two live intervals is
547    /// not empty.
548    bool overlaps(const LiveInterval& other) const {
549      return overlapsFrom(other, other.begin());
550    }
551
552    /// overlaps - Return true if the live interval overlaps a range specified
553    /// by [Start, End).
554    bool overlaps(unsigned Start, unsigned End) const;
555
556    /// overlapsFrom - Return true if the intersection of the two live intervals
557    /// is not empty.  The specified iterator is a hint that we can begin
558    /// scanning the Other interval starting at I.
559    bool overlapsFrom(const LiveInterval& other, const_iterator I) const;
560
561    /// addRange - Add the specified LiveRange to this interval, merging
562    /// intervals as appropriate.  This returns an iterator to the inserted live
563    /// range (which may have grown since it was inserted.
564    void addRange(LiveRange LR) {
565      addRangeFrom(LR, ranges.begin());
566    }
567
568    /// join - Join two live intervals (this, and other) together.  This applies
569    /// mappings to the value numbers in the LHS/RHS intervals as specified.  If
570    /// the intervals are not joinable, this aborts.
571    void join(LiveInterval &Other, const int *ValNoAssignments,
572              const int *RHSValNoAssignments,
573              SmallVector<VNInfo*, 16> &NewVNInfo,
574              MachineRegisterInfo *MRI);
575
576    /// isInOneLiveRange - Return true if the range specified is entirely in the
577    /// a single LiveRange of the live interval.
578    bool isInOneLiveRange(unsigned Start, unsigned End);
579
580    /// removeRange - Remove the specified range from this interval.  Note that
581    /// the range must be a single LiveRange in its entirety.
582    void removeRange(unsigned Start, unsigned End, bool RemoveDeadValNo = false);
583
584    void removeRange(LiveRange LR, bool RemoveDeadValNo = false) {
585      removeRange(LR.start, LR.end, RemoveDeadValNo);
586    }
587
588    /// removeValNo - Remove all the ranges defined by the specified value#.
589    /// Also remove the value# from value# list.
590    void removeValNo(VNInfo *ValNo);
591
592    /// scaleNumbering - Renumber VNI and ranges to provide gaps for new
593    /// instructions.
594    void scaleNumbering(unsigned factor);
595
596    /// getSize - Returns the sum of sizes of all the LiveRange's.
597    ///
598    unsigned getSize() const;
599
600    /// ComputeJoinedWeight - Set the weight of a live interval after
601    /// Other has been merged into it.
602    void ComputeJoinedWeight(const LiveInterval &Other);
603
604    bool operator<(const LiveInterval& other) const {
605      return beginNumber() < other.beginNumber();
606    }
607
608    void print(std::ostream &OS, const TargetRegisterInfo *TRI = 0) const;
609    void print(std::ostream *OS, const TargetRegisterInfo *TRI = 0) const {
610      if (OS) print(*OS, TRI);
611    }
612    void print(raw_ostream &OS, const TargetRegisterInfo *TRI = 0) const;
613    void print(raw_ostream *OS, const TargetRegisterInfo *TRI = 0) const {
614      if (OS) print(*OS, TRI);
615    }
616    void dump() const;
617
618  private:
619
620    Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From);
621    void extendIntervalEndTo(Ranges::iterator I, unsigned NewEnd);
622    Ranges::iterator extendIntervalStartTo(Ranges::iterator I, unsigned NewStr);
623    LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT
624
625  };
626
627  inline std::ostream &operator<<(std::ostream &OS, const LiveInterval &LI) {
628    LI.print(OS);
629    return OS;
630  }
631  inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) {
632    LI.print(OS);
633    return OS;
634  }
635}
636
637#endif
638