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. 246122f3e6SDimitry Andric InterferenceCache::BlockInterference InterferenceCache::Cursor::NoInterference; 256122f3e6SDimitry Andric 2691bc56edSDimitry Andric // Initializes PhysRegEntries (instead of a SmallVector, PhysRegEntries is a 2791bc56edSDimitry Andric // buffer of size NumPhysRegs to speed up alloc/clear for targets with large 2891bc56edSDimitry Andric // reg files). Calloced memory is used for good form, and quites tools like 2991bc56edSDimitry Andric // Valgrind too, but zero initialized memory is not required by the algorithm: 3091bc56edSDimitry Andric // this is because PhysRegEntries works like a SparseSet and its entries are 3191bc56edSDimitry Andric // only valid when there is a corresponding CacheEntries assignment. There is 3291bc56edSDimitry Andric // also support for when pass managers are reused for targets with different 3391bc56edSDimitry Andric // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized. 3491bc56edSDimitry Andric void InterferenceCache::reinitPhysRegEntries() { 3591bc56edSDimitry Andric if (PhysRegEntriesCount == TRI->getNumRegs()) return; 3691bc56edSDimitry Andric free(PhysRegEntries); 3791bc56edSDimitry Andric PhysRegEntriesCount = TRI->getNumRegs(); 3891bc56edSDimitry Andric PhysRegEntries = (unsigned char*) 3991bc56edSDimitry Andric calloc(PhysRegEntriesCount, sizeof(unsigned char)); 4091bc56edSDimitry Andric } 4191bc56edSDimitry Andric 423b0f4066SDimitry Andric void InterferenceCache::init(MachineFunction *mf, 433b0f4066SDimitry Andric LiveIntervalUnion *liuarray, 443b0f4066SDimitry Andric SlotIndexes *indexes, 45dff0c46cSDimitry Andric LiveIntervals *lis, 463b0f4066SDimitry Andric const TargetRegisterInfo *tri) { 473b0f4066SDimitry Andric MF = mf; 483b0f4066SDimitry Andric LIUArray = liuarray; 493b0f4066SDimitry Andric TRI = tri; 5091bc56edSDimitry Andric reinitPhysRegEntries(); 513b0f4066SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) 52dff0c46cSDimitry Andric Entries[i].clear(mf, indexes, lis); 533b0f4066SDimitry Andric } 543b0f4066SDimitry Andric 553b0f4066SDimitry Andric InterferenceCache::Entry *InterferenceCache::get(unsigned PhysReg) { 563b0f4066SDimitry Andric unsigned E = PhysRegEntries[PhysReg]; 573b0f4066SDimitry Andric if (E < CacheEntries && Entries[E].getPhysReg() == PhysReg) { 583b0f4066SDimitry Andric if (!Entries[E].valid(LIUArray, TRI)) 597ae0e2c9SDimitry Andric Entries[E].revalidate(LIUArray, TRI); 603b0f4066SDimitry Andric return &Entries[E]; 613b0f4066SDimitry Andric } 623b0f4066SDimitry Andric // No valid entry exists, pick the next round-robin entry. 633b0f4066SDimitry Andric E = RoundRobin; 643b0f4066SDimitry Andric if (++RoundRobin == CacheEntries) 653b0f4066SDimitry Andric RoundRobin = 0; 6617a519f9SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) { 6717a519f9SDimitry Andric // Skip entries that are in use. 6817a519f9SDimitry Andric if (Entries[E].hasRefs()) { 6917a519f9SDimitry Andric if (++E == CacheEntries) 7017a519f9SDimitry Andric E = 0; 7117a519f9SDimitry Andric continue; 7217a519f9SDimitry Andric } 733b0f4066SDimitry Andric Entries[E].reset(PhysReg, LIUArray, TRI, MF); 743b0f4066SDimitry Andric PhysRegEntries[PhysReg] = E; 753b0f4066SDimitry Andric return &Entries[E]; 763b0f4066SDimitry Andric } 7717a519f9SDimitry Andric llvm_unreachable("Ran out of interference cache entries."); 7817a519f9SDimitry Andric } 793b0f4066SDimitry Andric 803b0f4066SDimitry Andric /// revalidate - LIU contents have changed, update tags. 817ae0e2c9SDimitry Andric void InterferenceCache::Entry::revalidate(LiveIntervalUnion *LIUArray, 827ae0e2c9SDimitry Andric const TargetRegisterInfo *TRI) { 833b0f4066SDimitry Andric // Invalidate all block entries. 843b0f4066SDimitry Andric ++Tag; 853b0f4066SDimitry Andric // Invalidate all iterators. 863b0f4066SDimitry Andric PrevPos = SlotIndex(); 877ae0e2c9SDimitry Andric unsigned i = 0; 887ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) 897ae0e2c9SDimitry Andric RegUnits[i].VirtTag = LIUArray[*Units].getTag(); 903b0f4066SDimitry Andric } 913b0f4066SDimitry Andric 923b0f4066SDimitry Andric void InterferenceCache::Entry::reset(unsigned physReg, 933b0f4066SDimitry Andric LiveIntervalUnion *LIUArray, 943b0f4066SDimitry Andric const TargetRegisterInfo *TRI, 953b0f4066SDimitry Andric const MachineFunction *MF) { 9617a519f9SDimitry Andric assert(!hasRefs() && "Cannot reset cache entry with references"); 973b0f4066SDimitry Andric // LIU's changed, invalidate cache. 983b0f4066SDimitry Andric ++Tag; 993b0f4066SDimitry Andric PhysReg = physReg; 1003b0f4066SDimitry Andric Blocks.resize(MF->getNumBlockIDs()); 1013b0f4066SDimitry Andric 1023b0f4066SDimitry Andric // Reset iterators. 1033b0f4066SDimitry Andric PrevPos = SlotIndex(); 1047ae0e2c9SDimitry Andric RegUnits.clear(); 1057ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { 1067ae0e2c9SDimitry Andric RegUnits.push_back(LIUArray[*Units]); 1077ae0e2c9SDimitry Andric RegUnits.back().Fixed = &LIS->getRegUnit(*Units); 1087ae0e2c9SDimitry Andric } 1093b0f4066SDimitry Andric } 1103b0f4066SDimitry Andric 1113b0f4066SDimitry Andric bool InterferenceCache::Entry::valid(LiveIntervalUnion *LIUArray, 1123b0f4066SDimitry Andric const TargetRegisterInfo *TRI) { 1137ae0e2c9SDimitry Andric unsigned i = 0, e = RegUnits.size(); 1147ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) { 1157ae0e2c9SDimitry Andric if (i == e) 1163b0f4066SDimitry Andric return false; 1177ae0e2c9SDimitry Andric if (LIUArray[*Units].changedSince(RegUnits[i].VirtTag)) 1183b0f4066SDimitry Andric return false; 1193b0f4066SDimitry Andric } 1203b0f4066SDimitry Andric return i == e; 1213b0f4066SDimitry Andric } 1223b0f4066SDimitry Andric 1233b0f4066SDimitry Andric void InterferenceCache::Entry::update(unsigned MBBNum) { 1243b0f4066SDimitry Andric SlotIndex Start, Stop; 12591bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 1263b0f4066SDimitry Andric 1273b0f4066SDimitry Andric // Use advanceTo only when possible. 1283b0f4066SDimitry Andric if (PrevPos != Start) { 1297ae0e2c9SDimitry Andric if (!PrevPos.isValid() || Start < PrevPos) { 1307ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1317ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1327ae0e2c9SDimitry Andric RUI.VirtI.find(Start); 1337ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->find(Start); 1347ae0e2c9SDimitry Andric } 1357ae0e2c9SDimitry Andric } else { 1367ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1377ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1387ae0e2c9SDimitry Andric RUI.VirtI.advanceTo(Start); 1397ae0e2c9SDimitry Andric if (RUI.FixedI != RUI.Fixed->end()) 1407ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->advanceTo(RUI.FixedI, Start); 1417ae0e2c9SDimitry Andric } 1427ae0e2c9SDimitry Andric } 1433b0f4066SDimitry Andric PrevPos = Start; 1443b0f4066SDimitry Andric } 1453b0f4066SDimitry Andric 1463b0f4066SDimitry Andric MachineFunction::const_iterator MFI = MF->getBlockNumbered(MBBNum); 1473b0f4066SDimitry Andric BlockInterference *BI = &Blocks[MBBNum]; 148dff0c46cSDimitry Andric ArrayRef<SlotIndex> RegMaskSlots; 149dff0c46cSDimitry Andric ArrayRef<const uint32_t*> RegMaskBits; 1503b0f4066SDimitry Andric for (;;) { 1513b0f4066SDimitry Andric BI->Tag = Tag; 1523b0f4066SDimitry Andric BI->First = BI->Last = SlotIndex(); 1533b0f4066SDimitry Andric 1547ae0e2c9SDimitry Andric // Check for first interference from virtregs. 1557ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1567ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 1573b0f4066SDimitry Andric if (!I.valid()) 1583b0f4066SDimitry Andric continue; 1593b0f4066SDimitry Andric SlotIndex StartI = I.start(); 1603b0f4066SDimitry Andric if (StartI >= Stop) 1613b0f4066SDimitry Andric continue; 1623b0f4066SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1633b0f4066SDimitry Andric BI->First = StartI; 1643b0f4066SDimitry Andric } 1653b0f4066SDimitry Andric 1667ae0e2c9SDimitry Andric // Same thing for fixed interference. 1677ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1687ae0e2c9SDimitry Andric LiveInterval::const_iterator I = RegUnits[i].FixedI; 1697ae0e2c9SDimitry Andric LiveInterval::const_iterator E = RegUnits[i].Fixed->end(); 1707ae0e2c9SDimitry Andric if (I == E) 1717ae0e2c9SDimitry Andric continue; 1727ae0e2c9SDimitry Andric SlotIndex StartI = I->start; 1737ae0e2c9SDimitry Andric if (StartI >= Stop) 1747ae0e2c9SDimitry Andric continue; 1757ae0e2c9SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1767ae0e2c9SDimitry Andric BI->First = StartI; 1777ae0e2c9SDimitry Andric } 1787ae0e2c9SDimitry Andric 179dff0c46cSDimitry Andric // Also check for register mask interference. 180dff0c46cSDimitry Andric RegMaskSlots = LIS->getRegMaskSlotsInBlock(MBBNum); 181dff0c46cSDimitry Andric RegMaskBits = LIS->getRegMaskBitsInBlock(MBBNum); 182dff0c46cSDimitry Andric SlotIndex Limit = BI->First.isValid() ? BI->First : Stop; 183dff0c46cSDimitry Andric for (unsigned i = 0, e = RegMaskSlots.size(); 184dff0c46cSDimitry Andric i != e && RegMaskSlots[i] < Limit; ++i) 185dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i], PhysReg)) { 186dff0c46cSDimitry Andric // Register mask i clobbers PhysReg before the LIU interference. 187dff0c46cSDimitry Andric BI->First = RegMaskSlots[i]; 188dff0c46cSDimitry Andric break; 189dff0c46cSDimitry Andric } 190dff0c46cSDimitry Andric 1913b0f4066SDimitry Andric PrevPos = Stop; 1923b0f4066SDimitry Andric if (BI->First.isValid()) 1933b0f4066SDimitry Andric break; 1943b0f4066SDimitry Andric 1953b0f4066SDimitry Andric // No interference in this block? Go ahead and precompute the next block. 1963b0f4066SDimitry Andric if (++MFI == MF->end()) 1973b0f4066SDimitry Andric return; 1983b0f4066SDimitry Andric MBBNum = MFI->getNumber(); 1993b0f4066SDimitry Andric BI = &Blocks[MBBNum]; 2003b0f4066SDimitry Andric if (BI->Tag == Tag) 2013b0f4066SDimitry Andric return; 20291bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 2033b0f4066SDimitry Andric } 2043b0f4066SDimitry Andric 2053b0f4066SDimitry Andric // Check for last interference in block. 2067ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2077ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 2083b0f4066SDimitry Andric if (!I.valid() || I.start() >= Stop) 2093b0f4066SDimitry Andric continue; 2103b0f4066SDimitry Andric I.advanceTo(Stop); 2113b0f4066SDimitry Andric bool Backup = !I.valid() || I.start() >= Stop; 2123b0f4066SDimitry Andric if (Backup) 2133b0f4066SDimitry Andric --I; 2143b0f4066SDimitry Andric SlotIndex StopI = I.stop(); 2153b0f4066SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2163b0f4066SDimitry Andric BI->Last = StopI; 2173b0f4066SDimitry Andric if (Backup) 2183b0f4066SDimitry Andric ++I; 2193b0f4066SDimitry Andric } 220dff0c46cSDimitry Andric 2217ae0e2c9SDimitry Andric // Fixed interference. 2227ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2237ae0e2c9SDimitry Andric LiveInterval::iterator &I = RegUnits[i].FixedI; 224f785676fSDimitry Andric LiveRange *LR = RegUnits[i].Fixed; 225f785676fSDimitry Andric if (I == LR->end() || I->start >= Stop) 2267ae0e2c9SDimitry Andric continue; 227f785676fSDimitry Andric I = LR->advanceTo(I, Stop); 228f785676fSDimitry Andric bool Backup = I == LR->end() || I->start >= Stop; 2297ae0e2c9SDimitry Andric if (Backup) 2307ae0e2c9SDimitry Andric --I; 2317ae0e2c9SDimitry Andric SlotIndex StopI = I->end; 2327ae0e2c9SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2337ae0e2c9SDimitry Andric BI->Last = StopI; 2347ae0e2c9SDimitry Andric if (Backup) 2357ae0e2c9SDimitry Andric ++I; 2367ae0e2c9SDimitry Andric } 2377ae0e2c9SDimitry Andric 238dff0c46cSDimitry Andric // Also check for register mask interference. 239dff0c46cSDimitry Andric SlotIndex Limit = BI->Last.isValid() ? BI->Last : Start; 240dff0c46cSDimitry Andric for (unsigned i = RegMaskSlots.size(); 241dff0c46cSDimitry Andric i && RegMaskSlots[i-1].getDeadSlot() > Limit; --i) 242dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i-1], PhysReg)) { 243dff0c46cSDimitry Andric // Register mask i-1 clobbers PhysReg after the LIU interference. 244dff0c46cSDimitry Andric // Model the regmask clobber as a dead def. 245dff0c46cSDimitry Andric BI->Last = RegMaskSlots[i-1].getDeadSlot(); 246dff0c46cSDimitry Andric break; 247dff0c46cSDimitry Andric } 2483b0f4066SDimitry Andric } 249