xref: /aosp_15_r20/external/llvm/lib/CodeGen/InterferenceCache.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- InterferenceCache.h - Caching per-block interference ---*- C++ -*--===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // InterferenceCache remembers per-block interference from LiveIntervalUnions,
11*9880d681SAndroid Build Coastguard Worker // fixed RegUnit interference, and register masks.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
16*9880d681SAndroid Build Coastguard Worker #define LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LiveIntervalUnion.h"
19*9880d681SAndroid Build Coastguard Worker 
20*9880d681SAndroid Build Coastguard Worker namespace llvm {
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker class LiveIntervals;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker class LLVM_LIBRARY_VISIBILITY InterferenceCache {
25*9880d681SAndroid Build Coastguard Worker   const TargetRegisterInfo *TRI;
26*9880d681SAndroid Build Coastguard Worker   LiveIntervalUnion *LIUArray;
27*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker   /// BlockInterference - information about the interference in a single basic
30*9880d681SAndroid Build Coastguard Worker   /// block.
31*9880d681SAndroid Build Coastguard Worker   struct BlockInterference {
BlockInterferenceBlockInterference32*9880d681SAndroid Build Coastguard Worker     BlockInterference() : Tag(0) {}
33*9880d681SAndroid Build Coastguard Worker     unsigned Tag;
34*9880d681SAndroid Build Coastguard Worker     SlotIndex First;
35*9880d681SAndroid Build Coastguard Worker     SlotIndex Last;
36*9880d681SAndroid Build Coastguard Worker   };
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   /// Entry - A cache entry containing interference information for all aliases
39*9880d681SAndroid Build Coastguard Worker   /// of PhysReg in all basic blocks.
40*9880d681SAndroid Build Coastguard Worker   class Entry {
41*9880d681SAndroid Build Coastguard Worker     /// PhysReg - The register currently represented.
42*9880d681SAndroid Build Coastguard Worker     unsigned PhysReg;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker     /// Tag - Cache tag is changed when any of the underlying LiveIntervalUnions
45*9880d681SAndroid Build Coastguard Worker     /// change.
46*9880d681SAndroid Build Coastguard Worker     unsigned Tag;
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker     /// RefCount - The total number of Cursor instances referring to this Entry.
49*9880d681SAndroid Build Coastguard Worker     unsigned RefCount;
50*9880d681SAndroid Build Coastguard Worker 
51*9880d681SAndroid Build Coastguard Worker     /// MF - The current function.
52*9880d681SAndroid Build Coastguard Worker     MachineFunction *MF;
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker     /// Indexes - Mapping block numbers to SlotIndex ranges.
55*9880d681SAndroid Build Coastguard Worker     SlotIndexes *Indexes;
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker     /// LIS - Used for accessing register mask interference maps.
58*9880d681SAndroid Build Coastguard Worker     LiveIntervals *LIS;
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker     /// PrevPos - The previous position the iterators were moved to.
61*9880d681SAndroid Build Coastguard Worker     SlotIndex PrevPos;
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker     /// RegUnitInfo - Information tracked about each RegUnit in PhysReg.
64*9880d681SAndroid Build Coastguard Worker     /// When PrevPos is set, the iterators are valid as if advanceTo(PrevPos)
65*9880d681SAndroid Build Coastguard Worker     /// had just been called.
66*9880d681SAndroid Build Coastguard Worker     struct RegUnitInfo {
67*9880d681SAndroid Build Coastguard Worker       /// Iterator pointing into the LiveIntervalUnion containing virtual
68*9880d681SAndroid Build Coastguard Worker       /// register interference.
69*9880d681SAndroid Build Coastguard Worker       LiveIntervalUnion::SegmentIter VirtI;
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker       /// Tag of the LIU last time we looked.
72*9880d681SAndroid Build Coastguard Worker       unsigned VirtTag;
73*9880d681SAndroid Build Coastguard Worker 
74*9880d681SAndroid Build Coastguard Worker       /// Fixed interference in RegUnit.
75*9880d681SAndroid Build Coastguard Worker       LiveRange *Fixed;
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker       /// Iterator pointing into the fixed RegUnit interference.
78*9880d681SAndroid Build Coastguard Worker       LiveInterval::iterator FixedI;
79*9880d681SAndroid Build Coastguard Worker 
RegUnitInfoRegUnitInfo80*9880d681SAndroid Build Coastguard Worker       RegUnitInfo(LiveIntervalUnion &LIU)
81*9880d681SAndroid Build Coastguard Worker           : VirtTag(LIU.getTag()), Fixed(nullptr) {
82*9880d681SAndroid Build Coastguard Worker         VirtI.setMap(LIU.getMap());
83*9880d681SAndroid Build Coastguard Worker       }
84*9880d681SAndroid Build Coastguard Worker     };
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker     /// Info for each RegUnit in PhysReg. It is very rare ofr a PHysReg to have
87*9880d681SAndroid Build Coastguard Worker     /// more than 4 RegUnits.
88*9880d681SAndroid Build Coastguard Worker     SmallVector<RegUnitInfo, 4> RegUnits;
89*9880d681SAndroid Build Coastguard Worker 
90*9880d681SAndroid Build Coastguard Worker     /// Blocks - Interference for each block in the function.
91*9880d681SAndroid Build Coastguard Worker     SmallVector<BlockInterference, 8> Blocks;
92*9880d681SAndroid Build Coastguard Worker 
93*9880d681SAndroid Build Coastguard Worker     /// update - Recompute Blocks[MBBNum]
94*9880d681SAndroid Build Coastguard Worker     void update(unsigned MBBNum);
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker   public:
Entry()97*9880d681SAndroid Build Coastguard Worker     Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(nullptr), LIS(nullptr) {}
98*9880d681SAndroid Build Coastguard Worker 
clear(MachineFunction * mf,SlotIndexes * indexes,LiveIntervals * lis)99*9880d681SAndroid Build Coastguard Worker     void clear(MachineFunction *mf, SlotIndexes *indexes, LiveIntervals *lis) {
100*9880d681SAndroid Build Coastguard Worker       assert(!hasRefs() && "Cannot clear cache entry with references");
101*9880d681SAndroid Build Coastguard Worker       PhysReg = 0;
102*9880d681SAndroid Build Coastguard Worker       MF = mf;
103*9880d681SAndroid Build Coastguard Worker       Indexes = indexes;
104*9880d681SAndroid Build Coastguard Worker       LIS = lis;
105*9880d681SAndroid Build Coastguard Worker     }
106*9880d681SAndroid Build Coastguard Worker 
getPhysReg()107*9880d681SAndroid Build Coastguard Worker     unsigned getPhysReg() const { return PhysReg; }
108*9880d681SAndroid Build Coastguard Worker 
addRef(int Delta)109*9880d681SAndroid Build Coastguard Worker     void addRef(int Delta) { RefCount += Delta; }
110*9880d681SAndroid Build Coastguard Worker 
hasRefs()111*9880d681SAndroid Build Coastguard Worker     bool hasRefs() const { return RefCount > 0; }
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker     void revalidate(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker     /// valid - Return true if this is a valid entry for physReg.
116*9880d681SAndroid Build Coastguard Worker     bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker     /// reset - Initialize entry to represent physReg's aliases.
119*9880d681SAndroid Build Coastguard Worker     void reset(unsigned physReg,
120*9880d681SAndroid Build Coastguard Worker                LiveIntervalUnion *LIUArray,
121*9880d681SAndroid Build Coastguard Worker                const TargetRegisterInfo *TRI,
122*9880d681SAndroid Build Coastguard Worker                const MachineFunction *MF);
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker     /// get - Return an up to date BlockInterference.
get(unsigned MBBNum)125*9880d681SAndroid Build Coastguard Worker     BlockInterference *get(unsigned MBBNum) {
126*9880d681SAndroid Build Coastguard Worker       if (Blocks[MBBNum].Tag != Tag)
127*9880d681SAndroid Build Coastguard Worker         update(MBBNum);
128*9880d681SAndroid Build Coastguard Worker       return &Blocks[MBBNum];
129*9880d681SAndroid Build Coastguard Worker     }
130*9880d681SAndroid Build Coastguard Worker   };
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker   // We don't keep a cache entry for every physical register, that would use too
133*9880d681SAndroid Build Coastguard Worker   // much memory. Instead, a fixed number of cache entries are used in a round-
134*9880d681SAndroid Build Coastguard Worker   // robin manner.
135*9880d681SAndroid Build Coastguard Worker   enum { CacheEntries = 32 };
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker   // Point to an entry for each physreg. The entry pointed to may not be up to
138*9880d681SAndroid Build Coastguard Worker   // date, and it may have been reused for a different physreg.
139*9880d681SAndroid Build Coastguard Worker   unsigned char* PhysRegEntries;
140*9880d681SAndroid Build Coastguard Worker   size_t PhysRegEntriesCount;
141*9880d681SAndroid Build Coastguard Worker 
142*9880d681SAndroid Build Coastguard Worker   // Next round-robin entry to be picked.
143*9880d681SAndroid Build Coastguard Worker   unsigned RoundRobin;
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   // The actual cache entries.
146*9880d681SAndroid Build Coastguard Worker   Entry Entries[CacheEntries];
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker   // get - Get a valid entry for PhysReg.
149*9880d681SAndroid Build Coastguard Worker   Entry *get(unsigned PhysReg);
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker public:
InterferenceCache()152*9880d681SAndroid Build Coastguard Worker   InterferenceCache()
153*9880d681SAndroid Build Coastguard Worker     : TRI(nullptr), LIUArray(nullptr), MF(nullptr), PhysRegEntries(nullptr),
154*9880d681SAndroid Build Coastguard Worker       PhysRegEntriesCount(0), RoundRobin(0) {}
155*9880d681SAndroid Build Coastguard Worker 
~InterferenceCache()156*9880d681SAndroid Build Coastguard Worker   ~InterferenceCache() {
157*9880d681SAndroid Build Coastguard Worker     free(PhysRegEntries);
158*9880d681SAndroid Build Coastguard Worker   }
159*9880d681SAndroid Build Coastguard Worker 
160*9880d681SAndroid Build Coastguard Worker   void reinitPhysRegEntries();
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker   /// init - Prepare cache for a new function.
163*9880d681SAndroid Build Coastguard Worker   void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*, LiveIntervals*,
164*9880d681SAndroid Build Coastguard Worker             const TargetRegisterInfo *);
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker   /// getMaxCursors - Return the maximum number of concurrent cursors that can
167*9880d681SAndroid Build Coastguard Worker   /// be supported.
getMaxCursors()168*9880d681SAndroid Build Coastguard Worker   unsigned getMaxCursors() const { return CacheEntries; }
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   /// Cursor - The primary query interface for the block interference cache.
171*9880d681SAndroid Build Coastguard Worker   class Cursor {
172*9880d681SAndroid Build Coastguard Worker     Entry *CacheEntry;
173*9880d681SAndroid Build Coastguard Worker     const BlockInterference *Current;
174*9880d681SAndroid Build Coastguard Worker     static const BlockInterference NoInterference;
175*9880d681SAndroid Build Coastguard Worker 
setEntry(Entry * E)176*9880d681SAndroid Build Coastguard Worker     void setEntry(Entry *E) {
177*9880d681SAndroid Build Coastguard Worker       Current = nullptr;
178*9880d681SAndroid Build Coastguard Worker       // Update reference counts. Nothing happens when RefCount reaches 0, so
179*9880d681SAndroid Build Coastguard Worker       // we don't have to check for E == CacheEntry etc.
180*9880d681SAndroid Build Coastguard Worker       if (CacheEntry)
181*9880d681SAndroid Build Coastguard Worker         CacheEntry->addRef(-1);
182*9880d681SAndroid Build Coastguard Worker       CacheEntry = E;
183*9880d681SAndroid Build Coastguard Worker       if (CacheEntry)
184*9880d681SAndroid Build Coastguard Worker         CacheEntry->addRef(+1);
185*9880d681SAndroid Build Coastguard Worker     }
186*9880d681SAndroid Build Coastguard Worker 
187*9880d681SAndroid Build Coastguard Worker   public:
188*9880d681SAndroid Build Coastguard Worker     /// Cursor - Create a dangling cursor.
Cursor()189*9880d681SAndroid Build Coastguard Worker     Cursor() : CacheEntry(nullptr), Current(nullptr) {}
~Cursor()190*9880d681SAndroid Build Coastguard Worker     ~Cursor() { setEntry(nullptr); }
191*9880d681SAndroid Build Coastguard Worker 
Cursor(const Cursor & O)192*9880d681SAndroid Build Coastguard Worker     Cursor(const Cursor &O) : CacheEntry(nullptr), Current(nullptr) {
193*9880d681SAndroid Build Coastguard Worker       setEntry(O.CacheEntry);
194*9880d681SAndroid Build Coastguard Worker     }
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker     Cursor &operator=(const Cursor &O) {
197*9880d681SAndroid Build Coastguard Worker       setEntry(O.CacheEntry);
198*9880d681SAndroid Build Coastguard Worker       return *this;
199*9880d681SAndroid Build Coastguard Worker     }
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker     /// setPhysReg - Point this cursor to PhysReg's interference.
setPhysReg(InterferenceCache & Cache,unsigned PhysReg)202*9880d681SAndroid Build Coastguard Worker     void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) {
203*9880d681SAndroid Build Coastguard Worker       // Release reference before getting a new one. That guarantees we can
204*9880d681SAndroid Build Coastguard Worker       // actually have CacheEntries live cursors.
205*9880d681SAndroid Build Coastguard Worker       setEntry(nullptr);
206*9880d681SAndroid Build Coastguard Worker       if (PhysReg)
207*9880d681SAndroid Build Coastguard Worker         setEntry(Cache.get(PhysReg));
208*9880d681SAndroid Build Coastguard Worker     }
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker     /// moveTo - Move cursor to basic block MBBNum.
moveToBlock(unsigned MBBNum)211*9880d681SAndroid Build Coastguard Worker     void moveToBlock(unsigned MBBNum) {
212*9880d681SAndroid Build Coastguard Worker       Current = CacheEntry ? CacheEntry->get(MBBNum) : &NoInterference;
213*9880d681SAndroid Build Coastguard Worker     }
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker     /// hasInterference - Return true if the current block has any interference.
hasInterference()216*9880d681SAndroid Build Coastguard Worker     bool hasInterference() {
217*9880d681SAndroid Build Coastguard Worker       return Current->First.isValid();
218*9880d681SAndroid Build Coastguard Worker     }
219*9880d681SAndroid Build Coastguard Worker 
220*9880d681SAndroid Build Coastguard Worker     /// first - Return the starting index of the first interfering range in the
221*9880d681SAndroid Build Coastguard Worker     /// current block.
first()222*9880d681SAndroid Build Coastguard Worker     SlotIndex first() {
223*9880d681SAndroid Build Coastguard Worker       return Current->First;
224*9880d681SAndroid Build Coastguard Worker     }
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker     /// last - Return the ending index of the last interfering range in the
227*9880d681SAndroid Build Coastguard Worker     /// current block.
last()228*9880d681SAndroid Build Coastguard Worker     SlotIndex last() {
229*9880d681SAndroid Build Coastguard Worker       return Current->Last;
230*9880d681SAndroid Build Coastguard Worker     }
231*9880d681SAndroid Build Coastguard Worker   };
232*9880d681SAndroid Build Coastguard Worker 
233*9880d681SAndroid Build Coastguard Worker   friend class Cursor;
234*9880d681SAndroid Build Coastguard Worker };
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker } // namespace llvm
237*9880d681SAndroid Build Coastguard Worker 
238*9880d681SAndroid Build Coastguard Worker #endif
239