1dff0c46cSDimitry Andric //===-- InterferenceCache.cpp - Caching per-block interference ---------*--===// 23b0f4066SDimitry Andric // 33b0f4066SDimitry Andric // The LLVM Compiler Infrastructure 43b0f4066SDimitry Andric // 53b0f4066SDimitry Andric // This file is distributed under the University of Illinois Open Source 63b0f4066SDimitry Andric // License. See LICENSE.TXT for details. 73b0f4066SDimitry Andric // 83b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 93b0f4066SDimitry Andric // 103b0f4066SDimitry Andric // InterferenceCache remembers per-block interference in LiveIntervalUnions. 113b0f4066SDimitry Andric // 123b0f4066SDimitry Andric //===----------------------------------------------------------------------===// 133b0f4066SDimitry Andric 143b0f4066SDimitry Andric #include "InterferenceCache.h" 15dff0c46cSDimitry Andric #include "llvm/CodeGen/LiveIntervalAnalysis.h" 16139f7f9bSDimitry Andric #include "llvm/Support/ErrorHandling.h" 17139f7f9bSDimitry Andric #include "llvm/Target/TargetRegisterInfo.h" 183b0f4066SDimitry Andric 193b0f4066SDimitry Andric using namespace llvm; 203b0f4066SDimitry Andric 2191bc56edSDimitry Andric #define DEBUG_TYPE "regalloc" 2291bc56edSDimitry Andric 236122f3e6SDimitry Andric // Static member used for null interference cursors. 24ff0cc061SDimitry Andric const InterferenceCache::BlockInterference 25ff0cc061SDimitry Andric InterferenceCache::Cursor::NoInterference; 266122f3e6SDimitry Andric 2791bc56edSDimitry Andric // Initializes PhysRegEntries (instead of a SmallVector, PhysRegEntries is a 2891bc56edSDimitry Andric // buffer of size NumPhysRegs to speed up alloc/clear for targets with large 2991bc56edSDimitry Andric // reg files). Calloced memory is used for good form, and quites tools like 3091bc56edSDimitry Andric // Valgrind too, but zero initialized memory is not required by the algorithm: 3191bc56edSDimitry Andric // this is because PhysRegEntries works like a SparseSet and its entries are 3291bc56edSDimitry Andric // only valid when there is a corresponding CacheEntries assignment. There is 3391bc56edSDimitry Andric // also support for when pass managers are reused for targets with different 3491bc56edSDimitry Andric // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized. 3591bc56edSDimitry Andric void InterferenceCache::reinitPhysRegEntries() { 3691bc56edSDimitry Andric if (PhysRegEntriesCount == TRI->getNumRegs()) return; 3791bc56edSDimitry Andric free(PhysRegEntries); 3891bc56edSDimitry Andric PhysRegEntriesCount = TRI->getNumRegs(); 3991bc56edSDimitry Andric PhysRegEntries = (unsigned char*) 4091bc56edSDimitry Andric calloc(PhysRegEntriesCount, sizeof(unsigned char)); 4191bc56edSDimitry Andric } 4291bc56edSDimitry Andric 433b0f4066SDimitry Andric void InterferenceCache::init(MachineFunction *mf, 443b0f4066SDimitry Andric LiveIntervalUnion *liuarray, 453b0f4066SDimitry Andric SlotIndexes *indexes, 46dff0c46cSDimitry Andric LiveIntervals *lis, 473b0f4066SDimitry Andric const TargetRegisterInfo *tri) { 483b0f4066SDimitry Andric MF = mf; 493b0f4066SDimitry Andric LIUArray = liuarray; 503b0f4066SDimitry Andric TRI = tri; 5191bc56edSDimitry Andric reinitPhysRegEntries(); 523b0f4066SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) 53dff0c46cSDimitry Andric Entries[i].clear(mf, indexes, lis); 543b0f4066SDimitry Andric } 553b0f4066SDimitry Andric 563b0f4066SDimitry Andric InterferenceCache::Entry *InterferenceCache::get(unsigned PhysReg) { 573b0f4066SDimitry Andric unsigned E = PhysRegEntries[PhysReg]; 583b0f4066SDimitry Andric if (E < CacheEntries && Entries[E].getPhysReg() == PhysReg) { 593b0f4066SDimitry Andric if (!Entries[E].valid(LIUArray, TRI)) 607ae0e2c9SDimitry Andric Entries[E].revalidate(LIUArray, TRI); 613b0f4066SDimitry Andric return &Entries[E]; 623b0f4066SDimitry Andric } 633b0f4066SDimitry Andric // No valid entry exists, pick the next round-robin entry. 643b0f4066SDimitry Andric E = RoundRobin; 653b0f4066SDimitry Andric if (++RoundRobin == CacheEntries) 663b0f4066SDimitry Andric RoundRobin = 0; 6717a519f9SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) { 6817a519f9SDimitry Andric // Skip entries that are in use. 6917a519f9SDimitry Andric if (Entries[E].hasRefs()) { 7017a519f9SDimitry Andric if (++E == CacheEntries) 7117a519f9SDimitry Andric E = 0; 7217a519f9SDimitry Andric continue; 7317a519f9SDimitry Andric } 743b0f4066SDimitry Andric Entries[E].reset(PhysReg, LIUArray, TRI, MF); 753b0f4066SDimitry Andric PhysRegEntries[PhysReg] = E; 763b0f4066SDimitry Andric return &Entries[E]; 773b0f4066SDimitry Andric } 7817a519f9SDimitry Andric llvm_unreachable("Ran out of interference cache entries."); 7917a519f9SDimitry Andric } 803b0f4066SDimitry Andric 813b0f4066SDimitry Andric /// revalidate - LIU contents have changed, update tags. 827ae0e2c9SDimitry Andric void InterferenceCache::Entry::revalidate(LiveIntervalUnion *LIUArray, 837ae0e2c9SDimitry Andric const TargetRegisterInfo *TRI) { 843b0f4066SDimitry Andric // Invalidate all block entries. 853b0f4066SDimitry Andric ++Tag; 863b0f4066SDimitry Andric // Invalidate all iterators. 873b0f4066SDimitry Andric PrevPos = SlotIndex(); 887ae0e2c9SDimitry Andric unsigned i = 0; 897ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) 907ae0e2c9SDimitry Andric RegUnits[i].VirtTag = LIUArray[*Units].getTag(); 913b0f4066SDimitry Andric } 923b0f4066SDimitry Andric 933b0f4066SDimitry Andric void InterferenceCache::Entry::reset(unsigned physReg, 943b0f4066SDimitry Andric LiveIntervalUnion *LIUArray, 953b0f4066SDimitry Andric const TargetRegisterInfo *TRI, 963b0f4066SDimitry Andric const MachineFunction *MF) { 9717a519f9SDimitry Andric assert(!hasRefs() && "Cannot reset cache entry with references"); 983b0f4066SDimitry Andric // LIU's changed, invalidate cache. 993b0f4066SDimitry Andric ++Tag; 1003b0f4066SDimitry Andric PhysReg = physReg; 1013b0f4066SDimitry Andric Blocks.resize(MF->getNumBlockIDs()); 1023b0f4066SDimitry Andric 1033b0f4066SDimitry Andric // Reset iterators. 1043b0f4066SDimitry Andric PrevPos = SlotIndex(); 1057ae0e2c9SDimitry Andric RegUnits.clear(); 1067ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { 1077ae0e2c9SDimitry Andric RegUnits.push_back(LIUArray[*Units]); 1087ae0e2c9SDimitry Andric RegUnits.back().Fixed = &LIS->getRegUnit(*Units); 1097ae0e2c9SDimitry Andric } 1103b0f4066SDimitry Andric } 1113b0f4066SDimitry Andric 1123b0f4066SDimitry Andric bool InterferenceCache::Entry::valid(LiveIntervalUnion *LIUArray, 1133b0f4066SDimitry Andric const TargetRegisterInfo *TRI) { 1147ae0e2c9SDimitry Andric unsigned i = 0, e = RegUnits.size(); 1157ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) { 1167ae0e2c9SDimitry Andric if (i == e) 1173b0f4066SDimitry Andric return false; 1187ae0e2c9SDimitry Andric if (LIUArray[*Units].changedSince(RegUnits[i].VirtTag)) 1193b0f4066SDimitry Andric return false; 1203b0f4066SDimitry Andric } 1213b0f4066SDimitry Andric return i == e; 1223b0f4066SDimitry Andric } 1233b0f4066SDimitry Andric 1243b0f4066SDimitry Andric void InterferenceCache::Entry::update(unsigned MBBNum) { 1253b0f4066SDimitry Andric SlotIndex Start, Stop; 12691bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 1273b0f4066SDimitry Andric 1283b0f4066SDimitry Andric // Use advanceTo only when possible. 1293b0f4066SDimitry Andric if (PrevPos != Start) { 1307ae0e2c9SDimitry Andric if (!PrevPos.isValid() || Start < PrevPos) { 1317ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1327ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1337ae0e2c9SDimitry Andric RUI.VirtI.find(Start); 1347ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->find(Start); 1357ae0e2c9SDimitry Andric } 1367ae0e2c9SDimitry Andric } else { 1377ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1387ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1397ae0e2c9SDimitry Andric RUI.VirtI.advanceTo(Start); 1407ae0e2c9SDimitry Andric if (RUI.FixedI != RUI.Fixed->end()) 1417ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->advanceTo(RUI.FixedI, Start); 1427ae0e2c9SDimitry Andric } 1437ae0e2c9SDimitry Andric } 1443b0f4066SDimitry Andric PrevPos = Start; 1453b0f4066SDimitry Andric } 1463b0f4066SDimitry Andric 1473b0f4066SDimitry Andric MachineFunction::const_iterator MFI = MF->getBlockNumbered(MBBNum); 1483b0f4066SDimitry Andric BlockInterference *BI = &Blocks[MBBNum]; 149dff0c46cSDimitry Andric ArrayRef<SlotIndex> RegMaskSlots; 150dff0c46cSDimitry Andric ArrayRef<const uint32_t*> RegMaskBits; 1513b0f4066SDimitry Andric for (;;) { 1523b0f4066SDimitry Andric BI->Tag = Tag; 1533b0f4066SDimitry Andric BI->First = BI->Last = SlotIndex(); 1543b0f4066SDimitry Andric 1557ae0e2c9SDimitry Andric // Check for first interference from virtregs. 1567ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1577ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 1583b0f4066SDimitry Andric if (!I.valid()) 1593b0f4066SDimitry Andric continue; 1603b0f4066SDimitry Andric SlotIndex StartI = I.start(); 1613b0f4066SDimitry Andric if (StartI >= Stop) 1623b0f4066SDimitry Andric continue; 1633b0f4066SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1643b0f4066SDimitry Andric BI->First = StartI; 1653b0f4066SDimitry Andric } 1663b0f4066SDimitry Andric 1677ae0e2c9SDimitry Andric // Same thing for fixed interference. 1687ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1697ae0e2c9SDimitry Andric LiveInterval::const_iterator I = RegUnits[i].FixedI; 1707ae0e2c9SDimitry Andric LiveInterval::const_iterator E = RegUnits[i].Fixed->end(); 1717ae0e2c9SDimitry Andric if (I == E) 1727ae0e2c9SDimitry Andric continue; 1737ae0e2c9SDimitry Andric SlotIndex StartI = I->start; 1747ae0e2c9SDimitry Andric if (StartI >= Stop) 1757ae0e2c9SDimitry Andric continue; 1767ae0e2c9SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1777ae0e2c9SDimitry Andric BI->First = StartI; 1787ae0e2c9SDimitry Andric } 1797ae0e2c9SDimitry Andric 180dff0c46cSDimitry Andric // Also check for register mask interference. 181dff0c46cSDimitry Andric RegMaskSlots = LIS->getRegMaskSlotsInBlock(MBBNum); 182dff0c46cSDimitry Andric RegMaskBits = LIS->getRegMaskBitsInBlock(MBBNum); 183dff0c46cSDimitry Andric SlotIndex Limit = BI->First.isValid() ? BI->First : Stop; 184dff0c46cSDimitry Andric for (unsigned i = 0, e = RegMaskSlots.size(); 185dff0c46cSDimitry Andric i != e && RegMaskSlots[i] < Limit; ++i) 186dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i], PhysReg)) { 187dff0c46cSDimitry Andric // Register mask i clobbers PhysReg before the LIU interference. 188dff0c46cSDimitry Andric BI->First = RegMaskSlots[i]; 189dff0c46cSDimitry Andric break; 190dff0c46cSDimitry Andric } 191dff0c46cSDimitry Andric 1923b0f4066SDimitry Andric PrevPos = Stop; 1933b0f4066SDimitry Andric if (BI->First.isValid()) 1943b0f4066SDimitry Andric break; 1953b0f4066SDimitry Andric 1963b0f4066SDimitry Andric // No interference in this block? Go ahead and precompute the next block. 1973b0f4066SDimitry Andric if (++MFI == MF->end()) 1983b0f4066SDimitry Andric return; 1993b0f4066SDimitry Andric MBBNum = MFI->getNumber(); 2003b0f4066SDimitry Andric BI = &Blocks[MBBNum]; 2013b0f4066SDimitry Andric if (BI->Tag == Tag) 2023b0f4066SDimitry Andric return; 20391bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 2043b0f4066SDimitry Andric } 2053b0f4066SDimitry Andric 2063b0f4066SDimitry Andric // Check for last interference in block. 2077ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2087ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 2093b0f4066SDimitry Andric if (!I.valid() || I.start() >= Stop) 2103b0f4066SDimitry Andric continue; 2113b0f4066SDimitry Andric I.advanceTo(Stop); 2123b0f4066SDimitry Andric bool Backup = !I.valid() || I.start() >= Stop; 2133b0f4066SDimitry Andric if (Backup) 2143b0f4066SDimitry Andric --I; 2153b0f4066SDimitry Andric SlotIndex StopI = I.stop(); 2163b0f4066SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2173b0f4066SDimitry Andric BI->Last = StopI; 2183b0f4066SDimitry Andric if (Backup) 2193b0f4066SDimitry Andric ++I; 2203b0f4066SDimitry Andric } 221dff0c46cSDimitry Andric 2227ae0e2c9SDimitry Andric // Fixed interference. 2237ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2247ae0e2c9SDimitry Andric LiveInterval::iterator &I = RegUnits[i].FixedI; 225f785676fSDimitry Andric LiveRange *LR = RegUnits[i].Fixed; 226f785676fSDimitry Andric if (I == LR->end() || I->start >= Stop) 2277ae0e2c9SDimitry Andric continue; 228f785676fSDimitry Andric I = LR->advanceTo(I, Stop); 229f785676fSDimitry Andric bool Backup = I == LR->end() || I->start >= Stop; 2307ae0e2c9SDimitry Andric if (Backup) 2317ae0e2c9SDimitry Andric --I; 2327ae0e2c9SDimitry Andric SlotIndex StopI = I->end; 2337ae0e2c9SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2347ae0e2c9SDimitry Andric BI->Last = StopI; 2357ae0e2c9SDimitry Andric if (Backup) 2367ae0e2c9SDimitry Andric ++I; 2377ae0e2c9SDimitry Andric } 2387ae0e2c9SDimitry Andric 239dff0c46cSDimitry Andric // Also check for register mask interference. 240dff0c46cSDimitry Andric SlotIndex Limit = BI->Last.isValid() ? BI->Last : Start; 241dff0c46cSDimitry Andric for (unsigned i = RegMaskSlots.size(); 242dff0c46cSDimitry Andric i && RegMaskSlots[i-1].getDeadSlot() > Limit; --i) 243dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i-1], PhysReg)) { 244dff0c46cSDimitry Andric // Register mask i-1 clobbers PhysReg after the LIU interference. 245dff0c46cSDimitry Andric // Model the regmask clobber as a dead def. 246dff0c46cSDimitry Andric BI->Last = RegMaskSlots[i-1].getDeadSlot(); 247dff0c46cSDimitry Andric break; 248dff0c46cSDimitry Andric } 2493b0f4066SDimitry Andric } 250