Fix liveness calculation when splitting critical edges during PHI elimination.

- Edges are split before any phis are eliminated, so the code is SSA.

- Create a proper IR BasicBlock for the split edges.

- LiveVariables::addNewBlock now has same syntax as
  MachineDominatorTree::addNewBlock. Algorithm calculates predecessor live-out
  set rather than successor live-in set.

This feature still causes some miscompilations.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86867 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2009-11-11 19:31:31 +00:00
parent eba4ed9cbb
commit 3e20475fee
4 changed files with 83 additions and 55 deletions

View File

@ -267,9 +267,11 @@ public:
void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, void HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB,
MachineInstr *MI); MachineInstr *MI);
/// addNewBlock - Add a new basic block A as an empty predecessor of B. All /// addNewBlock - Add a new basic block BB as an empty succcessor to
/// variables that are live into B will be marked as passing live through A. /// DomBB. All variables that are live out of DomBB will be marked as passing
void addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B); /// live through BB. This method assumes that the machine code is still in SSA
/// form.
void addNewBlock(MachineBasicBlock *BB, MachineBasicBlock *DomBB);
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -650,34 +650,35 @@ void LiveVariables::analyzePHINodes(const MachineFunction& Fn) {
.push_back(BBI->getOperand(i).getReg()); .push_back(BBI->getOperand(i).getReg());
} }
void LiveVariables::addNewBlock(MachineBasicBlock *A, MachineBasicBlock *B) { /// addNewBlock - Add a new basic block BB as an empty succcessor to DomBB. All
unsigned NumA = A->getNumber(); /// variables that are live out of DomBB will be marked as passing live through
unsigned NumB = B->getNumber(); /// BB.
void LiveVariables::addNewBlock(MachineBasicBlock *BB,
MachineBasicBlock *DomBB) {
const unsigned NumNew = BB->getNumber();
const unsigned NumDom = DomBB->getNumber();
// Update info for all live variables // Update info for all live variables
for (unsigned i = 0, e = VirtRegInfo.size(); i != e; ++i) { for (unsigned Reg = TargetRegisterInfo::FirstVirtualRegister,
VarInfo &VI = VirtRegInfo[i]; E = MRI->getLastVirtReg()+1; Reg != E; ++Reg) {
VarInfo &VI = getVarInfo(Reg);
// Anything live through B is also live through A. // Anything live through DomBB is also live through BB.
if (VI.AliveBlocks.test(NumB)) { if (VI.AliveBlocks.test(NumDom)) {
VI.AliveBlocks.set(NumA); VI.AliveBlocks.set(NumNew);
continue; continue;
} }
// If we're not killed in B, we are not live in // Variables not defined in DomBB cannot be live out.
if (!VI.findKill(B)) const MachineInstr *Def = MRI->getVRegDef(Reg);
if (!Def || Def->getParent() != DomBB)
continue; continue;
unsigned Reg = i+TargetRegisterInfo::FirstVirtualRegister; // Killed by DomBB?
if (VI.findKill(DomBB))
continue;
// Find a def outside B // This register is defined in DomBB and live out
for (MachineRegisterInfo::def_iterator di = MRI->def_begin(Reg), VI.AliveBlocks.set(NumNew);
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;
}
}
} }
} }

View File

