diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index d3047da7c56..df85092f97f 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -180,7 +180,7 @@ void initializeLoopInterchangePass(PassRegistry &); void initializeLoopInstSimplifyPass(PassRegistry&); void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); -void initializeLoopSimplifyCFGPass(PassRegistry&); +void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); void initializeGlobalMergePass(PassRegistry&); void initializeLoopRerollPass(PassRegistry&); diff --git a/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h new file mode 100644 index 00000000000..7609bb26a1a --- /dev/null +++ b/include/llvm/Transforms/Scalar/LoopSimplifyCFG.h @@ -0,0 +1,32 @@ +//===- LoopSimplifyCFG.cpp - Loop CFG Simplification Pass -------*- C++ -*-===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H +#define LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Performs basic CFG simplifications to assist other loop passes. +class LoopSimplifyCFGPass : public PassInfoMixin { +public: + PreservedAnalyses run(Loop &L, AnalysisManager &AM); +}; +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_LOOPSIMPLIFYCFG_H diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index 049b8fba392..32790a63086 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -57,6 +57,7 @@ #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/DCE.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" +#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/Reassociate.h" diff --git a/lib/Passes/PassRegistry.def b/lib/Passes/PassRegistry.def index 039b9d66ed6..9d45890ff14 100644 --- a/lib/Passes/PassRegistry.def +++ b/lib/Passes/PassRegistry.def @@ -136,4 +136,5 @@ LOOP_ANALYSIS("no-op-loop", NoOpLoopAnalysis()) LOOP_PASS("invalidate", InvalidateAllAnalysesPass()) LOOP_PASS("no-op-loop", NoOpLoopPass()) LOOP_PASS("print", PrintLoopPass(dbgs())) +LOOP_PASS("simplify-cfg", LoopSimplifyCFGPass()) #undef LOOP_PASS diff --git a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp index d908dc72391..5b31d248eb9 100644 --- a/lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ b/lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -14,7 +14,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/LoopSimplifyCFG.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -24,47 +24,23 @@ #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" -namespace { -class LoopSimplifyCFG : public LoopPass { -public: - static char ID; // Pass ID, replacement for typeid - LoopSimplifyCFG() : LoopPass(ID) { - initializeLoopSimplifyCFGPass(*PassRegistry::getPassRegistry()); - } - - bool runOnLoop(Loop *L, LPPassManager &) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addPreserved(); - getLoopAnalysisUsage(AU); - } -}; -} - -char LoopSimplifyCFG::ID = 0; -INITIALIZE_PASS_BEGIN(LoopSimplifyCFG, "loop-simplifycfg", "Simplify loop CFG", - false, false) -INITIALIZE_PASS_DEPENDENCY(LoopPass) -INITIALIZE_PASS_END(LoopSimplifyCFG, "loop-simplifycfg", "Simplify loop CFG", - false, false) - -Pass *llvm::createLoopSimplifyCFGPass() { return new LoopSimplifyCFG(); } - -static bool simplifyLoopCFG(Loop *L, DominatorTree *DT, LoopInfo *LI) { +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 Blocks(L->blocks()); + SmallVector Blocks(L.blocks()); for (auto &Block : Blocks) { // Attempt to merge blocks in the trivial case. Don't modify blocks which @@ -74,27 +50,64 @@ static bool simplifyLoopCFG(Loop *L, DominatorTree *DT, LoopInfo *LI) { continue; BasicBlock *Pred = Succ->getSinglePredecessor(); - if (!Pred || !Pred->getSingleSuccessor() || LI->getLoopFor(Pred) != L) + 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); + if (L.getHeader() == Pred) + L.moveToHeader(Succ); + LI.removeBlock(Pred); + MergeBasicBlockIntoOnlyPred(Succ, &DT); Changed = true; } return Changed; } -/// runOnLoop - Perform basic CFG simplifications to assist other loop passes. -/// For now, this only attempts to merge blocks in the trivial case. -bool LoopSimplifyCFG::runOnLoop(Loop *L, LPPassManager &) { - if (skipLoop(L)) - return false; +PreservedAnalyses LoopSimplifyCFGPass::run(Loop &L, AnalysisManager &AM) { + auto &FAM = AM.getResult(L).getManager(); + Function *F = L.getHeader()->getParent(); - DominatorTree *DT = &getAnalysis().getDomTree(); - LoopInfo *LI = &getAnalysis().getLoopInfo(); - return simplifyLoopCFG(L, DT, LI); + auto *LI = FAM.getCachedResult(*F); + auto *DT = FAM.getCachedResult(*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().getDomTree(); + LoopInfo &LI = getAnalysis().getLoopInfo(); + return simplifyLoopCFG(*L, DT, LI); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addPreserved(); + 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(); } diff --git a/lib/Transforms/Scalar/Scalar.cpp b/lib/Transforms/Scalar/Scalar.cpp index b55ab69a55a..d3d6adad9c2 100644 --- a/lib/Transforms/Scalar/Scalar.cpp +++ b/lib/Transforms/Scalar/Scalar.cpp @@ -88,7 +88,7 @@ void llvm::initializeScalarOpts(PassRegistry &Registry) { initializeFloat2IntPass(Registry); initializeLoopDistributePass(Registry); initializeLoopLoadEliminationPass(Registry); - initializeLoopSimplifyCFGPass(Registry); + initializeLoopSimplifyCFGLegacyPassPass(Registry); initializeLoopVersioningPassPass(Registry); } diff --git a/test/Transforms/LoopSimplifyCFG/merge-header.ll b/test/Transforms/LoopSimplifyCFG/merge-header.ll index 2e032ef22eb..cf56d91d07f 100644 --- a/test/Transforms/LoopSimplifyCFG/merge-header.ll +++ b/test/Transforms/LoopSimplifyCFG/merge-header.ll @@ -1,4 +1,5 @@ ; RUN: opt -S -loop-simplifycfg < %s | FileCheck %s +; RUN: opt -S -passes='require,require,loop(simplify-cfg)' < %s | FileCheck %s ; CHECK-LABEL: foo ; CHECK: entry: