10b57cec5SDimitry Andric //===- LiveRegMatrix.cpp - Track register interference --------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the LiveRegMatrix analysis pass. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h" 140b57cec5SDimitry Andric #include "RegisterCoalescer.h" 150b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 160b57cec5SDimitry Andric #include "llvm/CodeGen/LiveInterval.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h" 23480093f4SDimitry Andric #include "llvm/InitializePasses.h" 240b57cec5SDimitry Andric #include "llvm/MC/LaneBitmask.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 260b57cec5SDimitry Andric #include "llvm/Pass.h" 270b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 290b57cec5SDimitry Andric #include <cassert> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace llvm; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric #define DEBUG_TYPE "regalloc" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric STATISTIC(NumAssigned , "Number of registers assigned"); 360b57cec5SDimitry Andric STATISTIC(NumUnassigned , "Number of registers unassigned"); 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric char LiveRegMatrix::ID = 0; 390b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix", 400b57cec5SDimitry Andric "Live Register Matrix", false, false) 41*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass) 420b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(VirtRegMap) 430b57cec5SDimitry Andric INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix", 440b57cec5SDimitry Andric "Live Register Matrix", false, false) 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID) {} 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const { 490b57cec5SDimitry Andric AU.setPreservesAll(); 50*0fca6ea1SDimitry Andric AU.addRequiredTransitive<LiveIntervalsWrapperPass>(); 510b57cec5SDimitry Andric AU.addRequiredTransitive<VirtRegMap>(); 520b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) { 560b57cec5SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo(); 57*0fca6ea1SDimitry Andric LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS(); 580b57cec5SDimitry Andric VRM = &getAnalysis<VirtRegMap>(); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric unsigned NumRegUnits = TRI->getNumRegUnits(); 610b57cec5SDimitry Andric if (NumRegUnits != Matrix.size()) 620b57cec5SDimitry Andric Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]); 630b57cec5SDimitry Andric Matrix.init(LIUAlloc, NumRegUnits); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Make sure no stale queries get reused. 660b57cec5SDimitry Andric invalidateVirtRegs(); 670b57cec5SDimitry Andric return false; 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric void LiveRegMatrix::releaseMemory() { 710b57cec5SDimitry Andric for (unsigned i = 0, e = Matrix.size(); i != e; ++i) { 720b57cec5SDimitry Andric Matrix[i].clear(); 730b57cec5SDimitry Andric // No need to clear Queries here, since LiveIntervalUnion::Query doesn't 740b57cec5SDimitry Andric // have anything important to clear and LiveRegMatrix's runOnFunction() 750b57cec5SDimitry Andric // does a std::unique_ptr::reset anyways. 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric template <typename Callable> 800b57cec5SDimitry Andric static bool foreachUnit(const TargetRegisterInfo *TRI, 8181ad6265SDimitry Andric const LiveInterval &VRegInterval, MCRegister PhysReg, 820b57cec5SDimitry Andric Callable Func) { 830b57cec5SDimitry Andric if (VRegInterval.hasSubRanges()) { 840b57cec5SDimitry Andric for (MCRegUnitMaskIterator Units(PhysReg, TRI); Units.isValid(); ++Units) { 850b57cec5SDimitry Andric unsigned Unit = (*Units).first; 860b57cec5SDimitry Andric LaneBitmask Mask = (*Units).second; 8781ad6265SDimitry Andric for (const LiveInterval::SubRange &S : VRegInterval.subranges()) { 880b57cec5SDimitry Andric if ((S.LaneMask & Mask).any()) { 890b57cec5SDimitry Andric if (Func(Unit, S)) 900b57cec5SDimitry Andric return true; 910b57cec5SDimitry Andric break; 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric } else { 9606c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 9706c3fb27SDimitry Andric if (Func(Unit, VRegInterval)) 980b57cec5SDimitry Andric return true; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric return false; 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 10481ad6265SDimitry Andric void LiveRegMatrix::assign(const LiveInterval &VirtReg, MCRegister PhysReg) { 105e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "assigning " << printReg(VirtReg.reg(), TRI) << " to " 1060b57cec5SDimitry Andric << printReg(PhysReg, TRI) << ':'); 107e8d8bef9SDimitry Andric assert(!VRM->hasPhys(VirtReg.reg()) && "Duplicate VirtReg assignment"); 108e8d8bef9SDimitry Andric VRM->assignVirt2Phys(VirtReg.reg(), PhysReg); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric foreachUnit( 1110b57cec5SDimitry Andric TRI, VirtReg, PhysReg, [&](unsigned Unit, const LiveRange &Range) { 1120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI) << ' ' << Range); 1130b57cec5SDimitry Andric Matrix[Unit].unify(VirtReg, Range); 1140b57cec5SDimitry Andric return false; 1150b57cec5SDimitry Andric }); 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric ++NumAssigned; 1180b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << '\n'); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 12181ad6265SDimitry Andric void LiveRegMatrix::unassign(const LiveInterval &VirtReg) { 122e8d8bef9SDimitry Andric Register PhysReg = VRM->getPhys(VirtReg.reg()); 123e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "unassigning " << printReg(VirtReg.reg(), TRI) 124e8d8bef9SDimitry Andric << " from " << printReg(PhysReg, TRI) << ':'); 125e8d8bef9SDimitry Andric VRM->clearVirt(VirtReg.reg()); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric foreachUnit(TRI, VirtReg, PhysReg, 1280b57cec5SDimitry Andric [&](unsigned Unit, const LiveRange &Range) { 1290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI)); 1300b57cec5SDimitry Andric Matrix[Unit].extract(VirtReg, Range); 1310b57cec5SDimitry Andric return false; 1320b57cec5SDimitry Andric }); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric ++NumUnassigned; 1350b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << '\n'); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 138e8d8bef9SDimitry Andric bool LiveRegMatrix::isPhysRegUsed(MCRegister PhysReg) const { 13906c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 14006c3fb27SDimitry Andric if (!Matrix[Unit].empty()) 1410b57cec5SDimitry Andric return true; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric return false; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 14681ad6265SDimitry Andric bool LiveRegMatrix::checkRegMaskInterference(const LiveInterval &VirtReg, 147e8d8bef9SDimitry Andric MCRegister PhysReg) { 1480b57cec5SDimitry Andric // Check if the cached information is valid. 1490b57cec5SDimitry Andric // The same BitVector can be reused for all PhysRegs. 1500b57cec5SDimitry Andric // We could cache multiple VirtRegs if it becomes necessary. 151e8d8bef9SDimitry Andric if (RegMaskVirtReg != VirtReg.reg() || RegMaskTag != UserTag) { 152e8d8bef9SDimitry Andric RegMaskVirtReg = VirtReg.reg(); 1530b57cec5SDimitry Andric RegMaskTag = UserTag; 1540b57cec5SDimitry Andric RegMaskUsable.clear(); 1550b57cec5SDimitry Andric LIS->checkRegMaskInterference(VirtReg, RegMaskUsable); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // The BitVector is indexed by PhysReg, not register unit. 1590b57cec5SDimitry Andric // Regmask interference is more fine grained than regunits. 1600b57cec5SDimitry Andric // For example, a Win64 call can clobber %ymm8 yet preserve %xmm8. 1610b57cec5SDimitry Andric return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg)); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 16481ad6265SDimitry Andric bool LiveRegMatrix::checkRegUnitInterference(const LiveInterval &VirtReg, 165e8d8bef9SDimitry Andric MCRegister PhysReg) { 1660b57cec5SDimitry Andric if (VirtReg.empty()) 1670b57cec5SDimitry Andric return false; 168e8d8bef9SDimitry Andric CoalescerPair CP(VirtReg.reg(), PhysReg, *TRI); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric bool Result = foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit, 1710b57cec5SDimitry Andric const LiveRange &Range) { 1720b57cec5SDimitry Andric const LiveRange &UnitRange = LIS->getRegUnit(Unit); 1730b57cec5SDimitry Andric return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes()); 1740b57cec5SDimitry Andric }); 1750b57cec5SDimitry Andric return Result; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric LiveIntervalUnion::Query &LiveRegMatrix::query(const LiveRange &LR, 179e8d8bef9SDimitry Andric MCRegister RegUnit) { 1800b57cec5SDimitry Andric LiveIntervalUnion::Query &Q = Queries[RegUnit]; 1810b57cec5SDimitry Andric Q.init(UserTag, LR, Matrix[RegUnit]); 1820b57cec5SDimitry Andric return Q; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric LiveRegMatrix::InterferenceKind 18681ad6265SDimitry Andric LiveRegMatrix::checkInterference(const LiveInterval &VirtReg, 18781ad6265SDimitry Andric MCRegister PhysReg) { 1880b57cec5SDimitry Andric if (VirtReg.empty()) 1890b57cec5SDimitry Andric return IK_Free; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric // Regmask interference is the fastest check. 1920b57cec5SDimitry Andric if (checkRegMaskInterference(VirtReg, PhysReg)) 1930b57cec5SDimitry Andric return IK_RegMask; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // Check for fixed interference. 1960b57cec5SDimitry Andric if (checkRegUnitInterference(VirtReg, PhysReg)) 1970b57cec5SDimitry Andric return IK_RegUnit; 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric // Check the matrix for virtual register interference. 2000b57cec5SDimitry Andric bool Interference = foreachUnit(TRI, VirtReg, PhysReg, 201e8d8bef9SDimitry Andric [&](MCRegister Unit, const LiveRange &LR) { 2020b57cec5SDimitry Andric return query(LR, Unit).checkInterference(); 2030b57cec5SDimitry Andric }); 2040b57cec5SDimitry Andric if (Interference) 2050b57cec5SDimitry Andric return IK_VirtReg; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric return IK_Free; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric bool LiveRegMatrix::checkInterference(SlotIndex Start, SlotIndex End, 211e8d8bef9SDimitry Andric MCRegister PhysReg) { 2120b57cec5SDimitry Andric // Construct artificial live range containing only one segment [Start, End). 2130b57cec5SDimitry Andric VNInfo valno(0, Start); 2140b57cec5SDimitry Andric LiveRange::Segment Seg(Start, End, &valno); 2150b57cec5SDimitry Andric LiveRange LR; 2160b57cec5SDimitry Andric LR.addSegment(Seg); 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric // Check for interference with that segment 21906c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 220fe6060f1SDimitry Andric // LR is stack-allocated. LiveRegMatrix caches queries by a key that 221fe6060f1SDimitry Andric // includes the address of the live range. If (for the same reg unit) this 222fe6060f1SDimitry Andric // checkInterference overload is called twice, without any other query() 223fe6060f1SDimitry Andric // calls in between (on heap-allocated LiveRanges) - which would invalidate 224fe6060f1SDimitry Andric // the cached query - the LR address seen the second time may well be the 225fe6060f1SDimitry Andric // same as that seen the first time, while the Start/End/valno may not - yet 226fe6060f1SDimitry Andric // the same cached result would be fetched. To avoid that, we don't cache 227fe6060f1SDimitry Andric // this query. 228fe6060f1SDimitry Andric // 229fe6060f1SDimitry Andric // FIXME: the usability of the Query API needs to be improved to avoid 230fe6060f1SDimitry Andric // subtle bugs due to query identity. Avoiding caching, for example, would 231fe6060f1SDimitry Andric // greatly simplify things. 232fe6060f1SDimitry Andric LiveIntervalUnion::Query Q; 23306c3fb27SDimitry Andric Q.reset(UserTag, LR, Matrix[Unit]); 234fe6060f1SDimitry Andric if (Q.checkInterference()) 2350b57cec5SDimitry Andric return true; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric return false; 2380b57cec5SDimitry Andric } 239e8d8bef9SDimitry Andric 240e8d8bef9SDimitry Andric Register LiveRegMatrix::getOneVReg(unsigned PhysReg) const { 24181ad6265SDimitry Andric const LiveInterval *VRegInterval = nullptr; 24206c3fb27SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) { 24306c3fb27SDimitry Andric if ((VRegInterval = Matrix[Unit].getOneVReg())) 244e8d8bef9SDimitry Andric return VRegInterval->reg(); 245e8d8bef9SDimitry Andric } 246e8d8bef9SDimitry Andric 247e8d8bef9SDimitry Andric return MCRegister::NoRegister; 248e8d8bef9SDimitry Andric } 249