From f235f13931835b3335f3f2ff2d3060381b93626c Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 10 Nov 2009 22:01:05 +0000 Subject: [PATCH] Teach PHIElimination to split critical edges when -split-phi-edges is enabled. Critical edges leading to a PHI node are split when the PHI source variable is live out from the predecessor block. This help the coalescer eliminate more PHI joins. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86725 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LiveVariables.h | 9 +++- lib/CodeGen/LiveVariables.cpp | 40 ++++++++++++++ lib/CodeGen/PHIElimination.cpp | 80 ++++++++++++++++++++++++++-- lib/CodeGen/PHIElimination.h | 9 ++++ 4 files changed, 133 insertions(+), 5 deletions(-) diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 172fb750944..c9b92e9e7f6 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -103,7 +103,10 @@ public: Kills.erase(I); return true; } - + + /// findKill - Find a kill instruction in MBB. Return NULL if none is found. + MachineInstr *findKill(const MachineBasicBlock *MBB) const; + void dump() const; }; @@ -263,6 +266,10 @@ public: void HandleVirtRegDef(unsigned reg, MachineInstr *MI); void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, MachineInstr *MI); + + /// addNewBlock - Add a new basic block A as an empty predecessor of B. All + /// variables that are live into B will be marked as passing live through A. + void addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B); }; } // End llvm namespace diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index 96c655c1a9b..1580667222f 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -50,6 +50,14 @@ void LiveVariables::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } +MachineInstr * +LiveVariables::VarInfo::findKill(const MachineBasicBlock *MBB) const { + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + if (Kills[i]->getParent() == MBB) + return Kills[i]; + return NULL; +} + void LiveVariables::VarInfo::dump() const { errs() << " Alive in blocks: "; for (SparseBitVector<>::iterator I = AliveBlocks.begin(), @@ -641,3 +649,35 @@ void LiveVariables::analyzePHINodes(const MachineFunction& Fn) { PHIVarInfo[BBI->getOperand(i + 1).getMBB()->getNumber()] .push_back(BBI->getOperand(i).getReg()); } + +void LiveVariables::addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B) { + unsigned NumA = A->getNumber(); + unsigned NumB = B->getNumber(); + + // Update info for all live variables + for (unsigned i = 0, e = VirtRegInfo.size(); i != e; ++i) { + VarInfo &VI = VirtRegInfo[i]; + + // Anything live through B is also live through A. + if (VI.AliveBlocks.test(NumB)) { + VI.AliveBlocks.set(NumA); + continue; + } + + // If we're not killed in B, we are not live in + if (!VI.findKill(B)) + continue; + + unsigned Reg = i+TargetRegisterInfo::FirstVirtualRegister; + + // Find a def outside B + for (MachineRegisterInfo::def_iterator di = MRI->def_begin(Reg), + de=MRI->def_end(); di != de; ++di) { + if (di->getParent() != B) { + // Reg was defined outside B and killed in B - it must be live in. + VI.AliveBlocks.set(NumA); + break; + } + } + } +} diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp index bf15bac2896..7c9c18c1cb0 100644 --- a/lib/CodeGen/PHIElimination.cpp +++ b/lib/CodeGen/PHIElimination.cpp @@ -27,12 +27,20 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include #include using namespace llvm; STATISTIC(NumAtomic, "Number of atomic phis lowered"); +STATISTIC(NumSplits, "Number of critical edges split on demand"); + +static cl::opt +SplitEdges("split-phi-edges", + cl::desc("Split critical edges during phi elimination"), + cl::init(false), cl::Hidden); char PHIElimination::ID = 0; static RegisterPass @@ -41,10 +49,14 @@ X("phi-node-elimination", "Eliminate PHI nodes for register allocation"); const PassInfo *const llvm::PHIEliminationID = &X; void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); AU.addPreserved(); - AU.addPreservedID(MachineLoopInfoID); - AU.addPreservedID(MachineDominatorsID); + if (SplitEdges) { + AU.addRequired(); + } else { + AU.setPreservesCFG(); + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); + } MachineFunctionPass::getAnalysisUsage(AU); } @@ -84,6 +96,9 @@ bool llvm::PHIElimination::EliminatePHINodes(MachineFunction &MF, if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI) return false; // Quick exit for basic blocks without PHIs. + if (SplitEdges) + SplitPHIEdges(MF, MBB); + // Get an iterator to the first instruction after the last PHI node (this may // also be the end of the basic block). MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin()); @@ -277,7 +292,8 @@ void llvm::PHIElimination::LowerAtomicPHINode( // Okay, if we now know that the value is not live out of the block, we can // add a kill marker in this block saying that it kills the incoming value! - if (!ValueIsUsed && !isLiveOut(SrcReg, opBlock, *LV)) { + // When SplitEdges is enabled, the value is never live out. + if (!ValueIsUsed && (SplitEdges || !isLiveOut(SrcReg, opBlock, *LV))) { // In our final twist, we have to decide which instruction kills the // register. In most cases this is the copy, however, the first // terminator instruction at the end of the block may also use the value. @@ -329,6 +345,22 @@ void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) { BBI->getOperand(i).getReg())]; } +void llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF, + MachineBasicBlock &MBB) { + LiveVariables &LV = getAnalysis(); + for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end(); + BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + unsigned Reg = BBI->getOperand(i).getReg(); + MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); + // We break edges when registers are live out from the predecessor block + // (not considering PHI nodes). + if (isLiveOut(Reg, *PreMBB, LV)) + SplitCriticalEdge(PreMBB, &MBB); + } + } +} + bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, LiveVariables &LV) { LiveVariables::VarInfo &InRegVI = LV.getVarInfo(Reg); @@ -376,3 +408,43 @@ bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, } return false; } + +MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, + MachineBasicBlock *B) { + assert(A && B && "Missing MBB end point"); + ++NumSplits; + + MachineFunction *MF = A->getParent(); + MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(B->getBasicBlock()); + MF->push_back(NMBB); + const unsigned NewNum = NMBB->getNumber(); + DEBUG(errs() << "PHIElimination splitting critical edge:" + " BB#" << A->getNumber() + << " -- BB#" << NewNum + << " -- BB#" << B->getNumber() << '\n'); + + A->ReplaceUsesOfBlockWith(B, NMBB); + NMBB->addSuccessor(B); + + // Insert unconditional "jump B" instruction in NMBB. + SmallVector Cond; + MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond); + + LiveVariables *LV = getAnalysisIfAvailable(); + if (LV) + LV->addNewBlock(NMBB, B); + + // Fix PHI nodes in B so they refer to NMBB instead of A + for (MachineBasicBlock::iterator i = B->begin(), e = B->end(); + i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i) + for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) + if (i->getOperand(ni+1).getMBB() == A) { + i->getOperand(ni+1).setMBB(NMBB); + // Mark PHI sources as passing live through NMBB + if (LV) + LV->getVarInfo(i->getOperand(ni).getReg()).AliveBlocks.set(NewNum); + } + return NMBB; +} + + diff --git a/lib/CodeGen/PHIElimination.h b/lib/CodeGen/PHIElimination.h index 8a04f9d6acf..8188440c899 100644 --- a/lib/CodeGen/PHIElimination.h +++ b/lib/CodeGen/PHIElimination.h @@ -89,12 +89,21 @@ namespace llvm { /// void analyzePHINodes(const MachineFunction& Fn); + /// Split critical edges where necessary for good coalescer performance. + void SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB); + /// isLiveOut - Determine if Reg is live out from MBB, when not /// considering PHI nodes. This means that Reg is either killed by /// a successor block or passed through one. bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, LiveVariables &LV); + /// SplitCriticalEdge - Split a critical edge from A to B by + /// inserting a new MBB. Update branches in A and PHI instructions + /// in B. Return the new block. + MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *A, + MachineBasicBlock *B); + // FindCopyInsertPoint - Find a safe place in MBB to insert a copy from // SrcReg. This needs to be after any def or uses of SrcReg, but before // any subsequent point where control flow might jump out of the basic