1f1933329SEugene Zelenko //===- InterferenceCache.h - Caching per-block interference ----*- C++ -*--===//
291cbcaf9SJakob Stoklund Olesen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
691cbcaf9SJakob Stoklund Olesen //
791cbcaf9SJakob Stoklund Olesen //===----------------------------------------------------------------------===//
891cbcaf9SJakob Stoklund Olesen //
996eebf0bSJakob Stoklund Olesen // InterferenceCache remembers per-block interference from LiveIntervalUnions,
1096eebf0bSJakob Stoklund Olesen // fixed RegUnit interference, and register masks.
1191cbcaf9SJakob Stoklund Olesen //
1291cbcaf9SJakob Stoklund Olesen //===----------------------------------------------------------------------===//
1391cbcaf9SJakob Stoklund Olesen 
14a7c40ef0SBenjamin Kramer #ifndef LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
15a7c40ef0SBenjamin Kramer #define LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
1691cbcaf9SJakob Stoklund Olesen 
17f1933329SEugene Zelenko #include "llvm/ADT/SmallVector.h"
18f1933329SEugene Zelenko #include "llvm/CodeGen/LiveInterval.h"
1926c9d70dSJakob Stoklund Olesen #include "llvm/CodeGen/LiveIntervalUnion.h"
20f1933329SEugene Zelenko #include "llvm/CodeGen/SlotIndexes.h"
21f1933329SEugene Zelenko #include "llvm/Support/Compiler.h"
22f1933329SEugene Zelenko #include <cassert>
23f1933329SEugene Zelenko #include <cstddef>
24f1933329SEugene Zelenko #include <cstdlib>
2591cbcaf9SJakob Stoklund Olesen 
2691cbcaf9SJakob Stoklund Olesen namespace llvm {
2791cbcaf9SJakob Stoklund Olesen 
28a16ae597SJakob Stoklund Olesen class LiveIntervals;
29f1933329SEugene Zelenko class MachineFunction;
30f1933329SEugene Zelenko class TargetRegisterInfo;
31a16ae597SJakob Stoklund Olesen 
32f4c20253SBenjamin Kramer class LLVM_LIBRARY_VISIBILITY InterferenceCache {
3391cbcaf9SJakob Stoklund Olesen   /// BlockInterference - information about the interference in a single basic
3491cbcaf9SJakob Stoklund Olesen   /// block.
3591cbcaf9SJakob Stoklund Olesen   struct BlockInterference {
36f1933329SEugene Zelenko     unsigned Tag = 0;
3791cbcaf9SJakob Stoklund Olesen     SlotIndex First;
3891cbcaf9SJakob Stoklund Olesen     SlotIndex Last;
39f1933329SEugene Zelenko 
40*3a8c5148SKazu Hirata     BlockInterference() = default;
4191cbcaf9SJakob Stoklund Olesen   };
4291cbcaf9SJakob Stoklund Olesen 
4391cbcaf9SJakob Stoklund Olesen   /// Entry - A cache entry containing interference information for all aliases
4491cbcaf9SJakob Stoklund Olesen   /// of PhysReg in all basic blocks.
4591cbcaf9SJakob Stoklund Olesen   class Entry {
4691cbcaf9SJakob Stoklund Olesen     /// PhysReg - The register currently represented.
47297655c1SMircea Trofin     MCRegister PhysReg = 0;
4891cbcaf9SJakob Stoklund Olesen 
4991cbcaf9SJakob Stoklund Olesen     /// Tag - Cache tag is changed when any of the underlying LiveIntervalUnions
5091cbcaf9SJakob Stoklund Olesen     /// change.
51f1933329SEugene Zelenko     unsigned Tag = 0;
5291cbcaf9SJakob Stoklund Olesen 
53a153ca58SJakob Stoklund Olesen     /// RefCount - The total number of Cursor instances referring to this Entry.
54f1933329SEugene Zelenko     unsigned RefCount = 0;
55a153ca58SJakob Stoklund Olesen 
564ad6c160SJakob Stoklund Olesen     /// MF - The current function.
574ad6c160SJakob Stoklund Olesen     MachineFunction *MF;
584ad6c160SJakob Stoklund Olesen 
5991cbcaf9SJakob Stoklund Olesen     /// Indexes - Mapping block numbers to SlotIndex ranges.
60f1933329SEugene Zelenko     SlotIndexes *Indexes = nullptr;
6191cbcaf9SJakob Stoklund Olesen 
62a16ae597SJakob Stoklund Olesen     /// LIS - Used for accessing register mask interference maps.
63f1933329SEugene Zelenko     LiveIntervals *LIS = nullptr;
64a16ae597SJakob Stoklund Olesen 
6591cbcaf9SJakob Stoklund Olesen     /// PrevPos - The previous position the iterators were moved to.
6691cbcaf9SJakob Stoklund Olesen     SlotIndex PrevPos;
6791cbcaf9SJakob Stoklund Olesen 
6896eebf0bSJakob Stoklund Olesen     /// RegUnitInfo - Information tracked about each RegUnit in PhysReg.
6996eebf0bSJakob Stoklund Olesen     /// When PrevPos is set, the iterators are valid as if advanceTo(PrevPos)
7096eebf0bSJakob Stoklund Olesen     /// had just been called.
7196eebf0bSJakob Stoklund Olesen     struct RegUnitInfo {
7296eebf0bSJakob Stoklund Olesen       /// Iterator pointing into the LiveIntervalUnion containing virtual
7396eebf0bSJakob Stoklund Olesen       /// register interference.
7496eebf0bSJakob Stoklund Olesen       LiveIntervalUnion::SegmentIter VirtI;
7591cbcaf9SJakob Stoklund Olesen 
7696eebf0bSJakob Stoklund Olesen       /// Tag of the LIU last time we looked.
7796eebf0bSJakob Stoklund Olesen       unsigned VirtTag;
7891cbcaf9SJakob Stoklund Olesen 
7996eebf0bSJakob Stoklund Olesen       /// Fixed interference in RegUnit.
80f1933329SEugene Zelenko       LiveRange *Fixed = nullptr;
8196eebf0bSJakob Stoklund Olesen 
8296eebf0bSJakob Stoklund Olesen       /// Iterator pointing into the fixed RegUnit interference.
8396eebf0bSJakob Stoklund Olesen       LiveInterval::iterator FixedI;
8496eebf0bSJakob Stoklund Olesen 
RegUnitInfoRegUnitInfo85f1933329SEugene Zelenko       RegUnitInfo(LiveIntervalUnion &LIU) : VirtTag(LIU.getTag()) {
8696eebf0bSJakob Stoklund Olesen         VirtI.setMap(LIU.getMap());
8796eebf0bSJakob Stoklund Olesen       }
8896eebf0bSJakob Stoklund Olesen     };
8996eebf0bSJakob Stoklund Olesen 
9096eebf0bSJakob Stoklund Olesen     /// Info for each RegUnit in PhysReg. It is very rare ofr a PHysReg to have
9196eebf0bSJakob Stoklund Olesen     /// more than 4 RegUnits.
9296eebf0bSJakob Stoklund Olesen     SmallVector<RegUnitInfo, 4> RegUnits;
9391cbcaf9SJakob Stoklund Olesen 
9491cbcaf9SJakob Stoklund Olesen     /// Blocks - Interference for each block in the function.
9591cbcaf9SJakob Stoklund Olesen     SmallVector<BlockInterference, 8> Blocks;
9691cbcaf9SJakob Stoklund Olesen 
9791cbcaf9SJakob Stoklund Olesen     /// update - Recompute Blocks[MBBNum]
9891cbcaf9SJakob Stoklund Olesen     void update(unsigned MBBNum);
9991cbcaf9SJakob Stoklund Olesen 
10091cbcaf9SJakob Stoklund Olesen   public:
101f1933329SEugene Zelenko     Entry() = default;
10291cbcaf9SJakob Stoklund Olesen 
clear(MachineFunction * mf,SlotIndexes * indexes,LiveIntervals * lis)103a16ae597SJakob Stoklund Olesen     void clear(MachineFunction *mf, SlotIndexes *indexes, LiveIntervals *lis) {
104a153ca58SJakob Stoklund Olesen       assert(!hasRefs() && "Cannot clear cache entry with references");
105297655c1SMircea Trofin       PhysReg = MCRegister::NoRegister;
1064ad6c160SJakob Stoklund Olesen       MF = mf;
10791cbcaf9SJakob Stoklund Olesen       Indexes = indexes;
108a16ae597SJakob Stoklund Olesen       LIS = lis;
10991cbcaf9SJakob Stoklund Olesen     }
11091cbcaf9SJakob Stoklund Olesen 
getPhysReg()111297655c1SMircea Trofin     MCRegister getPhysReg() const { return PhysReg; }
11291cbcaf9SJakob Stoklund Olesen 
addRef(int Delta)113a153ca58SJakob Stoklund Olesen     void addRef(int Delta) { RefCount += Delta; }
114a153ca58SJakob Stoklund Olesen 
hasRefs()115a153ca58SJakob Stoklund Olesen     bool hasRefs() const { return RefCount > 0; }
116a153ca58SJakob Stoklund Olesen 
11796eebf0bSJakob Stoklund Olesen     void revalidate(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
11891cbcaf9SJakob Stoklund Olesen 
11991cbcaf9SJakob Stoklund Olesen     /// valid - Return true if this is a valid entry for physReg.
12091cbcaf9SJakob Stoklund Olesen     bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
12191cbcaf9SJakob Stoklund Olesen 
12291cbcaf9SJakob Stoklund Olesen     /// reset - Initialize entry to represent physReg's aliases.
123297655c1SMircea Trofin     void reset(MCRegister physReg, LiveIntervalUnion *LIUArray,
124297655c1SMircea Trofin                const TargetRegisterInfo *TRI, const MachineFunction *MF);
12591cbcaf9SJakob Stoklund Olesen 
12691cbcaf9SJakob Stoklund Olesen     /// get - Return an up to date BlockInterference.
get(unsigned MBBNum)12791cbcaf9SJakob Stoklund Olesen     BlockInterference *get(unsigned MBBNum) {
12891cbcaf9SJakob Stoklund Olesen       if (Blocks[MBBNum].Tag != Tag)
12991cbcaf9SJakob Stoklund Olesen         update(MBBNum);
13091cbcaf9SJakob Stoklund Olesen       return &Blocks[MBBNum];
13191cbcaf9SJakob Stoklund Olesen     }
13291cbcaf9SJakob Stoklund Olesen   };
13391cbcaf9SJakob Stoklund Olesen 
13491cbcaf9SJakob Stoklund Olesen   // We don't keep a cache entry for every physical register, that would use too
13591cbcaf9SJakob Stoklund Olesen   // much memory. Instead, a fixed number of cache entries are used in a round-
13691cbcaf9SJakob Stoklund Olesen   // robin manner.
13791cbcaf9SJakob Stoklund Olesen   enum { CacheEntries = 32 };
13891cbcaf9SJakob Stoklund Olesen 
139f1933329SEugene Zelenko   const TargetRegisterInfo *TRI = nullptr;
140f1933329SEugene Zelenko   LiveIntervalUnion *LIUArray = nullptr;
141f1933329SEugene Zelenko   MachineFunction *MF = nullptr;
142f1933329SEugene Zelenko 
14391cbcaf9SJakob Stoklund Olesen   // Point to an entry for each physreg. The entry pointed to may not be up to
14491cbcaf9SJakob Stoklund Olesen   // date, and it may have been reused for a different physreg.
145f1933329SEugene Zelenko   unsigned char* PhysRegEntries = nullptr;
146f1933329SEugene Zelenko   size_t PhysRegEntriesCount = 0;
14791cbcaf9SJakob Stoklund Olesen 
14891cbcaf9SJakob Stoklund Olesen   // Next round-robin entry to be picked.
149f1933329SEugene Zelenko   unsigned RoundRobin = 0;
15091cbcaf9SJakob Stoklund Olesen 
15191cbcaf9SJakob Stoklund Olesen   // The actual cache entries.
15291cbcaf9SJakob Stoklund Olesen   Entry Entries[CacheEntries];
15391cbcaf9SJakob Stoklund Olesen 
15491cbcaf9SJakob Stoklund Olesen   // get - Get a valid entry for PhysReg.
155297655c1SMircea Trofin   Entry *get(MCRegister PhysReg);
15691cbcaf9SJakob Stoklund Olesen 
15791cbcaf9SJakob Stoklund Olesen public:
158f1933329SEugene Zelenko   InterferenceCache() = default;
1595eb10048SPuyan Lotfi 
~InterferenceCache()1605eb10048SPuyan Lotfi   ~InterferenceCache() {
1615eb10048SPuyan Lotfi     free(PhysRegEntries);
1625eb10048SPuyan Lotfi   }
1635eb10048SPuyan Lotfi 
1645eb10048SPuyan Lotfi   void reinitPhysRegEntries();
16591cbcaf9SJakob Stoklund Olesen 
16691cbcaf9SJakob Stoklund Olesen   /// init - Prepare cache for a new function.
167f1933329SEugene Zelenko   void init(MachineFunction *mf, LiveIntervalUnion *liuarray,
168f1933329SEugene Zelenko             SlotIndexes *indexes, LiveIntervals *lis,
169f1933329SEugene Zelenko             const TargetRegisterInfo *tri);
17091cbcaf9SJakob Stoklund Olesen 
171a153ca58SJakob Stoklund Olesen   /// getMaxCursors - Return the maximum number of concurrent cursors that can
172a153ca58SJakob Stoklund Olesen   /// be supported.
getMaxCursors()173a153ca58SJakob Stoklund Olesen   unsigned getMaxCursors() const { return CacheEntries; }
174a153ca58SJakob Stoklund Olesen 
17591cbcaf9SJakob Stoklund Olesen   /// Cursor - The primary query interface for the block interference cache.
17691cbcaf9SJakob Stoklund Olesen   class Cursor {
177f1933329SEugene Zelenko     Entry *CacheEntry = nullptr;
178f1933329SEugene Zelenko     const BlockInterference *Current = nullptr;
17957a3d084SBenjamin Kramer     static const BlockInterference NoInterference;
180a153ca58SJakob Stoklund Olesen 
setEntry(Entry * E)181a153ca58SJakob Stoklund Olesen     void setEntry(Entry *E) {
182ada08576SCraig Topper       Current = nullptr;
183a153ca58SJakob Stoklund Olesen       // Update reference counts. Nothing happens when RefCount reaches 0, so
184a153ca58SJakob Stoklund Olesen       // we don't have to check for E == CacheEntry etc.
185a153ca58SJakob Stoklund Olesen       if (CacheEntry)
186a153ca58SJakob Stoklund Olesen         CacheEntry->addRef(-1);
187a153ca58SJakob Stoklund Olesen       CacheEntry = E;
188a153ca58SJakob Stoklund Olesen       if (CacheEntry)
189a153ca58SJakob Stoklund Olesen         CacheEntry->addRef(+1);
190a153ca58SJakob Stoklund Olesen     }
191a153ca58SJakob Stoklund Olesen 
19291cbcaf9SJakob Stoklund Olesen   public:
193d7e99371SJakob Stoklund Olesen     /// Cursor - Create a dangling cursor.
194f1933329SEugene Zelenko     Cursor() = default;
195a153ca58SJakob Stoklund Olesen 
Cursor(const Cursor & O)196f1933329SEugene Zelenko     Cursor(const Cursor &O) {
197a153ca58SJakob Stoklund Olesen       setEntry(O.CacheEntry);
198a153ca58SJakob Stoklund Olesen     }
199a153ca58SJakob Stoklund Olesen 
200a153ca58SJakob Stoklund Olesen     Cursor &operator=(const Cursor &O) {
201a153ca58SJakob Stoklund Olesen       setEntry(O.CacheEntry);
202a153ca58SJakob Stoklund Olesen       return *this;
203a153ca58SJakob Stoklund Olesen     }
204d7e99371SJakob Stoklund Olesen 
~Cursor()205f1933329SEugene Zelenko     ~Cursor() { setEntry(nullptr); }
206f1933329SEugene Zelenko 
207d7e99371SJakob Stoklund Olesen     /// setPhysReg - Point this cursor to PhysReg's interference.
setPhysReg(InterferenceCache & Cache,MCRegister PhysReg)208297655c1SMircea Trofin     void setPhysReg(InterferenceCache &Cache, MCRegister PhysReg) {
209a153ca58SJakob Stoklund Olesen       // Release reference before getting a new one. That guarantees we can
210a153ca58SJakob Stoklund Olesen       // actually have CacheEntries live cursors.
211ada08576SCraig Topper       setEntry(nullptr);
212297655c1SMircea Trofin       if (PhysReg.isValid())
213a153ca58SJakob Stoklund Olesen         setEntry(Cache.get(PhysReg));
214d7e99371SJakob Stoklund Olesen     }
21591cbcaf9SJakob Stoklund Olesen 
21691cbcaf9SJakob Stoklund Olesen     /// moveTo - Move cursor to basic block MBBNum.
moveToBlock(unsigned MBBNum)21791cbcaf9SJakob Stoklund Olesen     void moveToBlock(unsigned MBBNum) {
218cacefc7dSJakob Stoklund Olesen       Current = CacheEntry ? CacheEntry->get(MBBNum) : &NoInterference;
21991cbcaf9SJakob Stoklund Olesen     }
22091cbcaf9SJakob Stoklund Olesen 
22191cbcaf9SJakob Stoklund Olesen     /// hasInterference - Return true if the current block has any interference.
hasInterference()22291cbcaf9SJakob Stoklund Olesen     bool hasInterference() {
22391cbcaf9SJakob Stoklund Olesen       return Current->First.isValid();
22491cbcaf9SJakob Stoklund Olesen     }
22591cbcaf9SJakob Stoklund Olesen 
22691cbcaf9SJakob Stoklund Olesen     /// first - Return the starting index of the first interfering range in the
22791cbcaf9SJakob Stoklund Olesen     /// current block.
first()22891cbcaf9SJakob Stoklund Olesen     SlotIndex first() {
22991cbcaf9SJakob Stoklund Olesen       return Current->First;
23091cbcaf9SJakob Stoklund Olesen     }
23191cbcaf9SJakob Stoklund Olesen 
23291cbcaf9SJakob Stoklund Olesen     /// last - Return the ending index of the last interfering range in the
23391cbcaf9SJakob Stoklund Olesen     /// current block.
last()23491cbcaf9SJakob Stoklund Olesen     SlotIndex last() {
23591cbcaf9SJakob Stoklund Olesen       return Current->Last;
23691cbcaf9SJakob Stoklund Olesen     }
23791cbcaf9SJakob Stoklund Olesen   };
23891cbcaf9SJakob Stoklund Olesen };
23991cbcaf9SJakob Stoklund Olesen 
240f1933329SEugene Zelenko } // end namespace llvm
24191cbcaf9SJakob Stoklund Olesen 
242f1933329SEugene Zelenko #endif // LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
243