summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorAnna Thomas <anna@azul.com>2017-05-03 11:47:11 +0000
committerAnna Thomas <anna@azul.com>2017-05-03 11:47:11 +0000
commit53c8d95c850eb2a97962882c9c0effe98a917f41 (patch)
treee81a826c09892c3a3413f925cbdb998e802ba3ff /llvm/lib/Transforms
parentc30d85bd8aad17f1235904a00b27181a7e29a952 (diff)
downloadbcm5719-llvm-53c8d95c850eb2a97962882c9c0effe98a917f41.tar.gz
bcm5719-llvm-53c8d95c850eb2a97962882c9c0effe98a917f41.zip
[Loop Deletion] Delete loops that are never executed
Summary: Currently, loop deletion deletes loop where the only values that are used outside the loop are loop-invariant. This patch adds logic to delete loops where the loop is proven to be never executed (i.e. the only predecessor of the loop preheader has a constant conditional branch as terminator, and the preheader is not the taken target). This will remove loops that become dead after loop-unswitching generates constant conditional branches. The next steps are: 1. moving the loop deletion implementation to LoopUtils. 2. Add logic in loop-simplifyCFG which will support changing conditional constant branches to unconditional branches. If loops become unreachable in this process, they can be removed using `deleteDeadLoop` function. Reviewers: chandlerc, efriedma, sanjoy, reames Reviewed by: sanjoy Subscribers: mzolotukhin, llvm-commits Differential Revision: https://reviews.llvm.org/D32494 llvm-svn: 302015
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/LoopDeletion.cpp104
1 files changed, 90 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 73e8ce0e1d9..3151ccd279c 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -20,6 +20,7 @@
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
@@ -29,6 +30,21 @@ using namespace llvm;
STATISTIC(NumDeleted, "Number of loops deleted");
+/// This function deletes dead loops. The caller of this function needs to
+/// guarantee that the loop is infact dead. Here we handle two kinds of dead
+/// loop. The first kind (\p isLoopDead) is where only invariant values from
+/// within the loop are used outside of it. The second kind (\p
+/// isLoopNeverExecuted) is where the loop is provably never executed. We can
+/// always remove never executed loops since they will not cause any
+/// difference to program behaviour.
+///
+/// This also updates the relevant analysis information in \p DT, \p SE, and \p
+/// LI. It also updates the loop PM if an updater struct is provided.
+// TODO: This function will be used by loop-simplifyCFG as well. So, move this
+// to LoopUtils.cpp
+static void deleteDeadLoop(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
+ LoopInfo &LI, bool LoopIsNeverExecuted,
+ LPMUpdater *Updater = nullptr);
/// Determines if a loop is dead.
///
/// This assumes that we've already checked for unique exit and exiting blocks,
@@ -84,12 +100,44 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE,
return true;
}
+/// This function returns true if there is no viable path from the
+/// entry block to the header of \p L. Right now, it only does
+/// a local search to save compile time.
+static bool isLoopNeverExecuted(Loop *L) {
+ using namespace PatternMatch;
+
+ auto *Preheader = L->getLoopPreheader();
+ // TODO: We can relax this constraint, since we just need a loop
+ // predecessor.
+ assert(Preheader && "Needs preheader!");
+
+ if (Preheader == &Preheader->getParent()->getEntryBlock())
+ return false;
+ // All predecessors of the preheader should have a constant conditional
+ // branch, with the loop's preheader as not-taken.
+ for (auto *Pred: predecessors(Preheader)) {
+ BasicBlock *Taken, *NotTaken;
+ ConstantInt *Cond;
+ if (!match(Pred->getTerminator(),
+ m_Br(m_ConstantInt(Cond), Taken, NotTaken)))
+ return false;
+ if (!Cond->getZExtValue())
+ std::swap(Taken, NotTaken);
+ if (Taken == Preheader)
+ return false;
+ }
+ assert(!pred_empty(Preheader) &&
+ "Preheader should have predecessors at this point!");
+ // All the predecessors have the loop preheader as not-taken target.
+ return true;
+}
+
/// Remove a loop if it is dead.
///
/// A loop is considered dead if it does not impact the observable behavior of
/// the program other than finite running time. This never removes a loop that
-/// might be infinite, as doing so could change the halting/non-halting nature
-/// of a program.
+/// might be infinite (unless it is never executed), as doing so could change
+/// the halting/non-halting nature of a program.
///
/// This entire process relies pretty heavily on LoopSimplify form and LCSSA in
/// order to make various safety checks work.
@@ -97,9 +145,6 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE,
/// \returns true if any changes were made. This may mutate the loop even if it
/// is unable to delete it due to hoisting trivially loop invariant
/// instructions out of the loop.
-///
-/// This also updates the relevant analysis information in \p DT, \p SE, and \p
-/// LI. It also updates the loop PM if an updater struct is provided.
static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
LoopInfo &LI, LPMUpdater *Updater = nullptr) {
assert(L->isLCSSAForm(DT) && "Expected LCSSA!");
@@ -119,6 +164,17 @@ static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
if (L->begin() != L->end())
return false;
+
+ BasicBlock *ExitBlock = L->getUniqueExitBlock();
+
+ if (ExitBlock && isLoopNeverExecuted(L)) {
+ deleteDeadLoop(L, DT, SE, LI, true /* LoopIsNeverExecuted */, Updater);
+ ++NumDeleted;
+ return true;
+ }
+
+ // The remaining checks below are for a loop being dead because all statements
+ // in the loop are invariant.
SmallVector<BasicBlock *, 4> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
@@ -126,7 +182,6 @@ static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
// be in the situation of needing to be able to solve statically which exit
// block will be branched to, or trying to preserve the branching logic in
// a loop invariant manner.
- BasicBlock *ExitBlock = L->getUniqueExitBlock();
if (!ExitBlock)
return false;
@@ -141,6 +196,19 @@ static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
if (isa<SCEVCouldNotCompute>(S))
return Changed;
+ deleteDeadLoop(L, DT, SE, LI, false /* LoopIsNeverExecuted */, Updater);
+ ++NumDeleted;
+
+ return true;
+}
+
+static void deleteDeadLoop(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
+ LoopInfo &LI, bool LoopIsNeverExecuted,
+ LPMUpdater *Updater) {
+ assert(L->isLCSSAForm(DT) && "Expected LCSSA!");
+ auto *Preheader = L->getLoopPreheader();
+ assert(Preheader && "Preheader should exist!");
+
// 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.
//
@@ -156,17 +224,29 @@ static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
// to determine what it needs to clean up.
SE.forgetLoop(L);
+ auto *ExitBlock = L->getUniqueExitBlock();
+ assert(ExitBlock && "Should have a unique exit block!");
+
// Connect the preheader directly to the exit block.
- TerminatorInst *TI = Preheader->getTerminator();
- TI->replaceUsesOfWith(L->getHeader(), ExitBlock);
+ // Even when the loop is never executed, we cannot remove the edge from the
+ // source block to the exit block. Consider the case where the unexecuted loop
+ // branches back to an outer loop. If we deleted the loop and removed the edge
+ // coming to this inner loop, this will break the outer loop structure (by
+ // deleting the backedge of the outer loop). If the outer loop is indeed a
+ // non-loop, it will be deleted in a future iteration of loop deletion pass.
+ Preheader->getTerminator()->replaceUsesOfWith(L->getHeader(), ExitBlock);
- // Rewrite phis in the exit block to get their inputs from
- // the preheader instead of the exiting block.
+ SmallVector<BasicBlock *, 4> ExitingBlocks;
+ L->getExitingBlocks(ExitingBlocks);
+ // 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<PHINode>(BI)) {
int j = P->getBasicBlockIndex(ExitingBlock);
assert(j >= 0 && "Can't find exiting block in exit block's phi node!");
+ if (LoopIsNeverExecuted)
+ P->setIncomingValue(j, UndefValue::get(P->getType()));
P->setIncomingBlock(j, Preheader);
for (unsigned i = 1; i < ExitingBlocks.size(); ++i)
P->removeIncomingValue(ExitingBlocks[i]);
@@ -211,9 +291,6 @@ static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
// The last step is to update LoopInfo now that we've eliminated this loop.
LI.markAsRemoved(L);
- ++NumDeleted;
-
- return true;
}
PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM,
@@ -254,7 +331,6 @@ Pass *llvm::createLoopDeletionPass() { return new LoopDeletionLegacyPass(); }
bool LoopDeletionLegacyPass::runOnLoop(Loop *L, LPPassManager &) {
if (skipLoop(L))
return false;
-
DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
OpenPOWER on IntegriCloud