2017-02-17 22:43:25 +01:00
|
|
|
//===- LiveRegMatrix.cpp - Track register interference --------------------===//
|
2012-06-09 04:13:10 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2012-06-09 04:13:10 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file defines the LiveRegMatrix analysis pass.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/CodeGen/LiveRegMatrix.h"
|
2012-09-06 20:15:23 +02:00
|
|
|
#include "RegisterCoalescer.h"
|
2012-06-09 04:13:10 +02:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2017-02-17 22:43:25 +01:00
|
|
|
#include "llvm/CodeGen/LiveInterval.h"
|
|
|
|
#include "llvm/CodeGen/LiveIntervalUnion.h"
|
2017-12-13 03:51:04 +01:00
|
|
|
#include "llvm/CodeGen/LiveIntervals.h"
|
2017-02-17 22:43:25 +01:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
2017-11-17 02:07:10 +01:00
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/CodeGen/VirtRegMap.h"
|
Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.
I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
recompiles touches affected_files header
342380 95 3604 llvm/include/llvm/ADT/STLExtras.h
314730 234 1345 llvm/include/llvm/InitializePasses.h
307036 118 2602 llvm/include/llvm/ADT/APInt.h
213049 59 3611 llvm/include/llvm/Support/MathExtras.h
170422 47 3626 llvm/include/llvm/Support/Compiler.h
162225 45 3605 llvm/include/llvm/ADT/Optional.h
158319 63 2513 llvm/include/llvm/ADT/Triple.h
140322 39 3598 llvm/include/llvm/ADT/StringRef.h
137647 59 2333 llvm/include/llvm/Support/Error.h
131619 73 1803 llvm/include/llvm/Support/FileSystem.h
Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.
Reviewers: bkramer, asbirlea, bollu, jdoerfert
Differential Revision: https://reviews.llvm.org/D70211
2019-11-13 22:15:01 +01:00
|
|
|
#include "llvm/InitializePasses.h"
|
2017-02-17 22:43:25 +01:00
|
|
|
#include "llvm/MC/LaneBitmask.h"
|
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2017-06-06 13:49:48 +02:00
|
|
|
#include "llvm/Pass.h"
|
2012-06-09 04:13:10 +02:00
|
|
|
#include "llvm/Support/Debug.h"
|
2015-01-14 12:23:27 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-02-17 22:43:25 +01:00
|
|
|
#include <cassert>
|
2012-06-09 04:13:10 +02:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 04:02:50 +02:00
|
|
|
#define DEBUG_TYPE "regalloc"
|
|
|
|
|
2012-06-09 04:13:10 +02:00
|
|
|
STATISTIC(NumAssigned , "Number of registers assigned");
|
|
|
|
STATISTIC(NumUnassigned , "Number of registers unassigned");
|
|
|
|
|
|
|
|
char LiveRegMatrix::ID = 0;
|
|
|
|
INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix",
|
|
|
|
"Live Register Matrix", false, false)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
|
|
|
|
INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix",
|
|
|
|
"Live Register Matrix", false, false)
|
|
|
|
|
2017-02-17 22:43:25 +01:00
|
|
|
LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID) {}
|
2012-06-09 04:13:10 +02:00
|
|
|
|
|
|
|
void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
|
|
AU.setPreservesAll();
|
|
|
|
AU.addRequiredTransitive<LiveIntervals>();
|
|
|
|
AU.addRequiredTransitive<VirtRegMap>();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) {
|
2014-08-05 04:39:49 +02:00
|
|
|
TRI = MF.getSubtarget().getRegisterInfo();
|
2012-06-09 04:13:10 +02:00
|
|
|
LIS = &getAnalysis<LiveIntervals>();
|
|
|
|
VRM = &getAnalysis<VirtRegMap>();
|
|
|
|
|
|
|
|
unsigned NumRegUnits = TRI->getNumRegUnits();
|
|
|
|
if (NumRegUnits != Matrix.size())
|
|
|
|
Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]);
|
|
|
|
Matrix.init(LIUAlloc, NumRegUnits);
|
|
|
|
|
|
|
|
// Make sure no stale queries get reused.
|
|
|
|
invalidateVirtRegs();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LiveRegMatrix::releaseMemory() {
|
|
|
|
for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
|
|
|
|
Matrix[i].clear();
|
2014-02-06 09:42:01 +01:00
|
|
|
// No need to clear Queries here, since LiveIntervalUnion::Query doesn't
|
|
|
|
// have anything important to clear and LiveRegMatrix's runOnFunction()
|
2014-03-06 06:51:42 +01:00
|
|
|
// does a std::unique_ptr::reset anyways.
|
2012-06-09 04:13:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-06 13:13:10 +02:00
|
|
|
template <typename Callable>
|
|
|
|
static bool foreachUnit(const TargetRegisterInfo *TRI,
|
2020-10-09 19:04:29 +02:00
|
|
|
LiveInterval &VRegInterval, MCRegister PhysReg,
|
2016-08-06 13:13:10 +02:00
|
|
|
Callable Func) {
|
2014-12-10 02:13:01 +01:00
|
|
|
if (VRegInterval.hasSubRanges()) {
|
|
|
|
for (MCRegUnitMaskIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
unsigned Unit = (*Units).first;
|
2015-09-25 23:51:14 +02:00
|
|
|
LaneBitmask Mask = (*Units).second;
|
2014-12-11 01:59:06 +01:00
|
|
|
for (LiveInterval::SubRange &S : VRegInterval.subranges()) {
|
2016-12-16 20:11:56 +01:00
|
|
|
if ((S.LaneMask & Mask).any()) {
|
2014-12-11 01:59:06 +01:00
|
|
|
if (Func(Unit, S))
|
2014-12-10 02:13:01 +01:00
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
|
|
|
if (Func(*Units, VRegInterval))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:04:29 +02:00
|
|
|
void LiveRegMatrix::assign(LiveInterval &VirtReg, MCRegister PhysReg) {
|
2020-09-15 23:54:38 +02:00
|
|
|
LLVM_DEBUG(dbgs() << "assigning " << printReg(VirtReg.reg(), TRI) << " to "
|
2018-05-14 14:53:11 +02:00
|
|
|
<< printReg(PhysReg, TRI) << ':');
|
2020-09-15 23:54:38 +02:00
|
|
|
assert(!VRM->hasPhys(VirtReg.reg()) && "Duplicate VirtReg assignment");
|
|
|
|
VRM->assignVirt2Phys(VirtReg.reg(), PhysReg);
|
2014-12-10 02:13:01 +01:00
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
foreachUnit(
|
|
|
|
TRI, VirtReg, PhysReg, [&](unsigned Unit, const LiveRange &Range) {
|
|
|
|
LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI) << ' ' << Range);
|
|
|
|
Matrix[Unit].unify(VirtReg, Range);
|
|
|
|
return false;
|
|
|
|
});
|
2014-12-10 02:13:01 +01:00
|
|
|
|
2012-06-09 04:13:10 +02:00
|
|
|
++NumAssigned;
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << '\n');
|
2012-06-09 04:13:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void LiveRegMatrix::unassign(LiveInterval &VirtReg) {
|
2020-09-15 23:54:38 +02:00
|
|
|
Register PhysReg = VRM->getPhys(VirtReg.reg());
|
|
|
|
LLVM_DEBUG(dbgs() << "unassigning " << printReg(VirtReg.reg(), TRI)
|
|
|
|
<< " from " << printReg(PhysReg, TRI) << ':');
|
|
|
|
VRM->clearVirt(VirtReg.reg());
|
2014-12-10 02:13:01 +01:00
|
|
|
|
2018-05-14 14:53:11 +02:00
|
|
|
foreachUnit(TRI, VirtReg, PhysReg,
|
|
|
|
[&](unsigned Unit, const LiveRange &Range) {
|
|
|
|
LLVM_DEBUG(dbgs() << ' ' << printRegUnit(Unit, TRI));
|
|
|
|
Matrix[Unit].extract(VirtReg, Range);
|
|
|
|
return false;
|
|
|
|
});
|
2014-12-10 02:13:01 +01:00
|
|
|
|
2012-06-09 04:13:10 +02:00
|
|
|
++NumUnassigned;
|
2018-05-14 14:53:11 +02:00
|
|
|
LLVM_DEBUG(dbgs() << '\n');
|
2012-06-09 04:13:10 +02:00
|
|
|
}
|
|
|
|
|
2020-10-09 19:04:29 +02:00
|
|
|
bool LiveRegMatrix::isPhysRegUsed(MCRegister PhysReg) const {
|
2015-07-14 19:38:17 +02:00
|
|
|
for (MCRegUnitIterator Unit(PhysReg, TRI); Unit.isValid(); ++Unit) {
|
|
|
|
if (!Matrix[*Unit].empty())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-06-09 04:13:10 +02:00
|
|
|
bool LiveRegMatrix::checkRegMaskInterference(LiveInterval &VirtReg,
|
2020-10-09 19:04:29 +02:00
|
|
|
MCRegister PhysReg) {
|
2012-06-09 04:13:10 +02:00
|
|
|
// Check if the cached information is valid.
|
|
|
|
// The same BitVector can be reused for all PhysRegs.
|
|
|
|
// We could cache multiple VirtRegs if it becomes necessary.
|
2020-09-15 23:54:38 +02:00
|
|
|
if (RegMaskVirtReg != VirtReg.reg() || RegMaskTag != UserTag) {
|
|
|
|
RegMaskVirtReg = VirtReg.reg();
|
2012-06-09 04:13:10 +02:00
|
|
|
RegMaskTag = UserTag;
|
|
|
|
RegMaskUsable.clear();
|
|
|
|
LIS->checkRegMaskInterference(VirtReg, RegMaskUsable);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The BitVector is indexed by PhysReg, not register unit.
|
|
|
|
// Regmask interference is more fine grained than regunits.
|
|
|
|
// For example, a Win64 call can clobber %ymm8 yet preserve %xmm8.
|
2012-06-16 00:24:22 +02:00
|
|
|
return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg));
|
2012-06-09 04:13:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg,
|
2020-10-09 19:04:29 +02:00
|
|
|
MCRegister PhysReg) {
|
2012-06-09 04:13:10 +02:00
|
|
|
if (VirtReg.empty())
|
|
|
|
return false;
|
2020-09-15 23:54:38 +02:00
|
|
|
CoalescerPair CP(VirtReg.reg(), PhysReg, *TRI);
|
2014-12-10 02:13:01 +01:00
|
|
|
|
|
|
|
bool Result = foreachUnit(TRI, VirtReg, PhysReg, [&](unsigned Unit,
|
|
|
|
const LiveRange &Range) {
|
|
|
|
const LiveRange &UnitRange = LIS->getRegUnit(Unit);
|
|
|
|
return Range.overlaps(UnitRange, CP, *LIS->getSlotIndexes());
|
|
|
|
});
|
|
|
|
return Result;
|
2012-06-09 04:13:10 +02:00
|
|
|
}
|
|
|
|
|
2017-03-02 01:35:08 +01:00
|
|
|
LiveIntervalUnion::Query &LiveRegMatrix::query(const LiveRange &LR,
|
2020-10-09 19:04:29 +02:00
|
|
|
MCRegister RegUnit) {
|
2012-06-09 04:13:10 +02:00
|
|
|
LiveIntervalUnion::Query &Q = Queries[RegUnit];
|
2017-03-02 01:35:08 +01:00
|
|
|
Q.init(UserTag, LR, Matrix[RegUnit]);
|
2012-06-09 04:13:10 +02:00
|
|
|
return Q;
|
|
|
|
}
|
|
|
|
|
|
|
|
LiveRegMatrix::InterferenceKind
|
2020-10-09 19:04:29 +02:00
|
|
|
LiveRegMatrix::checkInterference(LiveInterval &VirtReg, MCRegister PhysReg) {
|
2012-06-09 04:13:10 +02:00
|
|
|
if (VirtReg.empty())
|
|
|
|
return IK_Free;
|
|
|
|
|
|
|
|
// Regmask interference is the fastest check.
|
|
|
|
if (checkRegMaskInterference(VirtReg, PhysReg))
|
|
|
|
return IK_RegMask;
|
|
|
|
|
|
|
|
// Check for fixed interference.
|
|
|
|
if (checkRegUnitInterference(VirtReg, PhysReg))
|
|
|
|
return IK_RegUnit;
|
|
|
|
|
|
|
|
// Check the matrix for virtual register interference.
|
2017-03-02 01:35:08 +01:00
|
|
|
bool Interference = foreachUnit(TRI, VirtReg, PhysReg,
|
2020-10-09 19:04:29 +02:00
|
|
|
[&](MCRegister Unit, const LiveRange &LR) {
|
|
|
|
return query(LR, Unit).checkInterference();
|
|
|
|
});
|
2017-03-02 01:35:08 +01:00
|
|
|
if (Interference)
|
|
|
|
return IK_VirtReg;
|
2012-06-09 04:13:10 +02:00
|
|
|
|
|
|
|
return IK_Free;
|
|
|
|
}
|
2018-01-31 14:31:08 +01:00
|
|
|
|
|
|
|
bool LiveRegMatrix::checkInterference(SlotIndex Start, SlotIndex End,
|
2020-10-09 19:04:29 +02:00
|
|
|
MCRegister PhysReg) {
|
2018-01-31 14:31:08 +01:00
|
|
|
// Construct artificial live range containing only one segment [Start, End).
|
|
|
|
VNInfo valno(0, Start);
|
|
|
|
LiveRange::Segment Seg(Start, End, &valno);
|
|
|
|
LiveRange LR;
|
|
|
|
LR.addSegment(Seg);
|
|
|
|
|
|
|
|
// Check for interference with that segment
|
|
|
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
|
2021-03-09 05:55:53 +01:00
|
|
|
// LR is stack-allocated. LiveRegMatrix caches queries by a key that
|
|
|
|
// includes the address of the live range. If (for the same reg unit) this
|
|
|
|
// checkInterference overload is called twice, without any other query()
|
|
|
|
// calls in between (on heap-allocated LiveRanges) - which would invalidate
|
|
|
|
// the cached query - the LR address seen the second time may well be the
|
|
|
|
// same as that seen the first time, while the Start/End/valno may not - yet
|
|
|
|
// the same cached result would be fetched. To avoid that, we don't cache
|
|
|
|
// this query.
|
|
|
|
//
|
|
|
|
// FIXME: the usability of the Query API needs to be improved to avoid
|
|
|
|
// subtle bugs due to query identity. Avoiding caching, for example, would
|
|
|
|
// greatly simplify things.
|
|
|
|
LiveIntervalUnion::Query Q;
|
|
|
|
Q.reset(UserTag, LR, Matrix[*Units]);
|
|
|
|
if (Q.checkInterference())
|
2018-01-31 14:31:08 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2020-09-06 04:17:22 +02:00
|
|
|
|
|
|
|
Register LiveRegMatrix::getOneVReg(unsigned PhysReg) const {
|
|
|
|
LiveInterval *VRegInterval = nullptr;
|
|
|
|
for (MCRegUnitIterator Unit(PhysReg, TRI); Unit.isValid(); ++Unit) {
|
|
|
|
if ((VRegInterval = Matrix[*Unit].getOneVReg()))
|
|
|
|
return VRegInterval->reg();
|
|
|
|
}
|
|
|
|
|
|
|
|
return MCRegister::NoRegister;
|
|
|
|
}
|