| //===--------- 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/AssumptionCache.h" | |
| #include "llvm/Analysis/BasicAliasAnalysis.h" | |
| #include "llvm/Analysis/DependenceAnalysis.h" | |
| #include "llvm/Analysis/GlobalsModRef.h" | |
| #include "llvm/Analysis/LoopInfo.h" | |
| #include "llvm/Analysis/LoopPass.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/Scalar/LoopPassManager.h" | |
| #include "llvm/Transforms/Utils.h" | |
| #include "llvm/Transforms/Utils/BasicBlockUtils.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, | |
| ScalarEvolution &SE) { | |
| bool Changed = false; | |
| // Copy blocks into a temporary array to avoid iterator invalidation issues | |
| // as we remove them. | |
| SmallVector<WeakTrackingVH, 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; | |
| // Merge Succ into Pred and delete it. | |
| MergeBlockIntoPredecessor(Succ, &DT, &LI); | |
| SE.forgetLoop(&L); | |
| Changed = true; | |
| } | |
| return Changed; | |
| } | |
| PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, LoopAnalysisManager &AM, | |
| LoopStandardAnalysisResults &AR, | |
| LPMUpdater &) { | |
| if (!simplifyLoopCFG(L, AR.DT, AR.LI, AR.SE)) | |
| 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(); | |
| ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); | |
| return simplifyLoopCFG(*L, DT, LI, SE); | |
| } | |
| 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(); | |
| } |