Index: include/llvm/Analysis/RegionInfo.h =================================================================== --- include/llvm/Analysis/RegionInfo.h +++ include/llvm/Analysis/RegionInfo.h @@ -47,6 +47,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + // Class to be specialized for different users of RegionInfo // (i.e. BasicBlocks or MachineBasicBlocks). This is only to avoid needing to // pass around an unreasonable number of template parameters. @@ -676,6 +681,22 @@ RegionInfoBase(const RegionInfoBase &) = delete; const RegionInfoBase &operator=(const RegionInfoBase &) = delete; + RegionInfoBase(RegionInfoBase &&Arg) + : DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)), + TopLevelRegion(std::move(Arg.TopLevelRegion)), + BBtoRegion(std::move(Arg.BBtoRegion)) { + Arg.wipe(); + } + RegionInfoBase &operator=(RegionInfoBase &&RHS) { + DT = std::move(RHS.DT); + PDT = std::move(RHS.PDT); + DF = std::move(RHS.DF); + TopLevelRegion = std::move(RHS.TopLevelRegion); + BBtoRegion = std::move(RHS.BBtoRegion); + RHS.wipe(); + return *this; + } + DomTreeT *DT; PostDomTreeT *PDT; DomFrontierT *DF; @@ -687,6 +708,18 @@ /// Map every BB to the smallest region, that contains BB. BBtoRegionMap BBtoRegion; + /// \brief Wipe this region tree's state without releasing any resources. + /// + /// This is essentially a post-move helper only. It leaves the object in an + /// assignable and destroyable state, but otherwise invalid. + void wipe() { + DT = nullptr; + PDT = nullptr; + DF = nullptr; + TopLevelRegion = nullptr; + BBtoRegion.clear(); + } + // Check whether the entries of BBtoRegion for the BBs of region // SR are correct. Triggers an assertion if not. Calls itself recursively for // subregions. @@ -836,10 +869,19 @@ class RegionInfo : public RegionInfoBase> { public: + typedef RegionInfoBase> Base; + explicit RegionInfo(); ~RegionInfo() override; + RegionInfo(RegionInfo &&Arg) + : Base(std::move(static_cast(Arg))) {} + RegionInfo &operator=(RegionInfo &&RHS) { + Base::operator=(std::move(static_cast(RHS))); + return *this; + } + // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; @@ -884,6 +926,40 @@ //@} }; +/// \brief Analysis pass that exposes the \c RegionInfo for a function. +class RegionInfoAnalysis { + static char PassID; + +public: + typedef RegionInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "RegionInfoAnalysis"; } + + RegionInfo run(Function &F, AnalysisManager *AM); +}; + +/// \brief Printer pass for the \c RegionInfo. +class RegionInfoPrinterPass { + raw_ostream &OS; + +public: + explicit RegionInfoPrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "RegionInfoPrinterPass"; } +}; + +/// \brief Verifier pass for the \c RegionInfo. +struct RegionInfoVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "RegionInfoVerifierPass"; } +}; + template <> template <> inline BasicBlock * Index: lib/Analysis/RegionInfo.cpp =================================================================== --- lib/Analysis/RegionInfo.cpp +++ lib/Analysis/RegionInfo.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/RegionInfoImpl.h" #include "llvm/Analysis/RegionIterator.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -180,3 +181,36 @@ } } +//===----------------------------------------------------------------------===// +// RegionInfoAnalysis implementation +// + +char RegionInfoAnalysis::PassID; + +RegionInfo RegionInfoAnalysis::run(Function &F, AnalysisManager *AM) { + RegionInfo RI; + auto *DT = &AM->getResult(F); + auto *PDT = &AM->getResult(F); + auto *DF = &AM->getResult(F); + + RI.recalculate(F, DT, PDT, DF); + return RI; +} + +RegionInfoPrinterPass::RegionInfoPrinterPass(raw_ostream &OS) + : OS(OS) {} + +PreservedAnalyses +RegionInfoPrinterPass::run(Function &F, FunctionAnalysisManager *AM) { + OS << "Region Tree for function: " << F.getName() << "\n"; + AM->getResult(F).print(OS); + + return PreservedAnalyses::all(); +} + +PreservedAnalyses RegionInfoVerifierPass::run(Function &F, + AnalysisManager *AM) { + AM->getResult(F).verifyAnalysis(); + + return PreservedAnalyses::all(); +} Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" #include "llvm/Analysis/ScopedNoAliasAA.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -60,6 +60,7 @@ FUNCTION_ANALYSIS("postdomtree", PostDominatorTreeAnalysis()) FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis()) +FUNCTION_ANALYSIS("regions", RegionInfoAnalysis()) FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) FUNCTION_ANALYSIS("scalar-evolution", ScalarEvolutionAnalysis()) FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) @@ -94,9 +95,11 @@ FUNCTION_PASS("print", PostDominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", DominanceFrontierPrinterPass(dbgs())) FUNCTION_PASS("print", LoopPrinterPass(dbgs())) +FUNCTION_PASS("print", RegionInfoPrinterPass(dbgs())) FUNCTION_PASS("print", ScalarEvolutionPrinterPass(dbgs())) FUNCTION_PASS("simplify-cfg", SimplifyCFGPass()) FUNCTION_PASS("sroa", SROA()) FUNCTION_PASS("verify", VerifierPass()) FUNCTION_PASS("verify", DominatorTreeVerifierPass()) +FUNCTION_PASS("verify", RegionInfoVerifierPass()) #undef FUNCTION_PASS Index: test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll =================================================================== --- test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll +++ test/Analysis/RegionInfo/20100809_bb_not_in_domtree.ll @@ -1,4 +1,6 @@ ; RUN: opt -regions < %s +; RUN: opt < %s -passes='print' + define i32 @main() nounwind { entry: br label %for.cond Index: test/Analysis/RegionInfo/block_sort.ll =================================================================== --- test/Analysis/RegionInfo/block_sort.ll +++ test/Analysis/RegionInfo/block_sort.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @BZ2_blockSort() nounwind { start: br label %while Index: test/Analysis/RegionInfo/cond_loop.ll =================================================================== --- test/Analysis/RegionInfo/cond_loop.ll +++ test/Analysis/RegionInfo/cond_loop.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 5: br label %"0" Index: test/Analysis/RegionInfo/condition_complicated.ll =================================================================== --- test/Analysis/RegionInfo/condition_complicated.ll +++ test/Analysis/RegionInfo/condition_complicated.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { end165: br i1 1, label %false239, label %true181 Index: test/Analysis/RegionInfo/condition_complicated_2.ll =================================================================== --- test/Analysis/RegionInfo/condition_complicated_2.ll +++ test/Analysis/RegionInfo/condition_complicated_2.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc void @compress() nounwind { end33: br i1 1, label %end124, label %lor.lhs.false95 Index: test/Analysis/RegionInfo/condition_forward_edge.ll =================================================================== --- test/Analysis/RegionInfo/condition_forward_edge.ll +++ test/Analysis/RegionInfo/condition_forward_edge.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" Index: test/Analysis/RegionInfo/condition_same_exit.ll =================================================================== --- test/Analysis/RegionInfo/condition_same_exit.ll +++ test/Analysis/RegionInfo/condition_same_exit.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br i1 1, label %"1", label %"4" Index: test/Analysis/RegionInfo/condition_simple.ll =================================================================== --- test/Analysis/RegionInfo/condition_simple.ll +++ test/Analysis/RegionInfo/condition_simple.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" Index: test/Analysis/RegionInfo/exit_in_condition.ll =================================================================== --- test/Analysis/RegionInfo/exit_in_condition.ll +++ test/Analysis/RegionInfo/exit_in_condition.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer Index: test/Analysis/RegionInfo/loop_with_condition.ll =================================================================== --- test/Analysis/RegionInfo/loop_with_condition.ll +++ test/Analysis/RegionInfo/loop_with_condition.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @normal_condition() nounwind { 0: br label %"1" Index: test/Analysis/RegionInfo/loops_1.ll =================================================================== --- test/Analysis/RegionInfo/loops_1.ll +++ test/Analysis/RegionInfo/loops_1.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @loops_1() nounwind { entry: br i1 1, label %outer , label %a Index: test/Analysis/RegionInfo/loops_2.ll =================================================================== --- test/Analysis/RegionInfo/loops_2.ll +++ test/Analysis/RegionInfo/loops_2.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @meread_() nounwind { entry: br label %bb23 Index: test/Analysis/RegionInfo/mix_1.ll =================================================================== --- test/Analysis/RegionInfo/mix_1.ll +++ test/Analysis/RegionInfo/mix_1.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @a_linear_impl_fig_1() nounwind { 0: Index: test/Analysis/RegionInfo/nested_loops.ll =================================================================== --- test/Analysis/RegionInfo/nested_loops.ll +++ test/Analysis/RegionInfo/nested_loops.ll @@ -5,6 +5,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer Index: test/Analysis/RegionInfo/next.ll =================================================================== --- test/Analysis/RegionInfo/next.ll +++ test/Analysis/RegionInfo/next.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @MAIN__() nounwind { entry: br label %__label_002001.outer Index: test/Analysis/RegionInfo/paper.ll =================================================================== --- test/Analysis/RegionInfo/paper.ll +++ test/Analysis/RegionInfo/paper.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define void @a_linear_impl_fig_1() nounwind { 0: br label %"1" Index: test/Analysis/RegionInfo/two_loops_same_header.ll =================================================================== --- test/Analysis/RegionInfo/two_loops_same_header.ll +++ test/Analysis/RegionInfo/two_loops_same_header.ll @@ -4,6 +4,8 @@ ; RUN: opt -regions -print-region-style=bb -analyze < %s 2>&1 | FileCheck -check-prefix=BBIT %s ; RUN: opt -regions -print-region-style=rn -analyze < %s 2>&1 | FileCheck -check-prefix=RNIT %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s + define internal fastcc zeroext i8 @handle_compress() nounwind { entry: br label %outer Index: test/Analysis/RegionInfo/unreachable_bb.ll =================================================================== --- test/Analysis/RegionInfo/unreachable_bb.ll +++ test/Analysis/RegionInfo/unreachable_bb.ll @@ -1,4 +1,5 @@ ; RUN: opt -regions -analyze < %s | FileCheck %s +; RUN: opt < %s -passes='print' 2>&1 | FileCheck %s ; We should not crash if there are some bbs that are not reachable. define void @f() {