171d5a254SDimitry Andric //===- LiveRegMatrix.cpp - Track register interference --------------------===//
258b69754SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
658b69754SDimitry Andric //
758b69754SDimitry Andric //===----------------------------------------------------------------------===//
858b69754SDimitry Andric //
958b69754SDimitry Andric // This file defines the LiveRegMatrix analysis pass.
1058b69754SDimitry Andric //
1158b69754SDimitry Andric //===----------------------------------------------------------------------===//
1258b69754SDimitry Andric
137ab83427SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h"
14522600a2SDimitry Andric #include "RegisterCoalescer.h"
1558b69754SDimitry Andric #include "llvm/ADT/Statistic.h"
1671d5a254SDimitry Andric #include "llvm/CodeGen/LiveInterval.h"
1771d5a254SDimitry Andric #include "llvm/CodeGen/LiveIntervalUnion.h"
18044eb2f6SDimitry Andric #include "llvm/CodeGen/LiveIntervals.h"
1971d5a254SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
20044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
21044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
227ab83427SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
23706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
2471d5a254SDimitry Andric #include "llvm/MC/LaneBitmask.h"
2571d5a254SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
267ab83427SDimitry Andric #include "llvm/Pass.h"
2758b69754SDimitry Andric #include "llvm/Support/Debug.h"
2858b69754SDimitry Andric #include "llvm/Support/raw_ostream.h"
2971d5a254SDimitry Andric #include <cassert>
3058b69754SDimitry Andric
3158b69754SDimitry Andric using namespace llvm;
3258b69754SDimitry Andric
335ca98fd9SDimitry Andric #define DEBUG_TYPE "regalloc"
345ca98fd9SDimitry Andric
3558b69754SDimitry Andric STATISTIC(NumAssigned , "Number of registers assigned");
3658b69754SDimitry Andric STATISTIC(NumUnassigned , "Number of registers unassigned");
3758b69754SDimitry Andric
3858b69754SDimitry Andric char LiveRegMatrix::ID = 0;
3958b69754SDimitry Andric INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix",
4058b69754SDimitry Andric "Live Register Matrix", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)41ac9a064cSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
4258b69754SDimitry Andric INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
4358b69754SDimitry Andric INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix",
4458b69754SDimitry Andric "Live Register Matrix", false, false)
4558b69754SDimitry Andric
4671d5a254SDimitry Andric LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID) {}
4758b69754SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const4858b69754SDimitry Andric void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const {
4958b69754SDimitry Andric AU.setPreservesAll();
50ac9a064cSDimitry Andric AU.addRequiredTransitive<LiveIntervalsWrapperPass>();
5158b69754SDimitry Andric AU.addRequiredTransitive<VirtRegMap>();
5258b69754SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
5358b69754SDimitry Andric }
5458b69754SDimitry Andric
runOnMachineFunction(MachineFunction & MF)5558b69754SDimitry Andric bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) {
5667c32a98SDimitry Andric TRI = MF.getSubtarget().getRegisterInfo();
57ac9a064cSDimitry Andric LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
5858b69754SDimitry Andric VRM = &getAnalysis<VirtRegMap>();
5958b69754SDimitry Andric
6058b69754SDimitry Andric unsigned NumRegUnits = TRI->getNumRegUnits();
6158b69754SDimitry Andric if (NumRegUnits != Matrix.size())
6258b69754SDimitry Andric Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]);
6358b69754SDimitry Andric Matrix.init(LIUAlloc, NumRegUnits);
6458b69754SDimitry Andric
6558b69754SDimitry Andric // Make sure no stale queries get reused.
6658b69754SDimitry Andric invalidateVirtRegs();
6758b69754SDimitry Andric return false;
6858b69754SDimitry Andric }
6958b69754SDimitry Andric
releaseMemory()7058b69754SDimitry Andric void LiveRegMatrix::releaseMemory() {
7158b69754SDimitry Andric for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
7258b69754SDimitry Andric Matrix[i].clear();
735ca98fd9SDimitry Andric // No need to clear Queries here, since LiveIntervalUnion::Query doesn't
745ca98fd9SDimitry Andric // have anything important to clear and LiveRegMatrix's runOnFunction()
755ca98fd9SDimitry Andric // does a std::unique_ptr::reset anyways.
7658b69754SDimitry Andric }
7758b69754SDimitry Andric }
7858b69754SDimitry Andric
7967c32a98SDimitry Andric template <typename Callable>
foreachUnit(const TargetRegisterInfo * TRI,const LiveInterval & VRegInterval,MCRegister PhysReg,Callable Func)80b915e9e0SDimitry Andric static bool foreachUnit(const TargetRegisterInfo *TRI,
81145449b1SDimitry Andric const LiveInterval &VRegInterval, MCRegister PhysReg,
82b915e9e0SDimitry Andric Callable Func) {
8367c32a98SDimitry Andric if (VRegInterval.hasSubRanges()) {
8467c32a98SDimitry Andric for (MCRegUnitMaskIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
8567c32a98SDimitry Andric unsigned Unit = (*Units).first;
86dd58ef01SDimitry Andric LaneBitmask Mask = (*Units).second;
87145449b1SDimitry Andric for (const LiveInterval::SubRange &S : VRegInterval.subranges()) {
88b915e9e0SDimitry Andric if ((S.LaneMask & Mask).any()) {
8967c32a98SDimitry Andric if (Func(Unit, S))
9067c32a98SDimitry Andric return true;
9167c32a98SDimitry Andric break;
9267c32a98SDimitry Andric }
9367c32a98SDimitry Andric }
9467c32a98SDimitry Andric }
9567c32a98SDimitry Andric } else {
967fa27ce4SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
977fa27ce4SDimitry Andric if (Func(Unit, VRegInterval))
9867c32a98SDimitry Andric return true;
9967c32a98SDimitry Andric }
10067c32a98SDimitry Andric }
10167c32a98SDimitry Andric return false;
10267c32a98SDimitry Andric }
10367c32a98SDimitry Andric
assign(const LiveInterval & VirtReg,MCRegister PhysReg)104145449b1SDimitry Andric void LiveRegMatrix::assign(const LiveInterval &VirtReg, MCRegister PhysReg) {
105b60736ecSDimitry Andric LLVM_DEBUG(dbgs() << "assigning " << printReg(VirtReg.reg(), TRI) << " to "
106eb11fae6SDimitry Andric << printReg(PhysReg, TRI) << ':');
107b60736ecSDimitry Andric assert(!VRM->hasPhys(VirtReg.reg()) && "Duplicate VirtReg assignment");
108b60736ecSDimitry Andric VRM->assignVirt2Phys(VirtReg.reg(), PhysReg);
10967c32a98SDimitry Andric
110eb11fae6SDimitry Andric foreachUnit(
111eb11fae6SDimitry Andric TRI, VirtReg, PhysReg, [&](unsigned Unit, const LiveRange &Range) {
112eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI) << ' ' << Range);
11367c32a98SDimitry Andric Matrix[Unit].unify(VirtReg, Range);
11467c32a98SDimitry Andric return false;
11567c32a98SDimitry Andric });
11667c32a98SDimitry Andric
11758b69754SDimitry Andric ++NumAssigned;
118eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << '\n');
11958b69754SDimitry Andric }
12058b69754SDimitry Andric
unassign(const LiveInterval & VirtReg)121145449b1SDimitry Andric void LiveRegMatrix::unassign(const LiveInterval &VirtReg) {
122b60736ecSDimitry Andric Register PhysReg = VRM->getPhys(VirtReg.reg());
123b60736ecSDimitry Andric LLVM_DEBUG(dbgs() << "unassigning " << printReg(VirtReg.reg(), TRI)
124b60736ecSDimitry Andric << " from " << printReg(PhysReg, TRI) << ':');
125b60736ecSDimitry Andric VRM->clearVirt(VirtReg.reg());
12667c32a98SDimitry Andric
127eb11fae6SDimitry Andric foreachUnit(TRI, VirtReg, PhysReg,
128eb11fae6SDimitry Andric [&](unsigned Unit, const LiveRange &Range) {
129eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI));
13067c32a98SDimitry Andric Matrix[Unit].extract(VirtReg, Range);
13167c32a98SDimitry Andric return false;
13267c32a98SDimitry Andric });
13367c32a98SDimitry Andric
13458b69754SDimitry Andric ++NumUnassigned;
135eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << '\n');
13658b69754SDimitry Andric }
13758b69754SDimitry Andric
isPhysRegUsed(MCRegister PhysReg) const138b60736ecSDimitry Andric bool LiveRegMatrix::isPhysRegUsed(MCRegister PhysReg) const {
1397fa27ce4SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
1407fa27ce4SDimitry Andric if (!Matrix[Unit].empty())
141ee8648bdSDimitry Andric return true;
142ee8648bdSDimitry Andric }
143ee8648bdSDimitry Andric return false;
144ee8648bdSDimitry Andric }
145ee8648bdSDimitry Andric
checkRegMaskInterference(const LiveInterval & VirtReg,MCRegister PhysReg)146145449b1SDimitry Andric bool LiveRegMatrix::checkRegMaskInterference(const LiveInterval &VirtReg,
147b60736ecSDimitry Andric MCRegister PhysReg) {
14858b69754SDimitry Andric // Check if the cached information is valid.
14958b69754SDimitry Andric // The same BitVector can be reused for all PhysRegs.
15058b69754SDimitry Andric // We could cache multiple VirtRegs if it becomes necessary.
151b60736ecSDimitry Andric if (RegMaskVirtReg != VirtReg.reg() || RegMaskTag != UserTag) {
152b60736ecSDimitry Andric RegMaskVirtReg = VirtReg.reg();
15358b69754SDimitry Andric RegMaskTag = UserTag;
15458b69754SDimitry Andric RegMaskUsable.clear();
15558b69754SDimitry Andric LIS->checkRegMaskInterference(VirtReg, RegMaskUsable);
15658b69754SDimitry Andric }
15758b69754SDimitry Andric
15858b69754SDimitry Andric // The BitVector is indexed by PhysReg, not register unit.
15958b69754SDimitry Andric // Regmask interference is more fine grained than regunits.
16058b69754SDimitry Andric // For example, a Win64 call can clobber %ymm8 yet preserve %xmm8.
16158b69754SDimitry Andric return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg));
16258b69754SDimitry Andric }
16358b69754SDimitry Andric
checkRegUnitInterference(const LiveInterval & VirtReg,MCRegister PhysReg)164145449b1SDimitry Andric bool LiveRegMatrix::checkRegUnitInterference(const LiveInterval &VirtReg,
165b60736ecSDimitry Andric MCRegister PhysReg) {
16658b69754SDimitry Andric if (VirtReg.empty())
16758b69754SDimitry Andric return false;
168b60736ecSDimitry Andric CoalescerPair CP(VirtReg.reg(), PhysReg, *TRI);
16967c32a98SDimitry Andric
17067c32a98SDimitry Andric bool Result = foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
17167c32a98SDimitry Andric const LiveRange &Range) {
17267c32a98SDimitry Andric const LiveRange &UnitRange = LIS->getRegUnit(Unit);
17367c32a98SDimitry Andric return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
17467c32a98SDimitry Andric });
17567c32a98SDimitry Andric return Result;
17658b69754SDimitry Andric }
17758b69754SDimitry Andric
query(const LiveRange & LR,MCRegister RegUnit)17871d5a254SDimitry Andric LiveIntervalUnion::Query &LiveRegMatrix::query(const LiveRange &LR,
179b60736ecSDimitry Andric MCRegister RegUnit) {
18058b69754SDimitry Andric LiveIntervalUnion::Query &Q = Queries[RegUnit];
18171d5a254SDimitry Andric Q.init(UserTag, LR, Matrix[RegUnit]);
18258b69754SDimitry Andric return Q;
18358b69754SDimitry Andric }
18458b69754SDimitry Andric
18558b69754SDimitry Andric LiveRegMatrix::InterferenceKind
checkInterference(const LiveInterval & VirtReg,MCRegister PhysReg)186145449b1SDimitry Andric LiveRegMatrix::checkInterference(const LiveInterval &VirtReg,
187145449b1SDimitry Andric MCRegister PhysReg) {
18858b69754SDimitry Andric if (VirtReg.empty())
18958b69754SDimitry Andric return IK_Free;
19058b69754SDimitry Andric
19158b69754SDimitry Andric // Regmask interference is the fastest check.
19258b69754SDimitry Andric if (checkRegMaskInterference(VirtReg, PhysReg))
19358b69754SDimitry Andric return IK_RegMask;
19458b69754SDimitry Andric
19558b69754SDimitry Andric // Check for fixed interference.
19658b69754SDimitry Andric if (checkRegUnitInterference(VirtReg, PhysReg))
19758b69754SDimitry Andric return IK_RegUnit;
19858b69754SDimitry Andric
19958b69754SDimitry Andric // Check the matrix for virtual register interference.
20071d5a254SDimitry Andric bool Interference = foreachUnit(TRI, VirtReg, PhysReg,
201b60736ecSDimitry Andric [&](MCRegister Unit, const LiveRange &LR) {
20271d5a254SDimitry Andric return query(LR, Unit).checkInterference();
20371d5a254SDimitry Andric });
20471d5a254SDimitry Andric if (Interference)
20558b69754SDimitry Andric return IK_VirtReg;
20658b69754SDimitry Andric
20758b69754SDimitry Andric return IK_Free;
20858b69754SDimitry Andric }
209eb11fae6SDimitry Andric
checkInterference(SlotIndex Start,SlotIndex End,MCRegister PhysReg)210eb11fae6SDimitry Andric bool LiveRegMatrix::checkInterference(SlotIndex Start, SlotIndex End,
211b60736ecSDimitry Andric MCRegister PhysReg) {
212eb11fae6SDimitry Andric // Construct artificial live range containing only one segment [Start, End).
213eb11fae6SDimitry Andric VNInfo valno(0, Start);
214eb11fae6SDimitry Andric LiveRange::Segment Seg(Start, End, &valno);
215eb11fae6SDimitry Andric LiveRange LR;
216eb11fae6SDimitry Andric LR.addSegment(Seg);
217eb11fae6SDimitry Andric
218eb11fae6SDimitry Andric // Check for interference with that segment
2197fa27ce4SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
220344a3780SDimitry Andric // LR is stack-allocated. LiveRegMatrix caches queries by a key that
221344a3780SDimitry Andric // includes the address of the live range. If (for the same reg unit) this
222344a3780SDimitry Andric // checkInterference overload is called twice, without any other query()
223344a3780SDimitry Andric // calls in between (on heap-allocated LiveRanges) - which would invalidate
224344a3780SDimitry Andric // the cached query - the LR address seen the second time may well be the
225344a3780SDimitry Andric // same as that seen the first time, while the Start/End/valno may not - yet
226344a3780SDimitry Andric // the same cached result would be fetched. To avoid that, we don't cache
227344a3780SDimitry Andric // this query.
228344a3780SDimitry Andric //
229344a3780SDimitry Andric // FIXME: the usability of the Query API needs to be improved to avoid
230344a3780SDimitry Andric // subtle bugs due to query identity. Avoiding caching, for example, would
231344a3780SDimitry Andric // greatly simplify things.
232344a3780SDimitry Andric LiveIntervalUnion::Query Q;
2337fa27ce4SDimitry Andric Q.reset(UserTag, LR, Matrix[Unit]);
234344a3780SDimitry Andric if (Q.checkInterference())
235eb11fae6SDimitry Andric return true;
236eb11fae6SDimitry Andric }
237eb11fae6SDimitry Andric return false;
238eb11fae6SDimitry Andric }
239b60736ecSDimitry Andric
getOneVReg(unsigned PhysReg) const240b60736ecSDimitry Andric Register LiveRegMatrix::getOneVReg(unsigned PhysReg) const {
241145449b1SDimitry Andric const LiveInterval *VRegInterval = nullptr;
2427fa27ce4SDimitry Andric for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
2437fa27ce4SDimitry Andric if ((VRegInterval = Matrix[Unit].getOneVReg()))
244b60736ecSDimitry Andric return VRegInterval->reg();
245b60736ecSDimitry Andric }
246b60736ecSDimitry Andric
247b60736ecSDimitry Andric return MCRegister::NoRegister;
248b60736ecSDimitry Andric }
249