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 <typename IRUnitT> 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.
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;
/// 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.
class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
public:
+ typedef RegionInfoBase<RegionTraits<Function>> Base;
+
explicit RegionInfo();
~RegionInfo() override;
+ RegionInfo(RegionInfo &&Arg)
+ : Base(std::move(static_cast<Base &>(Arg))) {}
+ RegionInfo &operator=(RegionInfo &&RHS) {
+ Base::operator=(std::move(static_cast<Base &>(RHS)));
+ return *this;
+ }
+
// updateStatistics - Update statistic about created regions.
void updateStatistics(Region *R) final;
//@}
};
+/// \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<Function> *AM);
+};
+
+/// \brief Printer pass for the \c RegionInfo.
+class RegionInfoPrinterPass {
+ raw_ostream &OS;
+
+public:
+ explicit RegionInfoPrinterPass(raw_ostream &OS);
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "RegionInfoPrinterPass"; }
+};
+
+/// \brief Verifier pass for the \c RegionInfo.
+struct RegionInfoVerifierPass {
+ PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
+
+ static StringRef name() { return "RegionInfoVerifierPass"; }
+};
+
template <>
template <>
inline BasicBlock *
#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"
}
}
+//===----------------------------------------------------------------------===//
+// RegionInfoAnalysis implementation
+//
+
+char RegionInfoAnalysis::PassID;
+
+RegionInfo RegionInfoAnalysis::run(Function &F, AnalysisManager<Function> *AM) {
+ RegionInfo RI;
+ auto *DT = &AM->getResult<DominatorTreeAnalysis>(F);
+ auto *PDT = &AM->getResult<PostDominatorTreeAnalysis>(F);
+ auto *DF = &AM->getResult<DominanceFrontierAnalysis>(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<RegionInfoAnalysis>(F).print(OS);
+
+ return PreservedAnalyses::all();
+}
+
+PreservedAnalyses RegionInfoVerifierPass::run(Function &F,
+ AnalysisManager<Function> *AM) {
+ AM->getResult<RegionInfoAnalysis>(F).verifyAnalysis();
+
+ return PreservedAnalyses::all();
+}
#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"
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())
FUNCTION_PASS("print<postdomtree>", PostDominatorTreePrinterPass(dbgs()))
FUNCTION_PASS("print<domfrontier>", DominanceFrontierPrinterPass(dbgs()))
FUNCTION_PASS("print<loops>", LoopPrinterPass(dbgs()))
+FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(dbgs()))
FUNCTION_PASS("print<scalar-evolution>", ScalarEvolutionPrinterPass(dbgs()))
FUNCTION_PASS("simplify-cfg", SimplifyCFGPass())
FUNCTION_PASS("sroa", SROA())
FUNCTION_PASS("verify", VerifierPass())
FUNCTION_PASS("verify<domtree>", DominatorTreeVerifierPass())
+FUNCTION_PASS("verify<regions>", RegionInfoVerifierPass())
#undef FUNCTION_PASS
#ifndef LOOP_ANALYSIS
; RUN: opt -regions < %s
+; RUN: opt < %s -passes='print<regions>'
+
define i32 @main() nounwind {
entry:
br label %for.cond
; 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<regions>' 2>&1 | FileCheck %s
+
define void @BZ2_blockSort() nounwind {
start:
br label %while
; 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<regions>' 2>&1 | FileCheck %s
+
define void @normal_condition() nounwind {
5:
br label %"0"
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc zeroext i8 @handle_compress() nounwind {
end165:
br i1 1, label %false239, label %true181
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc void @compress() nounwind {
end33:
br i1 1, label %end124, label %lor.lhs.false95
; 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<regions>' 2>&1 | FileCheck %s
+
define void @normal_condition() nounwind {
0:
br label %"1"
; 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<regions>' 2>&1 | FileCheck %s
+
define void @normal_condition() nounwind {
0:
br i1 1, label %"1", label %"4"
; 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<regions>' 2>&1 | FileCheck %s
+
define void @normal_condition() nounwind {
0:
br label %"1"
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc zeroext i8 @handle_compress() nounwind {
entry:
br label %outer
; 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<regions>' 2>&1 | FileCheck %s
+
define void @normal_condition() nounwind {
0:
br label %"1"
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc zeroext i8 @loops_1() nounwind {
entry:
br i1 1, label %outer , label %a
; 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<regions>' 2>&1 | FileCheck %s
+
define void @meread_() nounwind {
entry:
br label %bb23
; 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<regions>' 2>&1 | FileCheck %s
+
define void @a_linear_impl_fig_1() nounwind {
0:
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc zeroext i8 @handle_compress() nounwind {
entry:
br label %outer
; 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<regions>' 2>&1 | FileCheck %s
+
define void @MAIN__() nounwind {
entry:
br label %__label_002001.outer
; 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<regions>' 2>&1 | FileCheck %s
+
define void @a_linear_impl_fig_1() nounwind {
0:
br label %"1"
; 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<regions>' 2>&1 | FileCheck %s
+
define internal fastcc zeroext i8 @handle_compress() nounwind {
entry:
br label %outer
; RUN: opt -regions -analyze < %s | FileCheck %s
+; RUN: opt < %s -passes='print<regions>' 2>&1 | FileCheck %s
; We should not crash if there are some bbs that are not reachable.
define void @f() {