diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index c27e0d4ed6b..1ac552ed525 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -96,6 +96,12 @@ namespace { bool TailDuplicateBlocks(MachineFunction &MF); bool shouldTailDuplicate(const MachineFunction &MF, MachineBasicBlock &TailBB); + bool isSimpleBB(MachineBasicBlock *TailBB); + bool canCompletelyDuplicateSimpleBB(MachineBasicBlock &BB); + bool duplicateSimpleBB(MachineBasicBlock *TailBB, + SmallVector &TDBBs, + const DenseSet &RegsUsedByPhi, + SmallVector &Copies); bool TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, SmallVector &TDBBs, SmallVector &Copies); @@ -557,6 +563,136 @@ TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF, return true; } +/// isSimpleBB - True if this BB has only one unconditional jump. +bool +TailDuplicatePass::isSimpleBB(MachineBasicBlock *TailBB) { + if (TailBB->succ_size() != 1) + return false; + MachineBasicBlock::iterator I = TailBB->getFirstNonPHI(); + MachineBasicBlock::iterator E = TailBB->end(); + while (I->isDebugValue() && I != E) + ++I; + if (I == E) + return true; + return I->getDesc().isUnconditionalBranch(); +} + +static bool +bothUsedInPHI(const MachineBasicBlock &A, + SmallPtrSet SuccsB) { + for (MachineBasicBlock::const_succ_iterator SI = A.succ_begin(), + SE = A.succ_end(); SI != SE; ++SI) { + MachineBasicBlock *BB = *SI; + if (SuccsB.count(BB) && !BB->empty() && BB->begin()->isPHI()) + return true; + } + + return false; +} + +bool +TailDuplicatePass::canCompletelyDuplicateSimpleBB(MachineBasicBlock &BB) { + SmallPtrSet Succs(BB.succ_begin(), BB.succ_end()); + + for (MachineBasicBlock::pred_iterator PI = BB.pred_begin(), + PE = BB.pred_end(); PI != PE; ++PI) { + MachineBasicBlock *PredBB = *PI; + if (PredBB->getLandingPadSuccessor()) + return false; + if (bothUsedInPHI(*PredBB, Succs)) + return false; + MachineBasicBlock *PredTBB = NULL, *PredFBB = NULL; + SmallVector PredCond; + if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) + return false; + } + return true; +} + +bool +TailDuplicatePass::duplicateSimpleBB(MachineBasicBlock *TailBB, + SmallVector &TDBBs, + const DenseSet &UsedByPhi, + SmallVector &Copies) { + if (!canCompletelyDuplicateSimpleBB(*TailBB)) + return false; + + bool Changed = false; + SmallVector Preds(TailBB->pred_begin(), + TailBB->pred_end()); + for (SmallSetVector::iterator PI = Preds.begin(), + PE = Preds.end(); PI != PE; ++PI) { + MachineBasicBlock *PredBB = *PI; + + MachineBasicBlock *PredTBB = NULL, *PredFBB = NULL; + SmallVector PredCond; + bool NotAnalyzable = + TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true); + (void)NotAnalyzable; + assert(!NotAnalyzable && "Cannot duplicate this!"); + + DEBUG(dbgs() << "\nTail-duplicating into PredBB: " << *PredBB + << "From simple Succ: " << *TailBB); + + MachineBasicBlock *NewTarget = *TailBB->succ_begin(); + MachineBasicBlock *NextBB = next(MachineFunction::iterator(PredBB)); + + DenseMap LocalVRMap; + SmallVector, 4> CopyInfos; + for (MachineBasicBlock::iterator I = TailBB->begin(); + I != TailBB->end() && I->isPHI();) { + MachineInstr *MI = &*I; + ++I; + ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos, UsedByPhi, true); + } + MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); + for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { + Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(), + TII->get(TargetOpcode::COPY), + CopyInfos[i].first).addReg(CopyInfos[i].second)); + } + + // Make PredFBB explicit. + if (PredCond.empty()) + PredFBB = PredTBB; + + // Make fall through explicit. + if (!PredTBB) + PredTBB = NextBB; + if (!PredFBB) + PredFBB = NextBB; + + // Redirect + if (PredFBB == TailBB) + PredFBB = NewTarget; + if (PredTBB == TailBB) + PredTBB = NewTarget; + + // Make the branch unconditional if possible + if (PredTBB == PredFBB) + PredFBB = NULL; + + // Avoid adding fall through branches. + if (PredFBB == NextBB) + PredFBB = NULL; + if (PredTBB == NextBB && PredFBB == NULL) + PredTBB = NULL; + + TII->RemoveBranch(*PredBB); + + if (PredTBB) + TII->InsertBranch(*PredBB, PredTBB, PredFBB, PredCond, DebugLoc()); + + PredBB->removeSuccessor(TailBB); + PredBB->addSuccessor(NewTarget); + + TDBBs.push_back(PredBB); + + Changed = true; + } + return Changed; +} + /// TailDuplicate - If it is profitable, duplicate TailBB's contents in each /// of its predecessors. bool @@ -568,14 +704,18 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, DEBUG(dbgs() << "\n*** Tail-duplicating BB#" << TailBB->getNumber() << '\n'); + DenseSet UsedByPhi; + getRegsUsedByPHIs(*TailBB, &UsedByPhi); + + if (isSimpleBB(TailBB)) + return duplicateSimpleBB(TailBB, TDBBs, UsedByPhi, Copies); + // Iterate through all the unique predecessors and tail-duplicate this // block into them, if possible. Copying the list ahead of time also // avoids trouble with the predecessor list reallocating. bool Changed = false; SmallSetVector Preds(TailBB->pred_begin(), TailBB->pred_end()); - DenseSet UsedByPhi; - getRegsUsedByPHIs(*TailBB, &UsedByPhi); for (SmallSetVector::iterator PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { MachineBasicBlock *PredBB = *PI;