From c4f3d51e12390f39f314451d868350e2a11a52b6 Mon Sep 17 00:00:00 2001 From: Cameron Zwarich Date: Tue, 22 Feb 2011 22:25:39 +0000 Subject: [PATCH] Make LoopDeletion work on loops with multiple edges, as long as the incoming values from all of the loop's exiting blocks are equal. Patch by Andrew Clinton. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126253 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopDeletion.cpp | 23 ++++++++++------ .../Transforms/LoopDeletion/multiple-exits.ll | 26 +++++++++++++++++++ 2 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 test/Transforms/LoopDeletion/multiple-exits.ll diff --git a/lib/Transforms/Scalar/LoopDeletion.cpp b/lib/Transforms/Scalar/LoopDeletion.cpp index 6d1d344a929..753a558cfe8 100644 --- a/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/lib/Transforms/Scalar/LoopDeletion.cpp @@ -78,7 +78,6 @@ bool LoopDeletion::IsLoopDead(Loop* L, SmallVector& exitingBlocks, SmallVector& exitBlocks, bool &Changed, BasicBlock *Preheader) { - BasicBlock* exitingBlock = exitingBlocks[0]; BasicBlock* exitBlock = exitBlocks[0]; // Make sure that all PHI entries coming from the loop are loop invariant. @@ -88,11 +87,21 @@ bool LoopDeletion::IsLoopDead(Loop* L, // of the loop. BasicBlock::iterator BI = exitBlock->begin(); while (PHINode* P = dyn_cast(BI)) { - Value* incoming = P->getIncomingValueForBlock(exitingBlock); + Value* incoming = P->getIncomingValueForBlock(exitingBlocks[0]); + + // Make sure all exiting blocks produce the same incoming value for the exit + // block. If there are different incoming values for different exiting + // blocks, then it is impossible to statically determine which value should + // be used. + for (unsigned i = 1; i < exitingBlocks.size(); ++i) { + if (incoming != P->getIncomingValueForBlock(exitingBlocks[i])) + return false; + } + if (Instruction* I = dyn_cast(incoming)) if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) return false; - + ++BI; } @@ -147,10 +156,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { if (exitBlocks.size() != 1) return false; - // Loops with multiple exits are too complicated to handle correctly. - if (exitingBlocks.size() != 1) - return false; - // Finally, we have to check that the loop really is dead. bool Changed = false; if (!IsLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader)) @@ -166,7 +171,6 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { // Now that we know the removal is safe, remove the loop by changing the // branch from the preheader to go to the single exit block. BasicBlock* exitBlock = exitBlocks[0]; - BasicBlock* exitingBlock = exitingBlocks[0]; // Because we're deleting a large chunk of code at once, the sequence in which // we remove things is very important to avoid invalidation issues. Don't @@ -183,9 +187,12 @@ bool LoopDeletion::runOnLoop(Loop* L, LPPassManager& LPM) { // Rewrite phis in the exit block to get their inputs from // the preheader instead of the exiting block. + BasicBlock* exitingBlock = exitingBlocks[0]; BasicBlock::iterator BI = exitBlock->begin(); while (PHINode* P = dyn_cast(BI)) { P->replaceUsesOfWith(exitingBlock, preheader); + for (unsigned i = 1; i < exitingBlocks.size(); ++i) + P->removeIncomingValue(exitingBlocks[i]); ++BI; } diff --git a/test/Transforms/LoopDeletion/multiple-exits.ll b/test/Transforms/LoopDeletion/multiple-exits.ll new file mode 100644 index 00000000000..6af413b49cd --- /dev/null +++ b/test/Transforms/LoopDeletion/multiple-exits.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -loop-deletion -S | FileCheck %s + +; Checks whether dead loops with multiple exits can be eliminated + +; CHECK: entry: +; CHECK-NEXT: br label %return + +; CHECK: return: +; CHECK-NEXT: ret void + +define void @foo(i64 %n, i64 %m) nounwind { +entry: + br label %bb + +bb: + %x.0 = phi i64 [ 0, %entry ], [ %t0, %bb2 ] + %t0 = add i64 %x.0, 1 + %t1 = icmp slt i64 %x.0, %n + br i1 %t1, label %bb2, label %return +bb2: + %t2 = icmp slt i64 %x.0, %m + br i1 %t1, label %bb, label %return + +return: + ret void +}