@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Function.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLExtras.h"
@ -65,10 +66,17 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
PHIDefs.clear(); PHIDefs.clear();
PHIKills.clear(); PHIKills.clear();
analyzePHINodes(Fn);
bool Changed = false; bool Changed = false;
// Split critical edges to help the coalescer
if (SplitEdges)
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
Changed |= SplitPHIEdges(Fn, *I);
// Populate VRegPHIUseCount
analyzePHINodes(Fn);
// Eliminate PHI instructions by inserting copies into predecessor blocks. // Eliminate PHI instructions by inserting copies into predecessor blocks.
for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
Changed |= EliminatePHINodes(Fn, *I); Changed |= EliminatePHINodes(Fn, *I);
@ -87,7 +95,6 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) {
return Changed; return Changed;
} }
/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in
/// predecessor basic blocks. /// predecessor basic blocks.
/// ///
@ -96,9 +103,6 @@ bool llvm::PHIElimination::EliminatePHINodes(MachineFunction &MF,
if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI) if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
return false; // Quick exit for basic blocks without PHIs. 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 // Get an iterator to the first instruction after the last PHI node (this may
// also be the end of the basic block). // also be the end of the basic block).
MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin()); MachineBasicBlock::iterator AfterPHIsIt = SkipPHIsAndLabels(MBB, MBB.begin());
@ -293,7 +297,7 @@ void llvm::PHIElimination::LowerAtomicPHINode(
// Okay, if we now know that the value is not live out of the block, we can // 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! // add a kill marker in this block saying that it kills the incoming value!
// When SplitEdges is enabled, the value is never live out. // When SplitEdges is enabled, the value is never live out.
if (!ValueIsUsed && (SplitEdges || !isLiveOut(SrcReg, opBlock, *LV))) { if (!ValueIsUsed && !isLiveOut(SrcReg, opBlock, *LV)) {
// In our final twist, we have to decide which instruction kills the // In our final twist, we have to decide which instruction kills the
// register. In most cases this is the copy, however, the first // register. In most cases this is the copy, however, the first
// terminator instruction at the end of the block may also use the value. // terminator instruction at the end of the block may also use the value.
@ -345,8 +349,10 @@ void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) {
BBI->getOperand(i).getReg())]; BBI->getOperand(i).getReg())];
} }
void llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF, bool llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF,
MachineBasicBlock &MBB) { MachineBasicBlock &MBB) {
if (MBB.empty() || MBB.front().getOpcode() != TargetInstrInfo::PHI)
return false; // Quick exit for basic blocks without PHIs.
LiveVariables &LV = getAnalysis<LiveVariables>(); LiveVariables &LV = getAnalysis<LiveVariables>();
for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end(); for (MachineBasicBlock::const_iterator BBI = MBB.begin(), BBE = MBB.end();
BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) { BBI != BBE && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) {
@ -354,29 +360,29 @@ void llvm::PHIElimination::SplitPHIEdges(MachineFunction &MF,
unsigned Reg = BBI->getOperand(i).getReg(); unsigned Reg = BBI->getOperand(i).getReg();
MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB();
// We break edges when registers are live out from the predecessor block // We break edges when registers are live out from the predecessor block
// (not considering PHI nodes). // (not considering PHI nodes). If the register is live in to this block
if (isLiveOut(Reg, *PreMBB, LV)) // anyway, we would gain nothing from splitting.
if (isLiveOut(Reg, *PreMBB, LV) && !isLiveIn(Reg, MBB, LV))
SplitCriticalEdge(PreMBB, &MBB); SplitCriticalEdge(PreMBB, &MBB);
} }
} }
return true;
} }
bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB,
LiveVariables &LV) { LiveVariables &LV) {
LiveVariables::VarInfo &InRegVI = LV.getVarInfo(Reg); LiveVariables::VarInfo &VI = LV.getVarInfo(Reg);
// Loop over all of the successors of the basic block, checking to see if // Loop over all of the successors of the basic block, checking to see if
// the value is either live in the block, or if it is killed in the block. // the value is either live in the block, or if it is killed in the block.
std::vector<MachineBasicBlock*> OpSuccBlocks; std::vector<MachineBasicBlock*> OpSuccBlocks;
// Otherwise, scan successors, including the BB the PHI node lives in.
for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(), for (MachineBasicBlock::const_succ_iterator SI = MBB.succ_begin(),
E = MBB.succ_end(); SI != E; ++SI) { E = MBB.succ_end(); SI != E; ++SI) {
MachineBasicBlock *SuccMBB = *SI; MachineBasicBlock *SuccMBB = *SI;
// Is it alive in this successor? // Is it alive in this successor?
unsigned SuccIdx = SuccMBB->getNumber(); unsigned SuccIdx = SuccMBB->getNumber();
if (InRegVI.AliveBlocks.test(SuccIdx)) if (VI.AliveBlocks.test(SuccIdx))
return true; return true;
OpSuccBlocks.push_back(SuccMBB); OpSuccBlocks.push_back(SuccMBB);
} }
@ -386,36 +392,56 @@ bool llvm::PHIElimination::isLiveOut(unsigned Reg, const MachineBasicBlock &MBB,
switch (OpSuccBlocks.size()) { switch (OpSuccBlocks.size()) {
case 1: { case 1: {
MachineBasicBlock *SuccMBB = OpSuccBlocks[0]; MachineBasicBlock *SuccMBB = OpSuccBlocks[0];
for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i)
if (InRegVI.Kills[i]->getParent() == SuccMBB) if (VI.Kills[i]->getParent() == SuccMBB)
return true; return true;
break; break;
} }
case 2: { case 2: {
MachineBasicBlock *SuccMBB1 = OpSuccBlocks[0], *SuccMBB2 = OpSuccBlocks[1]; MachineBasicBlock *SuccMBB1 = OpSuccBlocks[0], *SuccMBB2 = OpSuccBlocks[1];
for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i)
if (InRegVI.Kills[i]->getParent() == SuccMBB1 || if (VI.Kills[i]->getParent() == SuccMBB1 ||
InRegVI.Kills[i]->getParent() == SuccMBB2) VI.Kills[i]->getParent() == SuccMBB2)
return true; return true;
break; break;
} }
default: default:
std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end()); std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end());
for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) for (unsigned i = 0, e = VI.Kills.size(); i != e; ++i)
if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(), if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(),
InRegVI.Kills[i]->getParent())) VI.Kills[i]->getParent()))
return true; return true;
} }
return false; return false;
} }
bool llvm::PHIElimination::isLiveIn(unsigned Reg, const MachineBasicBlock &MBB,
LiveVariables &LV) {
LiveVariables::VarInfo &VI = LV.getVarInfo(Reg);
return VI.AliveBlocks.test(MBB.getNumber()) || VI.findKill(&MBB);
}
MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A,
MachineBasicBlock *B) { MachineBasicBlock *B) {
assert(A && B && "Missing MBB end point"); assert(A && B && "Missing MBB end point");
++NumSplits; ++NumSplits;
BasicBlock *ABB = const_cast<BasicBlock*>(A->getBasicBlock());
BasicBlock *BBB = const_cast<BasicBlock*>(B->getBasicBlock());
assert(ABB && BBB && "End points must have a basic block");
BasicBlock *BB = BasicBlock::Create(BBB->getContext(),
ABB->getName() + "." + BBB->getName() +
"_phi_edge");
Function *F = ABB->getParent();
F->getBasicBlockList().insert(F->end(), BB);
BranchInst::Create(BBB, BB);
// We could do more here to produce correct IR, compare
// llvm::SplitCriticalEdge
MachineFunction *MF = A->getParent(); MachineFunction *MF = A->getParent();
MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(B->getBasicBlock()); MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(BB);
MF->push_back(NMBB); MF->push_back(NMBB);
const unsigned NewNum = NMBB->getNumber(); const unsigned NewNum = NMBB->getNumber();
DEBUG(errs() << "PHIElimination splitting critical edge:" DEBUG(errs() << "PHIElimination splitting critical edge:"
@ -430,21 +456,14 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A,
SmallVector<MachineOperand, 4> Cond; SmallVector<MachineOperand, 4> Cond;
MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond); MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond);
LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>(); if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>())
if (LV) LV->addNewBlock(NMBB, A);
LV->addNewBlock(NMBB, B);
// Fix PHI nodes in B so they refer to NMBB instead of A // Fix PHI nodes in B so they refer to NMBB instead of A
for (MachineBasicBlock::iterator i = B->begin(), e = B->end(); for (MachineBasicBlock::iterator i = B->begin(), e = B->end();
i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i) i != e && i->getOpcode() == TargetInstrInfo::PHI; ++i)
for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2)
if (i->getOperand(ni+1).getMBB() == A) { if (i->getOperand(ni+1).getMBB() == A)
i->getOperand(ni+1).setMBB(NMBB); 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; return NMBB;
} }

View File

@ -90,7 +90,7 @@ namespace llvm {
void analyzePHINodes(const MachineFunction& Fn); void analyzePHINodes(const MachineFunction& Fn);
/// Split critical edges where necessary for good coalescer performance. /// Split critical edges where necessary for good coalescer performance.
void SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB); bool SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB);
/// isLiveOut - Determine if Reg is live out from MBB, when not /// isLiveOut - Determine if Reg is live out from MBB, when not
/// considering PHI nodes. This means that Reg is either killed by /// considering PHI nodes. This means that Reg is either killed by
@ -98,6 +98,12 @@ namespace llvm {
bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB, bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB,
LiveVariables &LV); LiveVariables &LV);
/// isLiveIn - Determine if Reg is live in to MBB, not considering PHI
/// source registers. This means that Reg is either killed by MBB or passes
/// through it.
bool isLiveIn(unsigned Reg, const MachineBasicBlock &MBB,
LiveVariables &LV);
/// SplitCriticalEdge - Split a critical edge from A to B by /// SplitCriticalEdge - Split a critical edge from A to B by
/// inserting a new MBB. Update branches in A and PHI instructions /// inserting a new MBB. Update branches in A and PHI instructions
/// in B. Return the new block. /// in B. Return the new block.