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