summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/CodeGen/RegisterPressure.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/lib/CodeGen/RegisterPressure.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/lib/CodeGen/RegisterPressure.cpp')
-rw-r--r--contrib/llvm/lib/CodeGen/RegisterPressure.cpp496
1 files changed, 350 insertions, 146 deletions
diff --git a/contrib/llvm/lib/CodeGen/RegisterPressure.cpp b/contrib/llvm/lib/CodeGen/RegisterPressure.cpp
index 97f22e1..092ecdd 100644
--- a/contrib/llvm/lib/CodeGen/RegisterPressure.cpp
+++ b/contrib/llvm/lib/CodeGen/RegisterPressure.cpp
@@ -25,68 +25,39 @@ using namespace llvm;
/// Increase pressure for each pressure set provided by TargetRegisterInfo.
static void increaseSetPressure(std::vector<unsigned> &CurrSetPressure,
- std::vector<unsigned> &MaxSetPressure,
- const int *PSet, unsigned Weight) {
- for (; *PSet != -1; ++PSet) {
- CurrSetPressure[*PSet] += Weight;
- if (&CurrSetPressure != &MaxSetPressure
- && CurrSetPressure[*PSet] > MaxSetPressure[*PSet]) {
- MaxSetPressure[*PSet] = CurrSetPressure[*PSet];
- }
- }
+ PSetIterator PSetI) {
+ unsigned Weight = PSetI.getWeight();
+ for (; PSetI.isValid(); ++PSetI)
+ CurrSetPressure[*PSetI] += Weight;
}
/// Decrease pressure for each pressure set provided by TargetRegisterInfo.
static void decreaseSetPressure(std::vector<unsigned> &CurrSetPressure,
- const int *PSet, unsigned Weight) {
- for (; *PSet != -1; ++PSet) {
- assert(CurrSetPressure[*PSet] >= Weight && "register pressure underflow");
- CurrSetPressure[*PSet] -= Weight;
- }
-}
-
-/// Directly increase pressure only within this RegisterPressure result.
-void RegisterPressure::increase(unsigned Reg, const TargetRegisterInfo *TRI,
- const MachineRegisterInfo *MRI) {
- if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- const TargetRegisterClass *RC = MRI->getRegClass(Reg);
- increaseSetPressure(MaxSetPressure, MaxSetPressure,
- TRI->getRegClassPressureSets(RC),
- TRI->getRegClassWeight(RC).RegWeight);
- }
- else {
- increaseSetPressure(MaxSetPressure, MaxSetPressure,
- TRI->getRegUnitPressureSets(Reg),
- TRI->getRegUnitWeight(Reg));
- }
-}
-
-/// Directly decrease pressure only within this RegisterPressure result.
-void RegisterPressure::decrease(unsigned Reg, const TargetRegisterInfo *TRI,
- const MachineRegisterInfo *MRI) {
- if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- const TargetRegisterClass *RC = MRI->getRegClass(Reg);
- decreaseSetPressure(MaxSetPressure, TRI->getRegClassPressureSets(RC),
- TRI->getRegClassWeight(RC).RegWeight);
- }
- else {
- decreaseSetPressure(MaxSetPressure, TRI->getRegUnitPressureSets(Reg),
- TRI->getRegUnitWeight(Reg));
+ PSetIterator PSetI) {
+ unsigned Weight = PSetI.getWeight();
+ for (; PSetI.isValid(); ++PSetI) {
+ assert(CurrSetPressure[*PSetI] >= Weight && "register pressure underflow");
+ CurrSetPressure[*PSetI] -= Weight;
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-static void dumpSetPressure(const std::vector<unsigned> &SetPressure,
- const TargetRegisterInfo *TRI) {
+void llvm::dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
+ const TargetRegisterInfo *TRI) {
+ bool Empty = true;
for (unsigned i = 0, e = SetPressure.size(); i < e; ++i) {
- if (SetPressure[i] != 0)
+ if (SetPressure[i] != 0) {
dbgs() << TRI->getRegPressureSetName(i) << "=" << SetPressure[i] << '\n';
+ Empty = false;
+ }
}
+ if (Empty)
+ dbgs() << "\n";
}
void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
dbgs() << "Max Pressure: ";
- dumpSetPressure(MaxSetPressure, TRI);
+ dumpRegSetPressure(MaxSetPressure, TRI);
dbgs() << "Live In: ";
for (unsigned i = 0, e = LiveInRegs.size(); i < e; ++i)
dbgs() << PrintReg(LiveInRegs[i], TRI) << " ";
@@ -98,44 +69,33 @@ void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
}
void RegPressureTracker::dump() const {
- dbgs() << "Curr Pressure: ";
- dumpSetPressure(CurrSetPressure, TRI);
+ if (!isTopClosed() || !isBottomClosed()) {
+ dbgs() << "Curr Pressure: ";
+ dumpRegSetPressure(CurrSetPressure, TRI);
+ }
P.dump(TRI);
}
#endif
/// Increase the current pressure as impacted by these registers and bump
/// the high water mark if needed.
-void RegPressureTracker::increaseRegPressure(ArrayRef<unsigned> Regs) {
- for (unsigned I = 0, E = Regs.size(); I != E; ++I) {
- if (TargetRegisterInfo::isVirtualRegister(Regs[I])) {
- const TargetRegisterClass *RC = MRI->getRegClass(Regs[I]);
- increaseSetPressure(CurrSetPressure, P.MaxSetPressure,
- TRI->getRegClassPressureSets(RC),
- TRI->getRegClassWeight(RC).RegWeight);
- }
- else {
- increaseSetPressure(CurrSetPressure, P.MaxSetPressure,
- TRI->getRegUnitPressureSets(Regs[I]),
- TRI->getRegUnitWeight(Regs[I]));
+void RegPressureTracker::increaseRegPressure(ArrayRef<unsigned> RegUnits) {
+ for (unsigned i = 0, e = RegUnits.size(); i != e; ++i) {
+ PSetIterator PSetI = MRI->getPressureSets(RegUnits[i]);
+ unsigned Weight = PSetI.getWeight();
+ for (; PSetI.isValid(); ++PSetI) {
+ CurrSetPressure[*PSetI] += Weight;
+ if (CurrSetPressure[*PSetI] > P.MaxSetPressure[*PSetI]) {
+ P.MaxSetPressure[*PSetI] = CurrSetPressure[*PSetI];
+ }
}
}
}
/// Simply decrease the current pressure as impacted by these registers.
-void RegPressureTracker::decreaseRegPressure(ArrayRef<unsigned> Regs) {
- for (unsigned I = 0, E = Regs.size(); I != E; ++I) {
- if (TargetRegisterInfo::isVirtualRegister(Regs[I])) {
- const TargetRegisterClass *RC = MRI->getRegClass(Regs[I]);
- decreaseSetPressure(CurrSetPressure,
- TRI->getRegClassPressureSets(RC),
- TRI->getRegClassWeight(RC).RegWeight);
- }
- else {
- decreaseSetPressure(CurrSetPressure, TRI->getRegUnitPressureSets(Regs[I]),
- TRI->getRegUnitWeight(Regs[I]));
- }
- }
+void RegPressureTracker::decreaseRegPressure(ArrayRef<unsigned> RegUnits) {
+ for (unsigned I = 0, E = RegUnits.size(); I != E; ++I)
+ decreaseSetPressure(CurrSetPressure, MRI->getPressureSets(RegUnits[I]));
}
/// Clear the result so it can be used for another round of pressure tracking.
@@ -187,12 +147,30 @@ void RegionPressure::openBottom(MachineBasicBlock::const_iterator PrevBottom) {
LiveInRegs.clear();
}
-const LiveInterval *RegPressureTracker::getInterval(unsigned Reg) const {
+const LiveRange *RegPressureTracker::getLiveRange(unsigned Reg) const {
if (TargetRegisterInfo::isVirtualRegister(Reg))
return &LIS->getInterval(Reg);
return LIS->getCachedRegUnit(Reg);
}
+void RegPressureTracker::reset() {
+ MBB = 0;
+ LIS = 0;
+
+ CurrSetPressure.clear();
+ LiveThruPressure.clear();
+ P.MaxSetPressure.clear();
+
+ if (RequireIntervals)
+ static_cast<IntervalPressure&>(P).reset();
+ else
+ static_cast<RegionPressure&>(P).reset();
+
+ LiveRegs.PhysRegs.clear();
+ LiveRegs.VirtRegs.clear();
+ UntiedDefs.clear();
+}
+
/// Setup the RegPressureTracker.
///
/// TODO: Add support for pressure without LiveIntervals.
@@ -200,13 +178,17 @@ void RegPressureTracker::init(const MachineFunction *mf,
const RegisterClassInfo *rci,
const LiveIntervals *lis,
const MachineBasicBlock *mbb,
- MachineBasicBlock::const_iterator pos)
+ MachineBasicBlock::const_iterator pos,
+ bool ShouldTrackUntiedDefs)
{
+ reset();
+
MF = mf;
TRI = MF->getTarget().getRegisterInfo();
RCI = rci;
MRI = &MF->getRegInfo();
MBB = mbb;
+ TrackUntiedDefs = ShouldTrackUntiedDefs;
if (RequireIntervals) {
assert(lis && "IntervalPressure requires LiveIntervals");
@@ -216,16 +198,12 @@ void RegPressureTracker::init(const MachineFunction *mf,
CurrPos = pos;
CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0);
- if (RequireIntervals)
- static_cast<IntervalPressure&>(P).reset();
- else
- static_cast<RegionPressure&>(P).reset();
P.MaxSetPressure = CurrSetPressure;
- LiveRegs.PhysRegs.clear();
LiveRegs.PhysRegs.setUniverse(TRI->getNumRegs());
- LiveRegs.VirtRegs.clear();
LiveRegs.VirtRegs.setUniverse(MRI->getNumVirtRegs());
+ if (TrackUntiedDefs)
+ UntiedDefs.setUniverse(MRI->getNumVirtRegs());
}
/// Does this pressure result have a valid top position and live ins.
@@ -304,16 +282,36 @@ void RegPressureTracker::closeRegion() {
// If both top and bottom are closed, do nothing.
}
+/// The register tracker is unaware of global liveness so ignores normal
+/// live-thru ranges. However, two-address or coalesced chains can also lead
+/// to live ranges with no holes. Count these to inform heuristics that we
+/// can never drop below this pressure.
+void RegPressureTracker::initLiveThru(const RegPressureTracker &RPTracker) {
+ LiveThruPressure.assign(TRI->getNumRegPressureSets(), 0);
+ assert(isBottomClosed() && "need bottom-up tracking to intialize.");
+ for (unsigned i = 0, e = P.LiveOutRegs.size(); i < e; ++i) {
+ unsigned Reg = P.LiveOutRegs[i];
+ if (TargetRegisterInfo::isVirtualRegister(Reg)
+ && !RPTracker.hasUntiedDef(Reg)) {
+ increaseSetPressure(LiveThruPressure, MRI->getPressureSets(Reg));
+ }
+ }
+}
+
/// \brief Convenient wrapper for checking membership in RegisterOperands.
-static bool containsReg(ArrayRef<unsigned> Regs, unsigned Reg) {
- return std::find(Regs.begin(), Regs.end(), Reg) != Regs.end();
+/// (std::count() doesn't have an early exit).
+static bool containsReg(ArrayRef<unsigned> RegUnits, unsigned RegUnit) {
+ return std::find(RegUnits.begin(), RegUnits.end(), RegUnit) != RegUnits.end();
}
/// Collect this instruction's unique uses and defs into SmallVectors for
/// processing defs and uses in order.
+///
+/// FIXME: always ignore tied opers
class RegisterOperands {
const TargetRegisterInfo *TRI;
const MachineRegisterInfo *MRI;
+ bool IgnoreDead;
public:
SmallVector<unsigned, 8> Uses;
@@ -321,7 +319,8 @@ public:
SmallVector<unsigned, 8> DeadDefs;
RegisterOperands(const TargetRegisterInfo *tri,
- const MachineRegisterInfo *mri): TRI(tri), MRI(mri) {}
+ const MachineRegisterInfo *mri, bool ID = false):
+ TRI(tri), MRI(mri), IgnoreDead(ID) {}
/// Push this operand's register onto the correct vector.
void collect(const MachineOperand &MO) {
@@ -330,25 +329,27 @@ public:
if (MO.readsReg())
pushRegUnits(MO.getReg(), Uses);
if (MO.isDef()) {
- if (MO.isDead())
- pushRegUnits(MO.getReg(), DeadDefs);
+ if (MO.isDead()) {
+ if (!IgnoreDead)
+ pushRegUnits(MO.getReg(), DeadDefs);
+ }
else
pushRegUnits(MO.getReg(), Defs);
}
}
protected:
- void pushRegUnits(unsigned Reg, SmallVectorImpl<unsigned> &Regs) {
+ void pushRegUnits(unsigned Reg, SmallVectorImpl<unsigned> &RegUnits) {
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- if (containsReg(Regs, Reg))
+ if (containsReg(RegUnits, Reg))
return;
- Regs.push_back(Reg);
+ RegUnits.push_back(Reg);
}
else if (MRI->isAllocatable(Reg)) {
for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
- if (containsReg(Regs, *Units))
+ if (containsReg(RegUnits, *Units))
continue;
- Regs.push_back(*Units);
+ RegUnits.push_back(*Units);
}
}
}
@@ -367,6 +368,56 @@ static void collectOperands(const MachineInstr *MI,
RegOpers.DeadDefs.erase(I, RegOpers.DeadDefs.end());
}
+/// Initialize an array of N PressureDiffs.
+void PressureDiffs::init(unsigned N) {
+ Size = N;
+ if (N <= Max) {
+ memset(PDiffArray, 0, N * sizeof(PressureDiff));
+ return;
+ }
+ Max = Size;
+ free(PDiffArray);
+ PDiffArray = reinterpret_cast<PressureDiff*>(calloc(N, sizeof(PressureDiff)));
+}
+
+/// Add a change in pressure to the pressure diff of a given instruction.
+void PressureDiff::addPressureChange(unsigned RegUnit, bool IsDec,
+ const MachineRegisterInfo *MRI) {
+ PSetIterator PSetI = MRI->getPressureSets(RegUnit);
+ int Weight = IsDec ? -PSetI.getWeight() : PSetI.getWeight();
+ for (; PSetI.isValid(); ++PSetI) {
+ // Find an existing entry in the pressure diff for this PSet.
+ PressureDiff::iterator I = begin(), E = end();
+ for (; I != E && I->isValid(); ++I) {
+ if (I->getPSet() >= *PSetI)
+ break;
+ }
+ // If all pressure sets are more constrained, skip the remaining PSets.
+ if (I == E)
+ break;
+ // Insert this PressureChange.
+ if (!I->isValid() || I->getPSet() != *PSetI) {
+ PressureChange PTmp = PressureChange(*PSetI);
+ for (PressureDiff::iterator J = I; J != E && PTmp.isValid(); ++J)
+ std::swap(*J,PTmp);
+ }
+ // Update the units for this pressure set.
+ I->setUnitInc(I->getUnitInc() + Weight);
+ }
+}
+
+/// Record the pressure difference induced by the given operand list.
+static void collectPDiff(PressureDiff &PDiff, RegisterOperands &RegOpers,
+ const MachineRegisterInfo *MRI) {
+ assert(!PDiff.begin()->isValid() && "stale PDiff");
+
+ for (unsigned i = 0, e = RegOpers.Defs.size(); i != e; ++i)
+ PDiff.addPressureChange(RegOpers.Defs[i], true, MRI);
+
+ for (unsigned i = 0, e = RegOpers.Uses.size(); i != e; ++i)
+ PDiff.addPressureChange(RegOpers.Uses[i], false, MRI);
+}
+
/// Force liveness of registers.
void RegPressureTracker::addLiveRegs(ArrayRef<unsigned> Regs) {
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
@@ -383,7 +434,7 @@ void RegPressureTracker::discoverLiveIn(unsigned Reg) {
// At live in discovery, unconditionally increase the high water mark.
P.LiveInRegs.push_back(Reg);
- P.increase(Reg, TRI, MRI);
+ increaseSetPressure(P.MaxSetPressure, MRI->getPressureSets(Reg));
}
/// Add Reg to the live out set and increase max pressure.
@@ -394,11 +445,16 @@ void RegPressureTracker::discoverLiveOut(unsigned Reg) {
// At live out discovery, unconditionally increase the high water mark.
P.LiveOutRegs.push_back(Reg);
- P.increase(Reg, TRI, MRI);
+ increaseSetPressure(P.MaxSetPressure, MRI->getPressureSets(Reg));
}
-/// Recede across the previous instruction.
-bool RegPressureTracker::recede() {
+/// Recede across the previous instruction. If LiveUses is provided, record any
+/// RegUnits that are made live by the current instruction's uses. This includes
+/// registers that are both defined and used by the instruction. If a pressure
+/// difference pointer is provided record the changes is pressure caused by this
+/// instruction independent of liveness.
+bool RegPressureTracker::recede(SmallVectorImpl<unsigned> *LiveUses,
+ PressureDiff *PDiff) {
// Check for the top of the analyzable region.
if (CurrPos == MBB->begin()) {
closeRegion();
@@ -431,6 +487,9 @@ bool RegPressureTracker::recede() {
RegisterOperands RegOpers(TRI, MRI);
collectOperands(CurrPos, RegOpers);
+ if (PDiff)
+ collectPDiff(*PDiff, RegOpers, MRI);
+
// Boost pressure for all dead defs together.
increaseRegPressure(RegOpers.DeadDefs);
decreaseRegPressure(RegOpers.DeadDefs);
@@ -439,10 +498,20 @@ bool RegPressureTracker::recede() {
// TODO: consider earlyclobbers?
for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
unsigned Reg = RegOpers.Defs[i];
- if (LiveRegs.erase(Reg))
- decreaseRegPressure(Reg);
- else
- discoverLiveOut(Reg);
+ bool DeadDef = false;
+ if (RequireIntervals) {
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ DeadDef = LRQ.isDeadDef();
+ }
+ }
+ if (!DeadDef) {
+ if (LiveRegs.erase(Reg))
+ decreaseRegPressure(Reg);
+ else
+ discoverLiveOut(Reg);
+ }
}
// Generate liveness for uses.
@@ -451,12 +520,24 @@ bool RegPressureTracker::recede() {
if (!LiveRegs.contains(Reg)) {
// Adjust liveouts if LiveIntervals are available.
if (RequireIntervals) {
- const LiveInterval *LI = getInterval(Reg);
- if (LI && !LI->killedAt(SlotIdx))
- discoverLiveOut(Reg);
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ if (!LRQ.isKill() && !LRQ.valueDefined())
+ discoverLiveOut(Reg);
+ }
}
increaseRegPressure(Reg);
LiveRegs.insert(Reg);
+ if (LiveUses && !containsReg(*LiveUses, Reg))
+ LiveUses->push_back(Reg);
+ }
+ }
+ if (TrackUntiedDefs) {
+ for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
+ unsigned Reg = RegOpers.Defs[i];
+ if (TargetRegisterInfo::isVirtualRegister(Reg) && !LiveRegs.contains(Reg))
+ UntiedDefs.insert(Reg);
}
}
return true;
@@ -464,6 +545,8 @@ bool RegPressureTracker::recede() {
/// Advance across the current instruction.
bool RegPressureTracker::advance() {
+ assert(!TrackUntiedDefs && "unsupported mode");
+
// Check for the bottom of the analyzable region.
if (CurrPos == MBB->end()) {
closeRegion();
@@ -496,8 +579,8 @@ bool RegPressureTracker::advance() {
// Kill liveness at last uses.
bool lastUse = false;
if (RequireIntervals) {
- const LiveInterval *LI = getInterval(Reg);
- lastUse = LI && LI->killedAt(SlotIdx);
+ const LiveRange *LR = getLiveRange(Reg);
+ lastUse = LR && LR->Query(SlotIdx).isKill();
}
else {
// Allocatable physregs are always single-use before register rewriting.
@@ -533,9 +616,9 @@ bool RegPressureTracker::advance() {
static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
ArrayRef<unsigned> NewPressureVec,
RegPressureDelta &Delta,
- const TargetRegisterInfo *TRI) {
- int ExcessUnits = 0;
- unsigned PSetID = ~0U;
+ const RegisterClassInfo *RCI,
+ ArrayRef<unsigned> LiveThruPressureVec) {
+ Delta.Excess = PressureChange();
for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
unsigned POld = OldPressureVec[i];
unsigned PNew = NewPressureVec[i];
@@ -543,7 +626,10 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
if (!PDiff) // No change in this set in the common case.
continue;
// Only consider change beyond the limit.
- unsigned Limit = TRI->getRegPressureSetLimit(i);
+ unsigned Limit = RCI->getRegPressureSetLimit(i);
+ if (!LiveThruPressureVec.empty())
+ Limit += LiveThruPressureVec[i];
+
if (Limit > POld) {
if (Limit > PNew)
PDiff = 0; // Under the limit
@@ -553,13 +639,12 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
else if (Limit > PNew)
PDiff = Limit - POld; // Just obeyed limit.
- if (std::abs(PDiff) > std::abs(ExcessUnits)) {
- ExcessUnits = PDiff;
- PSetID = i;
+ if (PDiff) {
+ Delta.Excess = PressureChange(i);
+ Delta.Excess.setUnitInc(PDiff);
+ break;
}
}
- Delta.Excess.PSetID = PSetID;
- Delta.Excess.UnitIncrease = ExcessUnits;
}
/// Find the max change in max pressure that either surpasses a critical PSet
@@ -570,11 +655,11 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
/// RegPressureTracker API change to work with pressure differences.
static void computeMaxPressureDelta(ArrayRef<unsigned> OldMaxPressureVec,
ArrayRef<unsigned> NewMaxPressureVec,
- ArrayRef<PressureElement> CriticalPSets,
+ ArrayRef<PressureChange> CriticalPSets,
ArrayRef<unsigned> MaxPressureLimit,
RegPressureDelta &Delta) {
- Delta.CriticalMax = PressureElement();
- Delta.CurrentMax = PressureElement();
+ Delta.CriticalMax = PressureChange();
+ Delta.CurrentMax = PressureChange();
unsigned CritIdx = 0, CritEnd = CriticalPSets.size();
for (unsigned i = 0, e = OldMaxPressureVec.size(); i < e; ++i) {
@@ -583,23 +668,25 @@ static void computeMaxPressureDelta(ArrayRef<unsigned> OldMaxPressureVec,
if (PNew == POld) // No change in this set in the common case.
continue;
- while (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID < i)
- ++CritIdx;
+ if (!Delta.CriticalMax.isValid()) {
+ while (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() < i)
+ ++CritIdx;
- if (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID == i) {
- int PDiff = (int)PNew - (int)CriticalPSets[CritIdx].UnitIncrease;
- if (PDiff > Delta.CriticalMax.UnitIncrease) {
- Delta.CriticalMax.PSetID = i;
- Delta.CriticalMax.UnitIncrease = PDiff;
+ if (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() == i) {
+ int PDiff = (int)PNew - (int)CriticalPSets[CritIdx].getUnitInc();
+ if (PDiff > 0) {
+ Delta.CriticalMax = PressureChange(i);
+ Delta.CriticalMax.setUnitInc(PDiff);
+ }
}
}
-
- // Find the greatest increase above MaxPressureLimit.
+ // Find the first increase above MaxPressureLimit.
// (Ignores negative MDiff).
- int MDiff = (int)PNew - (int)MaxPressureLimit[i];
- if (MDiff > Delta.CurrentMax.UnitIncrease) {
- Delta.CurrentMax.PSetID = i;
- Delta.CurrentMax.UnitIncrease = PNew;
+ if (!Delta.CurrentMax.isValid() && PNew > MaxPressureLimit[i]) {
+ Delta.CurrentMax = PressureChange(i);
+ Delta.CurrentMax.setUnitInc(PNew - POld);
+ if (CritIdx == CritEnd || Delta.CriticalMax.isValid())
+ break;
}
}
}
@@ -614,7 +701,7 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
assert(!MI->isDebugValue() && "Expect a nondebug instruction.");
// Account for register pressure similar to RegPressureTracker::recede().
- RegisterOperands RegOpers(TRI, MRI);
+ RegisterOperands RegOpers(TRI, MRI, /*IgnoreDead=*/true);
collectOperands(MI, RegOpers);
// Boost max pressure for all dead defs together.
@@ -625,8 +712,19 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
// Kill liveness at live defs.
for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
unsigned Reg = RegOpers.Defs[i];
- if (!containsReg(RegOpers.Uses, Reg))
- decreaseRegPressure(Reg);
+ bool DeadDef = false;
+ if (RequireIntervals) {
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ SlotIndex SlotIdx = LIS->getInstructionIndex(MI);
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ DeadDef = LRQ.isDeadDef();
+ }
+ }
+ if (!DeadDef) {
+ if (!containsReg(RegOpers.Uses, Reg))
+ decreaseRegPressure(Reg);
+ }
}
// Generate liveness for uses.
for (unsigned i = 0, e = RegOpers.Uses.size(); i < e; ++i) {
@@ -648,8 +746,9 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
/// result per-SUnit with enough information to adjust for the current
/// scheduling position. But this works as a proof of concept.
void RegPressureTracker::
-getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
- ArrayRef<PressureElement> CriticalPSets,
+getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff,
+ RegPressureDelta &Delta,
+ ArrayRef<PressureChange> CriticalPSets,
ArrayRef<unsigned> MaxPressureLimit) {
// Snapshot Pressure.
// FIXME: The snapshot heap space should persist. But I'm planning to
@@ -659,15 +758,117 @@ getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
bumpUpwardPressure(MI);
- computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, TRI);
+ computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
+ LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta);
- assert(Delta.CriticalMax.UnitIncrease >= 0 &&
- Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
+ assert(Delta.CriticalMax.getUnitInc() >= 0 &&
+ Delta.CurrentMax.getUnitInc() >= 0 && "cannot decrease max pressure");
// Restore the tracker's state.
P.MaxSetPressure.swap(SavedMaxPressure);
CurrSetPressure.swap(SavedPressure);
+
+#ifndef NDEBUG
+ if (!PDiff)
+ return;
+
+ // Check if the alternate algorithm yields the same result.
+ RegPressureDelta Delta2;
+ getUpwardPressureDelta(MI, *PDiff, Delta2, CriticalPSets, MaxPressureLimit);
+ if (Delta != Delta2) {
+ dbgs() << "DELTA: " << *MI;
+ if (Delta.Excess.isValid())
+ dbgs() << "Excess1 " << TRI->getRegPressureSetName(Delta.Excess.getPSet())
+ << " " << Delta.Excess.getUnitInc() << "\n";
+ if (Delta.CriticalMax.isValid())
+ dbgs() << "Critic1 " << TRI->getRegPressureSetName(Delta.CriticalMax.getPSet())
+ << " " << Delta.CriticalMax.getUnitInc() << "\n";
+ if (Delta.CurrentMax.isValid())
+ dbgs() << "CurrMx1 " << TRI->getRegPressureSetName(Delta.CurrentMax.getPSet())
+ << " " << Delta.CurrentMax.getUnitInc() << "\n";
+ if (Delta2.Excess.isValid())
+ dbgs() << "Excess2 " << TRI->getRegPressureSetName(Delta2.Excess.getPSet())
+ << " " << Delta2.Excess.getUnitInc() << "\n";
+ if (Delta2.CriticalMax.isValid())
+ dbgs() << "Critic2 " << TRI->getRegPressureSetName(Delta2.CriticalMax.getPSet())
+ << " " << Delta2.CriticalMax.getUnitInc() << "\n";
+ if (Delta2.CurrentMax.isValid())
+ dbgs() << "CurrMx2 " << TRI->getRegPressureSetName(Delta2.CurrentMax.getPSet())
+ << " " << Delta2.CurrentMax.getUnitInc() << "\n";
+ llvm_unreachable("RegP Delta Mismatch");
+ }
+#endif
+}
+
+/// This is a prototype of the fast version of querying register pressure that
+/// does not directly depend on current liveness. It's still slow because we
+/// recompute pressure change on-the-fly. This implementation only exists to
+/// prove correctness.
+///
+/// @param Delta captures information needed for heuristics.
+///
+/// @param CriticalPSets Are the pressure sets that are known to exceed some
+/// limit within the region, not necessarily at the current position.
+///
+/// @param MaxPressureLimit Is the max pressure within the region, not
+/// necessarily at the current position.
+void RegPressureTracker::
+getUpwardPressureDelta(const MachineInstr *MI, /*const*/ PressureDiff &PDiff,
+ RegPressureDelta &Delta,
+ ArrayRef<PressureChange> CriticalPSets,
+ ArrayRef<unsigned> MaxPressureLimit) const {
+ unsigned CritIdx = 0, CritEnd = CriticalPSets.size();
+ for (PressureDiff::const_iterator
+ PDiffI = PDiff.begin(), PDiffE = PDiff.end();
+ PDiffI != PDiffE && PDiffI->isValid(); ++PDiffI) {
+
+ unsigned PSetID = PDiffI->getPSet();
+ unsigned Limit = RCI->getRegPressureSetLimit(PSetID);
+ if (!LiveThruPressure.empty())
+ Limit += LiveThruPressure[PSetID];
+
+ unsigned POld = CurrSetPressure[PSetID];
+ unsigned MOld = P.MaxSetPressure[PSetID];
+ unsigned MNew = MOld;
+ // Ignore DeadDefs here because they aren't captured by PressureChange.
+ unsigned PNew = POld + PDiffI->getUnitInc();
+ assert((PDiffI->getUnitInc() >= 0) == (PNew >= POld) && "PSet overflow");
+ if (PNew > MOld)
+ MNew = PNew;
+ // Check if current pressure has exceeded the limit.
+ if (!Delta.Excess.isValid()) {
+ unsigned ExcessInc = 0;
+ if (PNew > Limit)
+ ExcessInc = POld > Limit ? PNew - POld : PNew - Limit;
+ else if (POld > Limit)
+ ExcessInc = Limit - POld;
+ if (ExcessInc) {
+ Delta.Excess = PressureChange(PSetID);
+ Delta.Excess.setUnitInc(ExcessInc);
+ }
+ }
+ // Check if max pressure has exceeded a critical pressure set max.
+ if (MNew == MOld)
+ continue;
+ if (!Delta.CriticalMax.isValid()) {
+ while (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() < PSetID)
+ ++CritIdx;
+
+ if (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() == PSetID) {
+ int CritInc = (int)MNew - (int)CriticalPSets[CritIdx].getUnitInc();
+ if (CritInc > 0 && CritInc <= INT16_MAX) {
+ Delta.CriticalMax = PressureChange(PSetID);
+ Delta.CriticalMax.setUnitInc(CritInc);
+ }
+ }
+ }
+ // Check if max pressure has exceeded the current max.
+ if (!Delta.CurrentMax.isValid() && MNew > MaxPressureLimit[PSetID]) {
+ Delta.CurrentMax = PressureChange(PSetID);
+ Delta.CurrentMax.setUnitInc(MNew - MOld);
+ }
+ }
}
/// Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx).
@@ -713,10 +914,12 @@ void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) {
// FIXME: allow the caller to pass in the list of vreg uses that remain
// to be bottom-scheduled to avoid searching uses at each query.
SlotIndex CurrIdx = getCurrSlot();
- const LiveInterval *LI = getInterval(Reg);
- if (LI && LI->killedAt(SlotIdx)
- && !findUseBetween(Reg, CurrIdx, SlotIdx, MRI, LIS)) {
- decreaseRegPressure(Reg);
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ if (LRQ.isKill() && !findUseBetween(Reg, CurrIdx, SlotIdx, MRI, LIS)) {
+ decreaseRegPressure(Reg);
+ }
}
}
else if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
@@ -741,7 +944,7 @@ void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) {
/// This assumes that the current LiveIn set is sufficient.
void RegPressureTracker::
getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
- ArrayRef<PressureElement> CriticalPSets,
+ ArrayRef<PressureChange> CriticalPSets,
ArrayRef<unsigned> MaxPressureLimit) {
// Snapshot Pressure.
std::vector<unsigned> SavedPressure = CurrSetPressure;
@@ -749,11 +952,12 @@ getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
bumpDownwardPressure(MI);
- computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, TRI);
+ computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
+ LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta);
- assert(Delta.CriticalMax.UnitIncrease >= 0 &&
- Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
+ assert(Delta.CriticalMax.getUnitInc() >= 0 &&
+ Delta.CurrentMax.getUnitInc() >= 0 && "cannot decrease max pressure");
// Restore the tracker's state.
P.MaxSetPressure.swap(SavedMaxPressure);
OpenPOWER on IntegriCloud