1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[PHIElimination] Compile time optimization for huge functions.

This is a compile-time optimization for PHIElimination (splitting of critical
edges), which was reported at https://bugs.llvm.org/show_bug.cgi?id=44249. As
discussed there, the way to remedy the slowdowns with huge functions is to
pre-compute the live-in registers for each MBB in an efficient way in
PHIElimination.cpp and then pass that information along to
LiveVariabless::addNewBlock().

In all the huge test programs where this slowdown has been noticable, it has
dissapeared entirely with this patch.

Review: Björn Pettersson, Quentin Colombet.

Differential Revision: https://reviews.llvm.org/D73152
This commit is contained in:
Jonas Paulsson 2020-01-20 21:56:09 +01:00
parent 65c511b539
commit 7a5c44c970
5 changed files with 81 additions and 11 deletions

View File

@ -297,6 +297,11 @@ public:
MachineBasicBlock *DomBB,
MachineBasicBlock *SuccBB);
void addNewBlock(MachineBasicBlock *BB,
MachineBasicBlock *DomBB,
MachineBasicBlock *SuccBB,
std::vector<SparseBitVector<>> &LiveInSets);
/// isPHIJoin - Return true if Reg is a phi join register.
bool isPHIJoin(unsigned Reg) { return PHIJoins.test(Reg); }

View File

@ -18,6 +18,7 @@
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/simple_ilist.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/IR/DebugLoc.h"
@ -588,7 +589,9 @@ public:
///
/// This function updates LiveVariables, MachineDominatorTree, and
/// MachineLoopInfo, as applicable.
MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P);
MachineBasicBlock *
SplitCriticalEdge(MachineBasicBlock *Succ, Pass &P,
std::vector<SparseBitVector<>> *LiveInSets = nullptr);
/// Check if the edge between this block and the given successor \p
/// Succ, can be split. If this returns true a subsequent call to

View File

@ -806,3 +806,30 @@ void LiveVariables::addNewBlock(MachineBasicBlock *BB,
VI.AliveBlocks.set(NumNew);
}
}
/// addNewBlock - Add a new basic block BB as an empty succcessor to DomBB. All
/// variables that are live out of DomBB will be marked as passing live through
/// BB. LiveInSets[BB] is *not* updated (because it is not needed during
/// PHIElimination).
void LiveVariables::addNewBlock(MachineBasicBlock *BB,
MachineBasicBlock *DomBB,
MachineBasicBlock *SuccBB,
std::vector<SparseBitVector<>> &LiveInSets) {
const unsigned NumNew = BB->getNumber();
SparseBitVector<> &BV = LiveInSets[SuccBB->getNumber()];
for (auto R = BV.begin(), E = BV.end(); R != E; R++) {
unsigned VirtReg = Register::index2VirtReg(*R);
LiveVariables::VarInfo &VI = getVarInfo(VirtReg);
VI.AliveBlocks.set(NumNew);
}
// All registers used by PHI nodes in SuccBB must be live through BB.
for (MachineBasicBlock::iterator BBI = SuccBB->begin(),
BBE = SuccBB->end();
BBI != BBE && BBI->isPHI(); ++BBI) {
for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2)
if (BBI->getOperand(i + 1).getMBB() == BB)
getVarInfo(BBI->getOperand(i).getReg())
.AliveBlocks.set(NumNew);
}
}

View File

@ -871,8 +871,9 @@ bool MachineBasicBlock::canFallThrough() {
return getFallThrough() != nullptr;
}
MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ,
Pass &P) {
MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
MachineBasicBlock *Succ, Pass &P,
std::vector<SparseBitVector<>> *LiveInSets) {
if (!canSplitCriticalEdge(Succ))
return nullptr;
@ -1003,7 +1004,10 @@ MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ,
}
}
// Update relevant live-through information.
LV->addNewBlock(NMBB, this, Succ);
if (LiveInSets != nullptr)
LV->addNewBlock(NMBB, this, Succ, *LiveInSets);
else
LV->addNewBlock(NMBB, this, Succ);
}
if (LIS) {

View File

@ -96,7 +96,8 @@ namespace {
/// Split critical edges where necessary for good coalescer performance.
bool SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB,
MachineLoopInfo *MLI);
MachineLoopInfo *MLI,
std::vector<SparseBitVector<>> *LiveInSets);
// These functions are temporary abstractions around LiveVariables and
// LiveIntervals, so they can go away when LiveVariables does.
@ -151,16 +152,45 @@ bool PHIElimination::runOnMachineFunction(MachineFunction &MF) {
bool Changed = false;
// This pass takes the function out of SSA form.
MRI->leaveSSA();
// Split critical edges to help the coalescer.
if (!DisableEdgeSplitting && (LV || LIS)) {
// A set of live-in regs for each MBB which is used to update LV
// efficiently also with large functions.
std::vector<SparseBitVector<>> LiveInSets;
if (LV) {
LiveInSets.resize(MF.size());
for (unsigned Index = 0, e = MRI->getNumVirtRegs(); Index != e; ++Index) {
// Set the bit for this register for each MBB where it is
// live-through or live-in (killed).
unsigned VirtReg = Register::index2VirtReg(Index);
MachineInstr *DefMI = MRI->getVRegDef(VirtReg);
if (!DefMI)
continue;
LiveVariables::VarInfo &VI = LV->getVarInfo(VirtReg);
SparseBitVector<>::iterator AliveBlockItr = VI.AliveBlocks.begin();
SparseBitVector<>::iterator EndItr = VI.AliveBlocks.end();
while (AliveBlockItr != EndItr) {
unsigned BlockNum = *(AliveBlockItr++);
LiveInSets[BlockNum].set(Index);
}
// The register is live into an MBB in which it is killed but not
// defined. See comment for VarInfo in LiveVariables.h.
MachineBasicBlock *DefMBB = DefMI->getParent();
if (VI.Kills.size() > 1 ||
(!VI.Kills.empty() && VI.Kills.front()->getParent() != DefMBB))
for (auto *MI : VI.Kills)
LiveInSets[MI->getParent()->getNumber()].set(Index);
}
}
MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
for (auto &MBB : MF)
Changed |= SplitPHIEdges(MF, MBB, MLI);
Changed |= SplitPHIEdges(MF, MBB, MLI, (LV ? &LiveInSets : nullptr));
}
// This pass takes the function out of SSA form.
MRI->leaveSSA();
// Populate VRegPHIUseCount
analyzePHINodes(MF);
@ -561,7 +591,8 @@ void PHIElimination::analyzePHINodes(const MachineFunction& MF) {
bool PHIElimination::SplitPHIEdges(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineLoopInfo *MLI) {
MachineLoopInfo *MLI,
std::vector<SparseBitVector<>> *LiveInSets) {
if (MBB.empty() || !MBB.front().isPHI() || MBB.isEHPad())
return false; // Quick exit for basic blocks without PHIs.
@ -628,7 +659,7 @@ bool PHIElimination::SplitPHIEdges(MachineFunction &MF,
}
if (!ShouldSplit && !SplitAllCriticalEdges)
continue;
if (!PreMBB->SplitCriticalEdge(&MBB, *this)) {
if (!PreMBB->SplitCriticalEdge(&MBB, *this, LiveInSets)) {
LLVM_DEBUG(dbgs() << "Failed to split critical edge.\n");
continue;
}