diff options
Diffstat (limited to 'lib/Transforms/Scalar/LoopSimplifyCFG.cpp')
-rw-r--r-- | lib/Transforms/Scalar/LoopSimplifyCFG.cpp | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp new file mode 100644 index 000000000000..ec227932c09e --- /dev/null +++ b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -0,0 +1,114 @@ +//===--------- LoopSimplifyCFG.cpp - Loop CFG Simplification Pass ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Loop SimplifyCFG Pass. This pass is responsible for +// basic loop CFG cleanup, primarily to assist other loop passes. If you +// encounter a noncanonical CFG construct that causes another loop pass to +// perform suboptimally, this is the place to fix it up. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/DependenceAnalysis.h" +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/LoopPass.h" +#include "llvm/Analysis/LoopPassManager.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/Local.h" +#include "llvm/Transforms/Utils/LoopUtils.h" +using namespace llvm; + +#define DEBUG_TYPE "loop-simplifycfg" + +static bool simplifyLoopCFG(Loop &L, DominatorTree &DT, LoopInfo &LI) { + bool Changed = false; + // Copy blocks into a temporary array to avoid iterator invalidation issues + // as we remove them. + SmallVector<WeakVH, 16> Blocks(L.blocks()); + + for (auto &Block : Blocks) { + // Attempt to merge blocks in the trivial case. Don't modify blocks which + // belong to other loops. + BasicBlock *Succ = cast_or_null<BasicBlock>(Block); + if (!Succ) + continue; + + BasicBlock *Pred = Succ->getSinglePredecessor(); + if (!Pred || !Pred->getSingleSuccessor() || LI.getLoopFor(Pred) != &L) + continue; + + // Pred is going to disappear, so we need to update the loop info. + if (L.getHeader() == Pred) + L.moveToHeader(Succ); + LI.removeBlock(Pred); + MergeBasicBlockIntoOnlyPred(Succ, &DT); + Changed = true; + } + + return Changed; +} + +PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, AnalysisManager<Loop> &AM) { + const auto &FAM = + AM.getResult<FunctionAnalysisManagerLoopProxy>(L).getManager(); + Function *F = L.getHeader()->getParent(); + + auto *LI = FAM.getCachedResult<LoopAnalysis>(*F); + auto *DT = FAM.getCachedResult<DominatorTreeAnalysis>(*F); + assert((LI && DT) && "Analyses for LoopSimplifyCFG not available"); + + if (!simplifyLoopCFG(L, *DT, *LI)) + return PreservedAnalyses::all(); + return getLoopPassPreservedAnalyses(); +} + +namespace { +class LoopSimplifyCFGLegacyPass : public LoopPass { +public: + static char ID; // Pass ID, replacement for typeid + LoopSimplifyCFGLegacyPass() : LoopPass(ID) { + initializeLoopSimplifyCFGLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnLoop(Loop *L, LPPassManager &) override { + if (skipLoop(L)) + return false; + + DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); + return simplifyLoopCFG(*L, DT, LI); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addPreserved<DependenceAnalysisWrapperPass>(); + getLoopAnalysisUsage(AU); + } +}; +} + +char LoopSimplifyCFGLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(LoopSimplifyCFGLegacyPass, "loop-simplifycfg", + "Simplify loop CFG", false, false) +INITIALIZE_PASS_DEPENDENCY(LoopPass) +INITIALIZE_PASS_END(LoopSimplifyCFGLegacyPass, "loop-simplifycfg", + "Simplify loop CFG", false, false) + +Pass *llvm::createLoopSimplifyCFGPass() { + return new LoopSimplifyCFGLegacyPass(); +} |