diff options
Diffstat (limited to 'lib/CodeGen/PHIElimination.cpp')
-rw-r--r-- | lib/CodeGen/PHIElimination.cpp | 81 |
1 files changed, 71 insertions, 10 deletions
diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp index f0057ce..1651719 100644 --- a/lib/CodeGen/PHIElimination.cpp +++ b/lib/CodeGen/PHIElimination.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include <algorithm> #include <map> using namespace llvm; @@ -52,22 +53,22 @@ void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } -bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) { - MRI = &Fn.getRegInfo(); +bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &MF) { + MRI = &MF.getRegInfo(); bool Changed = false; // Split critical edges to help the coalescer if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>()) - for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) - Changed |= SplitPHIEdges(Fn, *I, *LV); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= SplitPHIEdges(MF, *I, *LV); // Populate VRegPHIUseCount - analyzePHINodes(Fn); + analyzePHINodes(MF); // Eliminate PHI instructions by inserting copies into predecessor blocks. - for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) - Changed |= EliminatePHINodes(Fn, *I); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= EliminatePHINodes(MF, *I); // Remove dead IMPLICIT_DEF instructions. for (SmallPtrSet<MachineInstr*, 4>::iterator I = ImpDefs.begin(), @@ -81,11 +82,16 @@ bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) { // Clean up the lowered PHI instructions. for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end(); I != E; ++I) - Fn.DeleteMachineInstr(I->first); + MF.DeleteMachineInstr(I->first); LoweredPHIs.clear(); ImpDefs.clear(); VRegPHIUseCount.clear(); + + // Eliminate REG_SEQUENCE instructions. Their whole purpose was to preseve + // SSA form. + Changed |= EliminateRegSequences(MF); + return Changed; } @@ -364,8 +370,8 @@ void llvm::PHIElimination::LowerAtomicPHINode( /// used in a PHI node. We map that to the BB the vreg is coming from. This is /// used later to determine when the vreg is killed in the BB. /// -void llvm::PHIElimination::analyzePHINodes(const MachineFunction& Fn) { - for (MachineFunction::const_iterator I = Fn.begin(), E = Fn.end(); +void llvm::PHIElimination::analyzePHINodes(const MachineFunction& MF) { + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) for (MachineBasicBlock::const_iterator BBI = I->begin(), BBE = I->end(); BBI != BBE && BBI->isPHI(); ++BBI) @@ -443,3 +449,58 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, return NMBB; } + +static void UpdateRegSequenceSrcs(unsigned SrcReg, + unsigned DstReg, unsigned SrcIdx, + MachineRegisterInfo *MRI) { + for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(SrcReg), + UE = MRI->reg_end(); RI != UE; ) { + MachineOperand &MO = RI.getOperand(); + ++RI; + MO.setReg(DstReg); + MO.setSubReg(SrcIdx); + } +} + +/// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as second part +/// of de-ssa process. This replaces sources of REG_SEQUENCE as sub-register +/// references of the register defined by REG_SEQUENCE. e.g. +/// +/// %reg1029<def>, %reg1030<def> = VLD1q16 %reg1024<kill>, ... +/// %reg1031<def> = REG_SEQUENCE %reg1029<kill>, 5, %reg1030<kill>, 6 +/// => +/// %reg1031:5<def>, %reg1031:6<def> = VLD1q16 %reg1024<kill>, ... +bool PHIElimination::EliminateRegSequences(MachineFunction &MF) { + bool Changed = false; + + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + for (MachineBasicBlock::iterator BBI = I->begin(), BBE = I->end(); + BBI != BBE; ) { + MachineInstr &MI = *BBI; + ++BBI; + if (MI.getOpcode() != TargetOpcode::REG_SEQUENCE) + continue; + unsigned DstReg = MI.getOperand(0).getReg(); + if (MI.getOperand(0).getSubReg() || + TargetRegisterInfo::isPhysicalRegister(DstReg) || + !(MI.getNumOperands() & 1)) { + DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI); + llvm_unreachable(0); + } + for (unsigned i = 1, e = MI.getNumOperands(); i < e; i += 2) { + unsigned SrcReg = MI.getOperand(i).getReg(); + if (MI.getOperand(i).getSubReg() || + TargetRegisterInfo::isPhysicalRegister(SrcReg)) { + DEBUG(dbgs() << "Illegal REG_SEQUENCE instruction:" << MI); + llvm_unreachable(0); + } + unsigned SrcIdx = MI.getOperand(i+1).getImm(); + UpdateRegSequenceSrcs(SrcReg, DstReg, SrcIdx, MRI); + } + + MI.eraseFromParent(); + Changed = true; + } + + return Changed; +} |