From ccd9bcca14e7046b7078cdf472a9185b86cdf07d Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Sat, 26 Jun 2010 04:27:33 +0000 Subject: Clean up some problems with extra CFG edges being introduced during if-conversion. The RemoveExtraEdges function doesn't work for blocks that end with unanalyzable branches, so in those cases, the "extra" edges must be explicitly removed. The CopyAndPredicateBlock and MergeBlocks methods can also avoid copying successor edges due to branches that have already been removed. The latter case is especially helpful when MergeBlocks is called for handling "diamond" if-conversions, where otherwise you can end up with some weird intermediate states in the CFG. Unfortunately I've been unable to find cases where this cleanup actually makes a significant difference in the code. There is one test where we manage to remove an empty block at the end of a function. Radar 6911268. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106939 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/IfConversion.cpp | 70 +++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 33 deletions(-) (limited to 'lib/CodeGen/IfConversion.cpp') diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp index 51fea7f..7237c04 100644 --- a/lib/CodeGen/IfConversion.cpp +++ b/lib/CodeGen/IfConversion.cpp @@ -186,7 +186,7 @@ namespace { SmallVectorImpl &Cond, SmallSet &Redefs, bool IgnoreBr = false); - void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI); + void MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges = true); bool MeetIfcvtSizeLimit(MachineBasicBlock &BB, unsigned Size) const { return Size > 0 && TII->isProfitableToIfCvt(BB, Size); @@ -1036,6 +1036,10 @@ bool IfConverter::IfConvertSimple(BBInfo &BBI, IfcvtKind Kind) { IterIfcvt = false; } + // RemoveExtraEdges won't work if the block has an unanalyzable branch, + // which is typically the case for IfConvertSimple, so explicitly remove + // CvtBBI as a successor. + BBI.BB->removeSuccessor(CvtBBI->BB); RemoveExtraEdges(BBI); // Update block info. BB can be iteratively if-converted. @@ -1098,8 +1102,7 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) { InitPredRedefs(NextBBI->BB, Redefs, TRI); bool HasEarlyExit = CvtBBI->FalseBB != NULL; - bool DupBB = CvtBBI->BB->pred_size() > 1; - if (DupBB) { + if (CvtBBI->BB->pred_size() > 1) { BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); // Copy instructions in the true block, predicate them, and add them to // the entry block. @@ -1111,7 +1114,7 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) { // Now merge the entry of the triangle with the true block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); - MergeBlocks(BBI, *CvtBBI); + MergeBlocks(BBI, *CvtBBI, false); } // If 'true' block has a 'false' successor, add an exit branch to it. @@ -1184,9 +1187,9 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, return false; } - // Merge the 'true' and 'false' blocks by copying the instructions - // from the 'false' block to the 'true' block. That is, unless the true - // block would clobber the predicate, in that case, do the opposite. + // Put the predicated instructions from the 'true' block before the + // instructions from the 'false' block, unless the true block would clobber + // the predicate, in which case, do the opposite. BBInfo *BBI1 = &TrueBBI; BBInfo *BBI2 = &FalseBBI; SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); @@ -1276,8 +1279,8 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, PredicateBlock(*BBI2, DI2, *Cond2, Redefs); // Merge the true block into the entry of the diamond. - MergeBlocks(BBI, *BBI1); - MergeBlocks(BBI, *BBI2); + MergeBlocks(BBI, *BBI1, TailBB == 0); + MergeBlocks(BBI, *BBI2, TailBB == 0); // If the if-converted block falls through or unconditionally branches into // the tail block, and the tail block does not have other predecessors, then @@ -1286,15 +1289,20 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind, if (TailBB) { BBInfo TailBBI = BBAnalysis[TailBB->getNumber()]; if (TailBB->pred_size() == 1 && !TailBBI.HasFallThrough) { - BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, TailBBI); TailBBI.IsDone = true; } else { + BBI.BB->addSuccessor(TailBB); InsertUncondBranch(BBI.BB, TailBB, TII); BBI.HasFallThrough = false; } } + // RemoveExtraEdges won't work if the block has an unanalyzable branch, + // which can happen here if TailBB is unanalyzable and is merged, so + // explicitly remove BBI1 and BBI2 as successors. + BBI.BB->removeSuccessor(BBI1->BB); + BBI.BB->removeSuccessor(BBI2->BB); RemoveExtraEdges(BBI); // Update block info. @@ -1367,17 +1375,19 @@ void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, UpdatePredRedefs(MI, Redefs, TRI, true); } - std::vector Succs(FromBBI.BB->succ_begin(), - FromBBI.BB->succ_end()); - MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); - MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; + if (!IgnoreBr) { + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; - for (unsigned i = 0, e = Succs.size(); i != e; ++i) { - MachineBasicBlock *Succ = Succs[i]; - // Fallthrough edge can't be transferred. - if (Succ == FallThrough) - continue; - ToBBI.BB->addSuccessor(Succ); + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. + if (Succ == FallThrough) + continue; + ToBBI.BB->addSuccessor(Succ); + } } std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), @@ -1391,21 +1401,14 @@ void IfConverter::CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI, } /// MergeBlocks - Move all instructions from FromBB to the end of ToBB. -/// -void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI) { +/// This will leave FromBB as an empty block, so remove all of its +/// successor edges except for the fall-through edge. If AddEdges is true, +/// i.e., when FromBBI's branch is being moved, add those successor edges to +/// ToBBI. +void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI, bool AddEdges) { ToBBI.BB->splice(ToBBI.BB->end(), FromBBI.BB, FromBBI.BB->begin(), FromBBI.BB->end()); - // Redirect all branches to FromBB to ToBB. - std::vector Preds(FromBBI.BB->pred_begin(), - FromBBI.BB->pred_end()); - for (unsigned i = 0, e = Preds.size(); i != e; ++i) { - MachineBasicBlock *Pred = Preds[i]; - if (Pred == ToBBI.BB) - continue; - Pred->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); - } - std::vector Succs(FromBBI.BB->succ_begin(), FromBBI.BB->succ_end()); MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); @@ -1417,7 +1420,8 @@ void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI) { if (Succ == FallThrough) continue; FromBBI.BB->removeSuccessor(Succ); - ToBBI.BB->addSuccessor(Succ); + if (AddEdges) + ToBBI.BB->addSuccessor(Succ); } // Now FromBBI always falls through to the next block! -- cgit v1.1