1*0b57cec5SDimitry Andric //===- InterferenceCache.cpp - Caching per-block interference -------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // InterferenceCache remembers per-block interference in LiveIntervalUnions. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "InterferenceCache.h" 14*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 15*0b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 16*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 19*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 20*0b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 21*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 22*0b57cec5SDimitry Andric #include <cassert> 23*0b57cec5SDimitry Andric #include <cstdint> 24*0b57cec5SDimitry Andric #include <tuple> 25*0b57cec5SDimitry Andric 26*0b57cec5SDimitry Andric using namespace llvm; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric #define DEBUG_TYPE "regalloc" 29*0b57cec5SDimitry Andric 30*0b57cec5SDimitry Andric // Static member used for null interference cursors. 31*0b57cec5SDimitry Andric const InterferenceCache::BlockInterference 32*0b57cec5SDimitry Andric InterferenceCache::Cursor::NoInterference; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric // Initializes PhysRegEntries (instead of a SmallVector, PhysRegEntries is a 35*0b57cec5SDimitry Andric // buffer of size NumPhysRegs to speed up alloc/clear for targets with large 36*0b57cec5SDimitry Andric // reg files). Calloced memory is used for good form, and quites tools like 37*0b57cec5SDimitry Andric // Valgrind too, but zero initialized memory is not required by the algorithm: 38*0b57cec5SDimitry Andric // this is because PhysRegEntries works like a SparseSet and its entries are 39*0b57cec5SDimitry Andric // only valid when there is a corresponding CacheEntries assignment. There is 40*0b57cec5SDimitry Andric // also support for when pass managers are reused for targets with different 41*0b57cec5SDimitry Andric // numbers of PhysRegs: in this case PhysRegEntries is freed and reinitialized. 42*0b57cec5SDimitry Andric void InterferenceCache::reinitPhysRegEntries() { 43*0b57cec5SDimitry Andric if (PhysRegEntriesCount == TRI->getNumRegs()) return; 44*0b57cec5SDimitry Andric free(PhysRegEntries); 45*0b57cec5SDimitry Andric PhysRegEntriesCount = TRI->getNumRegs(); 46*0b57cec5SDimitry Andric PhysRegEntries = static_cast<unsigned char*>( 47*0b57cec5SDimitry Andric safe_calloc(PhysRegEntriesCount, sizeof(unsigned char))); 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric void InterferenceCache::init(MachineFunction *mf, 51*0b57cec5SDimitry Andric LiveIntervalUnion *liuarray, 52*0b57cec5SDimitry Andric SlotIndexes *indexes, 53*0b57cec5SDimitry Andric LiveIntervals *lis, 54*0b57cec5SDimitry Andric const TargetRegisterInfo *tri) { 55*0b57cec5SDimitry Andric MF = mf; 56*0b57cec5SDimitry Andric LIUArray = liuarray; 57*0b57cec5SDimitry Andric TRI = tri; 58*0b57cec5SDimitry Andric reinitPhysRegEntries(); 590eae32dcSDimitry Andric for (Entry &E : Entries) 600eae32dcSDimitry Andric E.clear(mf, indexes, lis); 61*0b57cec5SDimitry Andric } 62*0b57cec5SDimitry Andric 63e8d8bef9SDimitry Andric InterferenceCache::Entry *InterferenceCache::get(MCRegister PhysReg) { 64e8d8bef9SDimitry Andric unsigned char E = PhysRegEntries[PhysReg.id()]; 65*0b57cec5SDimitry Andric if (E < CacheEntries && Entries[E].getPhysReg() == PhysReg) { 66*0b57cec5SDimitry Andric if (!Entries[E].valid(LIUArray, TRI)) 67*0b57cec5SDimitry Andric Entries[E].revalidate(LIUArray, TRI); 68*0b57cec5SDimitry Andric return &Entries[E]; 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric // No valid entry exists, pick the next round-robin entry. 71*0b57cec5SDimitry Andric E = RoundRobin; 72*0b57cec5SDimitry Andric if (++RoundRobin == CacheEntries) 73*0b57cec5SDimitry Andric RoundRobin = 0; 74*0b57cec5SDimitry Andric for (unsigned i = 0; i != CacheEntries; ++i) { 75*0b57cec5SDimitry Andric // Skip entries that are in use. 76*0b57cec5SDimitry Andric if (Entries[E].hasRefs()) { 77*0b57cec5SDimitry Andric if (++E == CacheEntries) 78*0b57cec5SDimitry Andric E = 0; 79*0b57cec5SDimitry Andric continue; 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric Entries[E].reset(PhysReg, LIUArray, TRI, MF); 82*0b57cec5SDimitry Andric PhysRegEntries[PhysReg] = E; 83*0b57cec5SDimitry Andric return &Entries[E]; 84*0b57cec5SDimitry Andric } 85*0b57cec5SDimitry Andric llvm_unreachable("Ran out of interference cache entries."); 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric /// revalidate - LIU contents have changed, update tags. 89*0b57cec5SDimitry Andric void InterferenceCache::Entry::revalidate(LiveIntervalUnion *LIUArray, 90*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 91*0b57cec5SDimitry Andric // Invalidate all block entries. 92*0b57cec5SDimitry Andric ++Tag; 93*0b57cec5SDimitry Andric // Invalidate all iterators. 94*0b57cec5SDimitry Andric PrevPos = SlotIndex(); 95*0b57cec5SDimitry Andric unsigned i = 0; 96*0b57cec5SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) 97*0b57cec5SDimitry Andric RegUnits[i].VirtTag = LIUArray[*Units].getTag(); 98*0b57cec5SDimitry Andric } 99*0b57cec5SDimitry Andric 100e8d8bef9SDimitry Andric void InterferenceCache::Entry::reset(MCRegister physReg, 101*0b57cec5SDimitry Andric LiveIntervalUnion *LIUArray, 102*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 103*0b57cec5SDimitry Andric const MachineFunction *MF) { 104*0b57cec5SDimitry Andric assert(!hasRefs() && "Cannot reset cache entry with references"); 105*0b57cec5SDimitry Andric // LIU's changed, invalidate cache. 106*0b57cec5SDimitry Andric ++Tag; 107*0b57cec5SDimitry Andric PhysReg = physReg; 108*0b57cec5SDimitry Andric Blocks.resize(MF->getNumBlockIDs()); 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric // Reset iterators. 111*0b57cec5SDimitry Andric PrevPos = SlotIndex(); 112*0b57cec5SDimitry Andric RegUnits.clear(); 113*0b57cec5SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { 114*0b57cec5SDimitry Andric RegUnits.push_back(LIUArray[*Units]); 115*0b57cec5SDimitry Andric RegUnits.back().Fixed = &LIS->getRegUnit(*Units); 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric } 118*0b57cec5SDimitry Andric 119*0b57cec5SDimitry Andric bool InterferenceCache::Entry::valid(LiveIntervalUnion *LIUArray, 120*0b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 121*0b57cec5SDimitry Andric unsigned i = 0, e = RegUnits.size(); 122*0b57cec5SDimitry Andric for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units, ++i) { 123*0b57cec5SDimitry Andric if (i == e) 124*0b57cec5SDimitry Andric return false; 125*0b57cec5SDimitry Andric if (LIUArray[*Units].changedSince(RegUnits[i].VirtTag)) 126*0b57cec5SDimitry Andric return false; 127*0b57cec5SDimitry Andric } 128*0b57cec5SDimitry Andric return i == e; 129*0b57cec5SDimitry Andric } 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric void InterferenceCache::Entry::update(unsigned MBBNum) { 132*0b57cec5SDimitry Andric SlotIndex Start, Stop; 133*0b57cec5SDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric // Use advanceTo only when possible. 136*0b57cec5SDimitry Andric if (PrevPos != Start) { 137*0b57cec5SDimitry Andric if (!PrevPos.isValid() || Start < PrevPos) { 138*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 139*0b57cec5SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 140*0b57cec5SDimitry Andric RUI.VirtI.find(Start); 141*0b57cec5SDimitry Andric RUI.FixedI = RUI.Fixed->find(Start); 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric } else { 144*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 145*0b57cec5SDimitry Andric RegUnitInfo &RUI = RegUnits[i]; 146*0b57cec5SDimitry Andric RUI.VirtI.advanceTo(Start); 147*0b57cec5SDimitry Andric if (RUI.FixedI != RUI.Fixed->end()) 148*0b57cec5SDimitry Andric RUI.FixedI = RUI.Fixed->advanceTo(RUI.FixedI, Start); 149*0b57cec5SDimitry Andric } 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric PrevPos = Start; 152*0b57cec5SDimitry Andric } 153*0b57cec5SDimitry Andric 154*0b57cec5SDimitry Andric MachineFunction::const_iterator MFI = 155*0b57cec5SDimitry Andric MF->getBlockNumbered(MBBNum)->getIterator(); 156*0b57cec5SDimitry Andric BlockInterference *BI = &Blocks[MBBNum]; 157*0b57cec5SDimitry Andric ArrayRef<SlotIndex> RegMaskSlots; 158*0b57cec5SDimitry Andric ArrayRef<const uint32_t*> RegMaskBits; 159*0b57cec5SDimitry Andric while (true) { 160*0b57cec5SDimitry Andric BI->Tag = Tag; 161*0b57cec5SDimitry Andric BI->First = BI->Last = SlotIndex(); 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric // Check for first interference from virtregs. 164*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 165*0b57cec5SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 166*0b57cec5SDimitry Andric if (!I.valid()) 167*0b57cec5SDimitry Andric continue; 168*0b57cec5SDimitry Andric SlotIndex StartI = I.start(); 169*0b57cec5SDimitry Andric if (StartI >= Stop) 170*0b57cec5SDimitry Andric continue; 171*0b57cec5SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 172*0b57cec5SDimitry Andric BI->First = StartI; 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric // Same thing for fixed interference. 176*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 177*0b57cec5SDimitry Andric LiveInterval::const_iterator I = RegUnits[i].FixedI; 178*0b57cec5SDimitry Andric LiveInterval::const_iterator E = RegUnits[i].Fixed->end(); 179*0b57cec5SDimitry Andric if (I == E) 180*0b57cec5SDimitry Andric continue; 181*0b57cec5SDimitry Andric SlotIndex StartI = I->start; 182*0b57cec5SDimitry Andric if (StartI >= Stop) 183*0b57cec5SDimitry Andric continue; 184*0b57cec5SDimitry Andric if (!BI->First.isValid() || StartI < BI->First) 185*0b57cec5SDimitry Andric BI->First = StartI; 186*0b57cec5SDimitry Andric } 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric // Also check for register mask interference. 189*0b57cec5SDimitry Andric RegMaskSlots = LIS->getRegMaskSlotsInBlock(MBBNum); 190*0b57cec5SDimitry Andric RegMaskBits = LIS->getRegMaskBitsInBlock(MBBNum); 191*0b57cec5SDimitry Andric SlotIndex Limit = BI->First.isValid() ? BI->First : Stop; 192*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegMaskSlots.size(); 193*0b57cec5SDimitry Andric i != e && RegMaskSlots[i] < Limit; ++i) 194*0b57cec5SDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i], PhysReg)) { 195*0b57cec5SDimitry Andric // Register mask i clobbers PhysReg before the LIU interference. 196*0b57cec5SDimitry Andric BI->First = RegMaskSlots[i]; 197*0b57cec5SDimitry Andric break; 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric 200*0b57cec5SDimitry Andric PrevPos = Stop; 201*0b57cec5SDimitry Andric if (BI->First.isValid()) 202*0b57cec5SDimitry Andric break; 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric // No interference in this block? Go ahead and precompute the next block. 205*0b57cec5SDimitry Andric if (++MFI == MF->end()) 206*0b57cec5SDimitry Andric return; 207*0b57cec5SDimitry Andric MBBNum = MFI->getNumber(); 208*0b57cec5SDimitry Andric BI = &Blocks[MBBNum]; 209*0b57cec5SDimitry Andric if (BI->Tag == Tag) 210*0b57cec5SDimitry Andric return; 211*0b57cec5SDimitry Andric std::tie(Start, Stop) = Indexes->getMBBRange(MBBNum); 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric // Check for last interference in block. 215*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 216*0b57cec5SDimitry Andric LiveIntervalUnion::SegmentIter &I = RegUnits[i].VirtI; 217*0b57cec5SDimitry Andric if (!I.valid() || I.start() >= Stop) 218*0b57cec5SDimitry Andric continue; 219*0b57cec5SDimitry Andric I.advanceTo(Stop); 220*0b57cec5SDimitry Andric bool Backup = !I.valid() || I.start() >= Stop; 221*0b57cec5SDimitry Andric if (Backup) 222*0b57cec5SDimitry Andric --I; 223*0b57cec5SDimitry Andric SlotIndex StopI = I.stop(); 224*0b57cec5SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 225*0b57cec5SDimitry Andric BI->Last = StopI; 226*0b57cec5SDimitry Andric if (Backup) 227*0b57cec5SDimitry Andric ++I; 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric // Fixed interference. 231*0b57cec5SDimitry Andric for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) { 232*0b57cec5SDimitry Andric LiveInterval::iterator &I = RegUnits[i].FixedI; 233*0b57cec5SDimitry Andric LiveRange *LR = RegUnits[i].Fixed; 234*0b57cec5SDimitry Andric if (I == LR->end() || I->start >= Stop) 235*0b57cec5SDimitry Andric continue; 236*0b57cec5SDimitry Andric I = LR->advanceTo(I, Stop); 237*0b57cec5SDimitry Andric bool Backup = I == LR->end() || I->start >= Stop; 238*0b57cec5SDimitry Andric if (Backup) 239*0b57cec5SDimitry Andric --I; 240*0b57cec5SDimitry Andric SlotIndex StopI = I->end; 241*0b57cec5SDimitry Andric if (!BI->Last.isValid() || StopI > BI->Last) 242*0b57cec5SDimitry Andric BI->Last = StopI; 243*0b57cec5SDimitry Andric if (Backup) 244*0b57cec5SDimitry Andric ++I; 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric // Also check for register mask interference. 248*0b57cec5SDimitry Andric SlotIndex Limit = BI->Last.isValid() ? BI->Last : Start; 249*0b57cec5SDimitry Andric for (unsigned i = RegMaskSlots.size(); 250*0b57cec5SDimitry Andric i && RegMaskSlots[i-1].getDeadSlot() > Limit; --i) 251*0b57cec5SDimitry Andric if (MachineOperand::clobbersPhysReg(RegMaskBits[i-1], PhysReg)) { 252*0b57cec5SDimitry Andric // Register mask i-1 clobbers PhysReg after the LIU interference. 253*0b57cec5SDimitry Andric // Model the regmask clobber as a dead def. 254*0b57cec5SDimitry Andric BI->Last = RegMaskSlots[i-1].getDeadSlot(); 255*0b57cec5SDimitry Andric break; 256*0b57cec5SDimitry Andric } 257*0b57cec5SDimitry Andric } 258