xref: /openbsd-src/gnu/llvm/llvm/include/llvm/CodeGen/LiveIntervalUnion.h (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- LiveIntervalUnion.h - Live interval union data struct ---*- C++ -*--===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // LiveIntervalUnion is a union of live segments across multiple live virtual
1009467b48Spatrick // registers. This may be used during coalescing to represent a congruence
1109467b48Spatrick // class, or during register allocation to model liveness of a physical
1209467b48Spatrick // register.
1309467b48Spatrick //
1409467b48Spatrick //===----------------------------------------------------------------------===//
1509467b48Spatrick 
1609467b48Spatrick #ifndef LLVM_CODEGEN_LIVEINTERVALUNION_H
1709467b48Spatrick #define LLVM_CODEGEN_LIVEINTERVALUNION_H
1809467b48Spatrick 
1909467b48Spatrick #include "llvm/ADT/IntervalMap.h"
2009467b48Spatrick #include "llvm/ADT/SmallVector.h"
2109467b48Spatrick #include "llvm/CodeGen/LiveInterval.h"
2209467b48Spatrick #include "llvm/CodeGen/SlotIndexes.h"
2309467b48Spatrick #include <cassert>
2409467b48Spatrick #include <limits>
2509467b48Spatrick 
2609467b48Spatrick namespace llvm {
2709467b48Spatrick 
2809467b48Spatrick class raw_ostream;
2909467b48Spatrick class TargetRegisterInfo;
3009467b48Spatrick 
3109467b48Spatrick #ifndef NDEBUG
3209467b48Spatrick // forward declaration
3309467b48Spatrick template <unsigned Element> class SparseBitVector;
3409467b48Spatrick 
3509467b48Spatrick using LiveVirtRegBitSet = SparseBitVector<128>;
3609467b48Spatrick #endif
3709467b48Spatrick 
3809467b48Spatrick /// Union of live intervals that are strong candidates for coalescing into a
3909467b48Spatrick /// single register (either physical or virtual depending on the context).  We
4009467b48Spatrick /// expect the constituent live intervals to be disjoint, although we may
4109467b48Spatrick /// eventually make exceptions to handle value-based interference.
4209467b48Spatrick class LiveIntervalUnion {
4309467b48Spatrick   // A set of live virtual register segments that supports fast insertion,
4409467b48Spatrick   // intersection, and removal.
4509467b48Spatrick   // Mapping SlotIndex intervals to virtual register numbers.
46*d415bd75Srobert   using LiveSegments = IntervalMap<SlotIndex, const LiveInterval *>;
4709467b48Spatrick 
4809467b48Spatrick public:
4909467b48Spatrick   // SegmentIter can advance to the next segment ordered by starting position
5009467b48Spatrick   // which may belong to a different live virtual register. We also must be able
5109467b48Spatrick   // to reach the current segment's containing virtual register.
5209467b48Spatrick   using SegmentIter = LiveSegments::iterator;
5309467b48Spatrick 
5409467b48Spatrick   /// Const version of SegmentIter.
5509467b48Spatrick   using ConstSegmentIter = LiveSegments::const_iterator;
5609467b48Spatrick 
5709467b48Spatrick   // LiveIntervalUnions share an external allocator.
5809467b48Spatrick   using Allocator = LiveSegments::Allocator;
5909467b48Spatrick 
6009467b48Spatrick private:
6109467b48Spatrick   unsigned Tag = 0;       // unique tag for current contents.
6209467b48Spatrick   LiveSegments Segments;  // union of virtual reg segments
6309467b48Spatrick 
6409467b48Spatrick public:
LiveIntervalUnion(Allocator & a)6509467b48Spatrick   explicit LiveIntervalUnion(Allocator &a) : Segments(a) {}
6609467b48Spatrick 
6709467b48Spatrick   // Iterate over all segments in the union of live virtual registers ordered
6809467b48Spatrick   // by their starting position.
begin()6909467b48Spatrick   SegmentIter begin() { return Segments.begin(); }
end()7009467b48Spatrick   SegmentIter end() { return Segments.end(); }
find(SlotIndex x)7109467b48Spatrick   SegmentIter find(SlotIndex x) { return Segments.find(x); }
begin()7209467b48Spatrick   ConstSegmentIter begin() const { return Segments.begin(); }
end()7309467b48Spatrick   ConstSegmentIter end() const { return Segments.end(); }
find(SlotIndex x)7409467b48Spatrick   ConstSegmentIter find(SlotIndex x) const { return Segments.find(x); }
7509467b48Spatrick 
empty()7609467b48Spatrick   bool empty() const { return Segments.empty(); }
startIndex()7709467b48Spatrick   SlotIndex startIndex() const { return Segments.start(); }
endIndex()7809467b48Spatrick   SlotIndex endIndex() const { return Segments.stop(); }
7909467b48Spatrick 
8009467b48Spatrick   // Provide public access to the underlying map to allow overlap iteration.
8109467b48Spatrick   using Map = LiveSegments;
getMap()8209467b48Spatrick   const Map &getMap() const { return Segments; }
8309467b48Spatrick 
8409467b48Spatrick   /// getTag - Return an opaque tag representing the current state of the union.
getTag()8509467b48Spatrick   unsigned getTag() const { return Tag; }
8609467b48Spatrick 
8709467b48Spatrick   /// changedSince - Return true if the union change since getTag returned tag.
changedSince(unsigned tag)8809467b48Spatrick   bool changedSince(unsigned tag) const { return tag != Tag; }
8909467b48Spatrick 
9009467b48Spatrick   // Add a live virtual register to this union and merge its segments.
91*d415bd75Srobert   void unify(const LiveInterval &VirtReg, const LiveRange &Range);
9209467b48Spatrick 
9309467b48Spatrick   // Remove a live virtual register's segments from this union.
94*d415bd75Srobert   void extract(const LiveInterval &VirtReg, const LiveRange &Range);
9509467b48Spatrick 
9609467b48Spatrick   // Remove all inserted virtual registers.
clear()9709467b48Spatrick   void clear() { Segments.clear(); ++Tag; }
9809467b48Spatrick 
9909467b48Spatrick   // Print union, using TRI to translate register names
10009467b48Spatrick   void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const;
10109467b48Spatrick 
10209467b48Spatrick #ifndef NDEBUG
10309467b48Spatrick   // Verify the live intervals in this union and add them to the visited set.
10409467b48Spatrick   void verify(LiveVirtRegBitSet& VisitedVRegs);
10509467b48Spatrick #endif
10609467b48Spatrick 
10773471bf0Spatrick   // Get any virtual register that is assign to this physical unit
108*d415bd75Srobert   const LiveInterval *getOneVReg() const;
10973471bf0Spatrick 
11009467b48Spatrick   /// Query interferences between a single live virtual register and a live
11109467b48Spatrick   /// interval union.
11209467b48Spatrick   class Query {
11309467b48Spatrick     const LiveIntervalUnion *LiveUnion = nullptr;
11409467b48Spatrick     const LiveRange *LR = nullptr;
11509467b48Spatrick     LiveRange::const_iterator LRI;  ///< current position in LR
11609467b48Spatrick     ConstSegmentIter LiveUnionI;    ///< current position in LiveUnion
117*d415bd75Srobert     SmallVector<const LiveInterval *, 4> InterferingVRegs;
11809467b48Spatrick     bool CheckedFirstInterference = false;
11909467b48Spatrick     bool SeenAllInterferences = false;
12009467b48Spatrick     unsigned Tag = 0;
12109467b48Spatrick     unsigned UserTag = 0;
12209467b48Spatrick 
123*d415bd75Srobert     // Count the virtual registers in this union that interfere with this
124*d415bd75Srobert     // query's live virtual register, up to maxInterferingRegs.
125*d415bd75Srobert     unsigned collectInterferingVRegs(unsigned MaxInterferingRegs);
126*d415bd75Srobert 
127*d415bd75Srobert     // Was this virtual register visited during collectInterferingVRegs?
128*d415bd75Srobert     bool isSeenInterference(const LiveInterval *VirtReg) const;
129*d415bd75Srobert 
13073471bf0Spatrick   public:
13173471bf0Spatrick     Query() = default;
Query(const LiveRange & LR,const LiveIntervalUnion & LIU)13273471bf0Spatrick     Query(const LiveRange &LR, const LiveIntervalUnion &LIU)
13373471bf0Spatrick         : LiveUnion(&LIU), LR(&LR) {}
13473471bf0Spatrick     Query(const Query &) = delete;
13573471bf0Spatrick     Query &operator=(const Query &) = delete;
13673471bf0Spatrick 
reset(unsigned NewUserTag,const LiveRange & NewLR,const LiveIntervalUnion & NewLiveUnion)13709467b48Spatrick     void reset(unsigned NewUserTag, const LiveRange &NewLR,
13809467b48Spatrick                const LiveIntervalUnion &NewLiveUnion) {
13909467b48Spatrick       LiveUnion = &NewLiveUnion;
14009467b48Spatrick       LR = &NewLR;
141*d415bd75Srobert       InterferingVRegs.clear();
14209467b48Spatrick       CheckedFirstInterference = false;
14309467b48Spatrick       SeenAllInterferences = false;
14409467b48Spatrick       Tag = NewLiveUnion.getTag();
14509467b48Spatrick       UserTag = NewUserTag;
14609467b48Spatrick     }
14709467b48Spatrick 
init(unsigned NewUserTag,const LiveRange & NewLR,const LiveIntervalUnion & NewLiveUnion)14809467b48Spatrick     void init(unsigned NewUserTag, const LiveRange &NewLR,
14909467b48Spatrick               const LiveIntervalUnion &NewLiveUnion) {
15009467b48Spatrick       if (UserTag == NewUserTag && LR == &NewLR && LiveUnion == &NewLiveUnion &&
15109467b48Spatrick           !NewLiveUnion.changedSince(Tag)) {
15209467b48Spatrick         // Retain cached results, e.g. firstInterference.
15309467b48Spatrick         return;
15409467b48Spatrick       }
15509467b48Spatrick       reset(NewUserTag, NewLR, NewLiveUnion);
15609467b48Spatrick     }
15709467b48Spatrick 
15809467b48Spatrick     // Does this live virtual register interfere with the union?
checkInterference()15909467b48Spatrick     bool checkInterference() { return collectInterferingVRegs(1); }
16009467b48Spatrick 
16109467b48Spatrick     // Vector generated by collectInterferingVRegs.
162*d415bd75Srobert     const SmallVectorImpl<const LiveInterval *> &interferingVRegs(
163*d415bd75Srobert         unsigned MaxInterferingRegs = std::numeric_limits<unsigned>::max()) {
164*d415bd75Srobert       if (!SeenAllInterferences || MaxInterferingRegs < InterferingVRegs.size())
165*d415bd75Srobert         collectInterferingVRegs(MaxInterferingRegs);
166*d415bd75Srobert       return InterferingVRegs;
16709467b48Spatrick     }
16809467b48Spatrick   };
16909467b48Spatrick 
17009467b48Spatrick   // Array of LiveIntervalUnions.
17109467b48Spatrick   class Array {
17209467b48Spatrick     unsigned Size = 0;
17309467b48Spatrick     LiveIntervalUnion *LIUs = nullptr;
17409467b48Spatrick 
17509467b48Spatrick   public:
17609467b48Spatrick     Array() = default;
~Array()17709467b48Spatrick     ~Array() { clear(); }
17809467b48Spatrick 
17909467b48Spatrick     // Initialize the array to have Size entries.
18009467b48Spatrick     // Reuse an existing allocation if the size matches.
18109467b48Spatrick     void init(LiveIntervalUnion::Allocator&, unsigned Size);
18209467b48Spatrick 
size()18309467b48Spatrick     unsigned size() const { return Size; }
18409467b48Spatrick 
18509467b48Spatrick     void clear();
18609467b48Spatrick 
18709467b48Spatrick     LiveIntervalUnion& operator[](unsigned idx) {
18809467b48Spatrick       assert(idx <  Size && "idx out of bounds");
18909467b48Spatrick       return LIUs[idx];
19009467b48Spatrick     }
19109467b48Spatrick 
19209467b48Spatrick     const LiveIntervalUnion& operator[](unsigned Idx) const {
19309467b48Spatrick       assert(Idx < Size && "Idx out of bounds");
19409467b48Spatrick       return LIUs[Idx];
19509467b48Spatrick     }
19609467b48Spatrick   };
19709467b48Spatrick };
19809467b48Spatrick 
19909467b48Spatrick } // end namespace llvm
20009467b48Spatrick 
20109467b48Spatrick #endif // LLVM_CODEGEN_LIVEINTERVALUNION_H
202