xref: /src/contrib/llvm-project/llvm/lib/CodeGen/LiveRegMatrix.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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