Incremental progress towards a new implementation of StrongPHIElimination. Most

of the problems with my last attempt were in the updating of LiveIntervals
rather than the coalescing itself. Therefore, I decided to get that right first
by essentially reimplementing the existing PHIElimination using LiveIntervals.

It works correctly, with only a few tests failing (which may not be legitimate
failures) and no new verifier failures (at least as far as I can tell, I didn't
count the number per file).

llvm-svn: 122321
This commit is contained in:
Cameron Zwarich 2010-12-21 06:54:43 +00:00
parent 1a20c2aedd
commit 79ebc7186e
1 changed files with 186 additions and 3 deletions

View File

@ -11,11 +11,15 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "strongphielim"
#include "PHIEliminationUtils.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
namespace {
@ -28,6 +32,16 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage&) const;
bool runOnMachineFunction(MachineFunction&);
private:
void InsertCopiesForPHI(MachineInstr*, MachineBasicBlock*);
MachineRegisterInfo* MRI;
const TargetInstrInfo* TII;
LiveIntervals* LI;
typedef DenseSet<std::pair<MachineBasicBlock*, unsigned> > CopySet;
CopySet InsertedCopies;
};
} // namespace
@ -52,6 +66,175 @@ void StrongPHIElimination::getAnalysisUsage(AnalysisUsage& AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
}
bool StrongPHIElimination::runOnMachineFunction(MachineFunction& Fn) {
llvm_unreachable("Strong phi elimination is not implemented");
static MachineOperand* findLastUse(MachineBasicBlock* MBB, unsigned Reg) {
// FIXME: This only needs to check from the first terminator, as only the
// first terminator can use a virtual register.
for (MachineBasicBlock::reverse_iterator RI = MBB->rbegin(); ; ++RI) {
assert (RI != MBB->rend());
MachineInstr* MI = &*RI;
for (MachineInstr::mop_iterator OI = MI->operands_begin(),
OE = MI->operands_end(); OI != OE; ++OI) {
MachineOperand& MO = *OI;
if (MO.isReg() && MO.isUse() && MO.getReg() == Reg)
return &MO;
}
}
return NULL;
}
bool StrongPHIElimination::runOnMachineFunction(MachineFunction& MF) {
MRI = &MF.getRegInfo();
TII = MF.getTarget().getInstrInfo();
LI = &getAnalysis<LiveIntervals>();
// Insert copies for all PHI source and destination registers.
for (MachineFunction::iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
BBI != BBE && BBI->isPHI(); ++BBI) {
InsertCopiesForPHI(BBI, I);
}
}
// Adjust the live intervals of all PHI source registers to handle the case
// where the PHIs in successor blocks were the only later uses of the source
// register.
for (CopySet::iterator I = InsertedCopies.begin(), E = InsertedCopies.end();
I != E; ++I) {
MachineBasicBlock* MBB = I->first;
unsigned SrcReg = I->second;
LiveInterval& SrcLI = LI->getInterval(SrcReg);
bool isLiveOut = false;
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI) {
if (SrcLI.liveAt(LI->getMBBStartIdx(*SI))) {
isLiveOut = true;
break;
}
}
if (isLiveOut)
continue;
MachineOperand* LastUse = findLastUse(MBB, SrcReg);
assert(LastUse);
SrcLI.removeRange(LI->getInstructionIndex(LastUse->getParent()).getDefIndex(),
LI->getMBBEndIdx(MBB));
LastUse->setIsKill(true);
}
// Remove all PHI instructions from the function.
bool Changed = false;
for (MachineFunction::iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end();
while (BBI != BBE && BBI->isPHI()) {
MachineInstr* PHI = BBI;
++BBI;
LI->RemoveMachineInstrFromMaps(PHI);
PHI->eraseFromParent();
Changed = true;
}
}
LI->renumber();
MF.verify(this);
InsertedCopies.clear();
return Changed;
}
void StrongPHIElimination::InsertCopiesForPHI(MachineInstr* PHI,
MachineBasicBlock* MBB) {
assert(PHI->isPHI());
unsigned DestReg = PHI->getOperand(0).getReg();
const TargetRegisterClass* RC = MRI->getRegClass(DestReg);
unsigned CopyReg = MRI->createVirtualRegister(RC);
MachineInstr* CopyInstr = BuildMI(*MBB,
MBB->SkipPHIsAndLabels(MBB->begin()),
PHI->getDebugLoc(),
TII->get(TargetOpcode::COPY),
DestReg).addReg(CopyReg);
LI->InsertMachineInstrInMaps(CopyInstr);
CopyInstr->getOperand(1).setIsKill(true);
// Add the region from the beginning of MBB to the copy instruction to
// CopyReg's live interval, and give the VNInfo the phidef flag.
LiveInterval& CopyLI = LI->getOrCreateInterval(CopyReg);
SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB);
SlotIndex DestCopyIndex = LI->getInstructionIndex(CopyInstr);
VNInfo* CopyVNI = CopyLI.getNextValue(MBBStartIndex,
CopyInstr,
LI->getVNInfoAllocator());
CopyVNI->setIsPHIDef(true);
CopyLI.addRange(LiveRange(MBBStartIndex,
DestCopyIndex.getDefIndex(),
CopyVNI));
// Adjust DestReg's live interval to adjust for its new definition at
// CopyInstr.
LiveInterval& DestLI = LI->getOrCreateInterval(DestReg);
SlotIndex PHIIndex = LI->getInstructionIndex(PHI);
DestLI.removeRange(PHIIndex.getDefIndex(), DestCopyIndex.getDefIndex());
VNInfo* DestVNI = DestLI.getVNInfoAt(DestCopyIndex.getDefIndex());
assert(DestVNI);
DestVNI->def = DestCopyIndex.getDefIndex();
SmallPtrSet<MachineBasicBlock*, 8> MBBsInsertedInto;
for (unsigned i = 1; i < PHI->getNumOperands(); i += 2) {
MachineOperand& SrcMO = PHI->getOperand(i);
unsigned SrcReg = SrcMO.getReg();
unsigned SrcSubReg = SrcMO.getSubReg();
assert(TargetRegisterInfo::isVirtualRegister(SrcReg) &&
"Machine PHI Operands must all be virtual registers!");
// If source is defined by an implicit def, there is no need to insert a
// copy.
// FIXME: For some reason, if LiveIntervals is run prior to PHI elimination
// implcit defs have no defining instruction. Is this expected?
MachineInstr* DefMI = MRI->getVRegDef(SrcReg);
if (!DefMI)
continue;
MachineBasicBlock* PredBB = PHI->getOperand(i + 1).getMBB();
// A copy may have already been inserted in the predecessor in the case of a
// block with multiple incoming edges.
if (!MBBsInsertedInto.insert(PredBB))
continue;
MachineBasicBlock::iterator
CopyInsertPoint = findPHICopyInsertPoint(PredBB, MBB, SrcReg);
MachineInstr* CopyInstr = BuildMI(*PredBB,
CopyInsertPoint,
PHI->getDebugLoc(),
TII->get(TargetOpcode::COPY),
CopyReg).addReg(SrcReg, 0, SrcSubReg);
LI->InsertMachineInstrInMaps(CopyInstr);
// addLiveRangeToEndOfBlock() also adds the phikill flag to the VNInfo for
// the newly added range.
LI->addLiveRangeToEndOfBlock(CopyReg, CopyInstr);
InsertedCopies.insert(std::make_pair(PredBB, SrcReg));
// If SrcReg is not live beyond the PHI, trim its interval so that it is no
// longer live-in to MBB. Note that SrcReg may appear in other PHIs that are
// processed later, but this is still correct to do at this point because we
// never rely on LiveIntervals being correct while inserting copies.
// FIXME: Should this just count uses at PHIs like the normal PHIElimination
// pass does?
LiveInterval& SrcLI = LI->getInterval(SrcReg);
SlotIndex MBBStartIndex = LI->getMBBStartIdx(MBB);
SlotIndex PHIIndex = LI->getInstructionIndex(PHI);
SlotIndex NextInstrIndex = PHIIndex.getNextIndex();
if (SrcLI.liveAt(MBBStartIndex) && SrcLI.expiredAt(NextInstrIndex))
SrcLI.removeRange(MBBStartIndex, PHIIndex, true);
}
}