12cab237bSDimitry 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" 152cab237bSDimitry Andric #include "llvm/ADT/ArrayRef.h" 162cab237bSDimitry Andric #include "llvm/CodeGen/LiveInterval.h" 172cab237bSDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h" 182cab237bSDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 192cab237bSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 202cab237bSDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 212cab237bSDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 222cab237bSDimitry Andric #include "llvm/CodeGen/SlotIndexes.h" 232cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 242cab237bSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 25139f7f9bSDimitry Andric #include "llvm/Support/ErrorHandling.h" 262cab237bSDimitry Andric #include <cassert> 272cab237bSDimitry Andric #include <cstdint> 282cab237bSDimitry Andric #include <cstdlib> 292cab237bSDimitry Andric #include <tuple> 303b0f4066SDimitry Andric 313b0f4066SDimitry Andric using namespace llvm; 323b0f4066SDimitry Andric 3391bc56edSDimitry Andric #define DEBUG_TYPE "regalloc" 3491bc56edSDimitry Andric 356122f3e6SDimitry Andric // Static member used for null interference cursors. 36ff0cc061SDimitry Andric const InterferenceCache::BlockInterference 37ff0cc061SDimitry Andric InterferenceCache::Cursor::NoInterference; 386122f3e6SDimitry Andric 3991bc56edSDimitry Andric // Initializes PhysRegEntries (instead of a SmallVector, PhysRegEntries is a 4091bc56edSDimitry Andric // buffer of size NumPhysRegs to speed up alloc/clear for targets with large 4191bc56edSDimitry Andric // reg files). Calloced memory is used for good form, and quites tools like 4291bc56edSDimitry Andric // Valgrind too, but zero initialized memory is not required by the algorithm: 4391bc56edSDimitry Andric // this is because PhysRegEntries works like a SparseSet and its entries are 4491bc56edSDimitry Andric // only valid when there is a corresponding CacheEntries assignment. There is 4591bc56edSDimitry Andric // also support for when pass managers are reused for targets with different 4691bc56edSDimitry Andric // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized. 4791bc56edSDimitry Andric void InterferenceCache::reinitPhysRegEntries() { 4891bc56edSDimitry Andric if (PhysRegEntriesCount == TRI->getNumRegs()) return; 4991bc56edSDimitry Andric free(PhysRegEntries); 5091bc56edSDimitry Andric PhysRegEntriesCount = TRI->getNumRegs(); 5191bc56edSDimitry Andric PhysRegEntries = (unsigned char*) 5291bc56edSDimitry Andric calloc(PhysRegEntriesCount, sizeof(unsigned char)); 5391bc56edSDimitry Andric } 5491bc56edSDimitry Andric 553b0f4066SDimitry Andric void InterferenceCache::init(MachineFunction *mf, 563b0f4066SDimitry Andric LiveIntervalUnion *liuarray, 573b0f4066SDimitry Andric SlotIndexes *indexes, 58dff0c46cSDimitry Andric LiveIntervals *lis, 593b0f4066SDimitry Andric const TargetRegisterInfo *tri) { 603b0f4066SDimitry Andric MF = mf; 613b0f4066SDimitry Andric LIUArray = liuarray; 623b0f4066SDimitry Andric TRI = tri; 6391bc56edSDimitry Andric reinitPhysRegEntries(); 643b0f4066SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) 65dff0c46cSDimitry Andric Entries[i].clear(mf, indexes, lis); 663b0f4066SDimitry Andric } 673b0f4066SDimitry Andric 683b0f4066SDimitry Andric InterferenceCache::Entry *InterferenceCache::get(unsigned PhysReg) { 693b0f4066SDimitry Andric unsigned E = PhysRegEntries[PhysReg]; 703b0f4066SDimitry Andric if (E < CacheEntries && Entries[E].getPhysReg() == PhysReg) { 713b0f4066SDimitry Andric if (!Entries[E].valid(LIUArray, TRI)) 727ae0e2c9SDimitry Andric Entries[E].revalidate(LIUArray, TRI); 733b0f4066SDimitry Andric return &Entries[E]; 743b0f4066SDimitry Andric } 753b0f4066SDimitry Andric // No valid entry exists, pick the next round-robin entry. 763b0f4066SDimitry Andric E = RoundRobin; 773b0f4066SDimitry Andric if (++RoundRobin == CacheEntries) 783b0f4066SDimitry Andric RoundRobin = 0; 7917a519f9SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) { 8017a519f9SDimitry Andric // Skip entries that are in use. 8117a519f9SDimitry Andric if (Entries[E].hasRefs()) { 8217a519f9SDimitry Andric if (++E == CacheEntries) 8317a519f9SDimitry Andric E = 0; 8417a519f9SDimitry Andric continue; 8517a519f9SDimitry Andric } 863b0f4066SDimitry Andric Entries[E].reset(PhysReg, LIUArray, TRI, MF); 873b0f4066SDimitry Andric PhysRegEntries[PhysReg] = E; 883b0f4066SDimitry Andric return &Entries[E]; 893b0f4066SDimitry Andric } 9017a519f9SDimitry Andric llvm_unreachable("Ran out of interference cache entries."); 9117a519f9SDimitry Andric } 923b0f4066SDimitry Andric 933b0f4066SDimitry Andric /// revalidate - LIU contents have changed, update tags. 947ae0e2c9SDimitry Andric void InterferenceCache::Entry::revalidate(LiveIntervalUnion *LIUArray, 957ae0e2c9SDimitry Andric const TargetRegisterInfo *TRI) { 963b0f4066SDimitry Andric // Invalidate all block entries. 973b0f4066SDimitry Andric ++Tag; 983b0f4066SDimitry Andric // Invalidate all iterators. 993b0f4066SDimitry Andric PrevPos = SlotIndex(); 1007ae0e2c9SDimitry Andric unsigned i = 0; 1017ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) 1027ae0e2c9SDimitry Andric RegUnits[i].VirtTag = LIUArray[*Units].getTag(); 1033b0f4066SDimitry Andric } 1043b0f4066SDimitry Andric 1053b0f4066SDimitry Andric void InterferenceCache::Entry::reset(unsigned physReg, 1063b0f4066SDimitry Andric LiveIntervalUnion *LIUArray, 1073b0f4066SDimitry Andric const TargetRegisterInfo *TRI, 1083b0f4066SDimitry Andric const MachineFunction *MF) { 10917a519f9SDimitry Andric assert(!hasRefs() && "Cannot reset cache entry with references"); 1103b0f4066SDimitry Andric // LIU's changed, invalidate cache. 1113b0f4066SDimitry Andric ++Tag; 1123b0f4066SDimitry Andric PhysReg = physReg; 1133b0f4066SDimitry Andric Blocks.resize(MF->getNumBlockIDs()); 1143b0f4066SDimitry Andric 1153b0f4066SDimitry Andric // Reset iterators. 1163b0f4066SDimitry Andric PrevPos = SlotIndex(); 1177ae0e2c9SDimitry Andric RegUnits.clear(); 1187ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { 1197ae0e2c9SDimitry Andric RegUnits.push_back(LIUArray[*Units]); 1207ae0e2c9SDimitry Andric RegUnits.back().Fixed = &LIS->getRegUnit(*Units); 1217ae0e2c9SDimitry Andric } 1223b0f4066SDimitry Andric } 1233b0f4066SDimitry Andric 1243b0f4066SDimitry Andric bool InterferenceCache::Entry::valid(LiveIntervalUnion *LIUArray, 1253b0f4066SDimitry Andric const TargetRegisterInfo *TRI) { 1267ae0e2c9SDimitry Andric unsigned i = 0, e = RegUnits.size(); 1277ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) { 1287ae0e2c9SDimitry Andric if (i == e) 1293b0f4066SDimitry Andric return false; 1307ae0e2c9SDimitry Andric if (LIUArray[*Units].changedSince(RegUnits[i].VirtTag)) 1313b0f4066SDimitry Andric return false; 1323b0f4066SDimitry Andric } 1333b0f4066SDimitry Andric return i == e; 1343b0f4066SDimitry Andric } 1353b0f4066SDimitry Andric 1363b0f4066SDimitry Andric void InterferenceCache::Entry::update(unsigned MBBNum) { 1373b0f4066SDimitry Andric SlotIndex Start, Stop; 13891bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 1393b0f4066SDimitry Andric 1403b0f4066SDimitry Andric // Use advanceTo only when possible. 1413b0f4066SDimitry Andric if (PrevPos != Start) { 1427ae0e2c9SDimitry Andric if (!PrevPos.isValid() || Start < PrevPos) { 1437ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1447ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1457ae0e2c9SDimitry Andric RUI.VirtI.find(Start); 1467ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->find(Start); 1477ae0e2c9SDimitry Andric } 1487ae0e2c9SDimitry Andric } else { 1497ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1507ae0e2c9SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 1517ae0e2c9SDimitry Andric RUI.VirtI.advanceTo(Start); 1527ae0e2c9SDimitry Andric if (RUI.FixedI != RUI.Fixed->end()) 1537ae0e2c9SDimitry Andric RUI.FixedI = RUI.Fixed->advanceTo(RUI.FixedI, Start); 1547ae0e2c9SDimitry Andric } 1557ae0e2c9SDimitry Andric } 1563b0f4066SDimitry Andric PrevPos = Start; 1573b0f4066SDimitry Andric } 1583b0f4066SDimitry Andric 1597d523365SDimitry Andric MachineFunction::const_iterator MFI = 1607d523365SDimitry Andric MF->getBlockNumbered(MBBNum)->getIterator(); 1613b0f4066SDimitry Andric BlockInterference *BI = &Blocks[MBBNum]; 162dff0c46cSDimitry Andric ArrayRef<SlotIndex> RegMaskSlots; 163dff0c46cSDimitry Andric ArrayRef<const uint32_t*> RegMaskBits; 1642cab237bSDimitry Andric while (true) { 1653b0f4066SDimitry Andric BI->Tag = Tag; 1663b0f4066SDimitry Andric BI->First = BI->Last = SlotIndex(); 1673b0f4066SDimitry Andric 1687ae0e2c9SDimitry Andric // Check for first interference from virtregs. 1697ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1707ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 1713b0f4066SDimitry Andric if (!I.valid()) 1723b0f4066SDimitry Andric continue; 1733b0f4066SDimitry Andric SlotIndex StartI = I.start(); 1743b0f4066SDimitry Andric if (StartI >= Stop) 1753b0f4066SDimitry Andric continue; 1763b0f4066SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1773b0f4066SDimitry Andric BI->First = StartI; 1783b0f4066SDimitry Andric } 1793b0f4066SDimitry Andric 1807ae0e2c9SDimitry Andric // Same thing for fixed interference. 1817ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 1827ae0e2c9SDimitry Andric LiveInterval::const_iterator I = RegUnits[i].FixedI; 1837ae0e2c9SDimitry Andric LiveInterval::const_iterator E = RegUnits[i].Fixed->end(); 1847ae0e2c9SDimitry Andric if (I == E) 1857ae0e2c9SDimitry Andric continue; 1867ae0e2c9SDimitry Andric SlotIndex StartI = I->start; 1877ae0e2c9SDimitry Andric if (StartI >= Stop) 1887ae0e2c9SDimitry Andric continue; 1897ae0e2c9SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 1907ae0e2c9SDimitry Andric BI->First = StartI; 1917ae0e2c9SDimitry Andric } 1927ae0e2c9SDimitry Andric 193dff0c46cSDimitry Andric // Also check for register mask interference. 194dff0c46cSDimitry Andric RegMaskSlots = LIS->getRegMaskSlotsInBlock(MBBNum); 195dff0c46cSDimitry Andric RegMaskBits = LIS->getRegMaskBitsInBlock(MBBNum); 196dff0c46cSDimitry Andric SlotIndex Limit = BI->First.isValid() ? BI->First : Stop; 197dff0c46cSDimitry Andric for (unsigned i = 0, e = RegMaskSlots.size(); 198dff0c46cSDimitry Andric i != e && RegMaskSlots[i] < Limit; ++i) 199dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i], PhysReg)) { 200dff0c46cSDimitry Andric // Register mask i clobbers PhysReg before the LIU interference. 201dff0c46cSDimitry Andric BI->First = RegMaskSlots[i]; 202dff0c46cSDimitry Andric break; 203dff0c46cSDimitry Andric } 204dff0c46cSDimitry Andric 2053b0f4066SDimitry Andric PrevPos = Stop; 2063b0f4066SDimitry Andric if (BI->First.isValid()) 2073b0f4066SDimitry Andric break; 2083b0f4066SDimitry Andric 2093b0f4066SDimitry Andric // No interference in this block? Go ahead and precompute the next block. 2103b0f4066SDimitry Andric if (++MFI == MF->end()) 2113b0f4066SDimitry Andric return; 2123b0f4066SDimitry Andric MBBNum = MFI->getNumber(); 2133b0f4066SDimitry Andric BI = &Blocks[MBBNum]; 2143b0f4066SDimitry Andric if (BI->Tag == Tag) 2153b0f4066SDimitry Andric return; 21691bc56edSDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 2173b0f4066SDimitry Andric } 2183b0f4066SDimitry Andric 2193b0f4066SDimitry Andric // Check for last interference in block. 2207ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2217ae0e2c9SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 2223b0f4066SDimitry Andric if (!I.valid() || I.start() >= Stop) 2233b0f4066SDimitry Andric continue; 2243b0f4066SDimitry Andric I.advanceTo(Stop); 2253b0f4066SDimitry Andric bool Backup = !I.valid() || I.start() >= Stop; 2263b0f4066SDimitry Andric if (Backup) 2273b0f4066SDimitry Andric --I; 2283b0f4066SDimitry Andric SlotIndex StopI = I.stop(); 2293b0f4066SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2303b0f4066SDimitry Andric BI->Last = StopI; 2313b0f4066SDimitry Andric if (Backup) 2323b0f4066SDimitry Andric ++I; 2333b0f4066SDimitry Andric } 234dff0c46cSDimitry Andric 2357ae0e2c9SDimitry Andric // Fixed interference. 2367ae0e2c9SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 2377ae0e2c9SDimitry Andric LiveInterval::iterator &I = RegUnits[i].FixedI; 238f785676fSDimitry Andric LiveRange *LR = RegUnits[i].Fixed; 239f785676fSDimitry Andric if (I == LR->end() || I->start >= Stop) 2407ae0e2c9SDimitry Andric continue; 241f785676fSDimitry Andric I = LR->advanceTo(I, Stop); 242f785676fSDimitry Andric bool Backup = I == LR->end() || I->start >= Stop; 2437ae0e2c9SDimitry Andric if (Backup) 2447ae0e2c9SDimitry Andric --I; 2457ae0e2c9SDimitry Andric SlotIndex StopI = I->end; 2467ae0e2c9SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 2477ae0e2c9SDimitry Andric BI->Last = StopI; 2487ae0e2c9SDimitry Andric if (Backup) 2497ae0e2c9SDimitry Andric ++I; 2507ae0e2c9SDimitry Andric } 2517ae0e2c9SDimitry Andric 252dff0c46cSDimitry Andric // Also check for register mask interference. 253dff0c46cSDimitry Andric SlotIndex Limit = BI->Last.isValid() ? BI->Last : Start; 254dff0c46cSDimitry Andric for (unsigned i = RegMaskSlots.size(); 255dff0c46cSDimitry Andric i && RegMaskSlots[i-1].getDeadSlot() > Limit; --i) 256dff0c46cSDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i-1], PhysReg)) { 257dff0c46cSDimitry Andric // Register mask i-1 clobbers PhysReg after the LIU interference. 258dff0c46cSDimitry Andric // Model the regmask clobber as a dead def. 259dff0c46cSDimitry Andric BI->Last = RegMaskSlots[i-1].getDeadSlot(); 260dff0c46cSDimitry Andric break; 261dff0c46cSDimitry Andric } 2623b0f4066SDimitry Andric } 263