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