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