diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index b129e679632..fc1393fc47a 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -27,6 +27,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; + /// \brief A cache of @llvm.assume calls within a function. /// /// This cache provides fast lookup of assumptions within a function by caching @@ -88,6 +93,42 @@ public: } }; +/// \brief A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis { + static char PassID; + +public: + typedef AssumptionCache 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 "AssumptionAnalysis"; } + + AssumptionAnalysis() {} + AssumptionAnalysis(const AssumptionAnalysis &Arg) {} + AssumptionAnalysis(AssumptionAnalysis &&Arg) {} + AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; } + AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; } + + AssumptionCache run(Function &F) { return AssumptionCache(F); } +}; + +/// \brief Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "AssumptionPrinterPass"; } +}; + /// \brief An immutable pass that tracks lazily created \c AssumptionCache /// objects. /// diff --git a/lib/Analysis/AssumptionCache.cpp b/lib/Analysis/AssumptionCache.cpp index da5ba18fc43..f468a43ef0b 100644 --- a/lib/Analysis/AssumptionCache.cpp +++ b/lib/Analysis/AssumptionCache.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Support/Debug.h" using namespace llvm; @@ -73,6 +74,20 @@ void AssumptionCache::registerAssumption(CallInst *CI) { #endif } +char AssumptionAnalysis::PassID; + +PreservedAnalyses AssumptionPrinterPass::run(Function &F, + AnalysisManager *AM) { + AssumptionCache &AC = AM->getResult(F); + + OS << "Cached assumptions for function: " << F.getName() << "\n"; + for (auto &VH : AC.assumptions()) + if (VH) + OS << " " << *cast(VH)->getArgOperand(0) << "\n"; + + return PreservedAnalyses::all(); +} + void AssumptionCacheTracker::FunctionCallbackVH::deleted() { auto I = ACT->AssumptionCaches.find_as(cast(getValPtr())); if (I != ACT->AssumptionCaches.end()) diff --git a/test/Analysis/AssumptionCache/basic.ll b/test/Analysis/AssumptionCache/basic.ll new file mode 100644 index 00000000000..bd4e7b6449f --- /dev/null +++ b/test/Analysis/AssumptionCache/basic.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -disable-output -passes='print' 2>&1 | FileCheck %s + +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" + +declare void @llvm.assume(i1) + +define void @test1(i32 %a) { +; CHECK-LABEL: Cached assumptions for function: test1 +; CHECK-NEXT: icmp ne i32 %{{.*}}, 0 +; CHECK-NEXT: icmp slt i32 %{{.*}}, 0 +; CHECK-NEXT: icmp sgt i32 %{{.*}}, 0 + +entry: + %cond1 = icmp ne i32 %a, 0 + call void @llvm.assume(i1 %cond1) + %cond2 = icmp slt i32 %a, 0 + call void @llvm.assume(i1 %cond2) + %cond3 = icmp sgt i32 %a, 0 + call void @llvm.assume(i1 %cond3) + + ret void +} diff --git a/tools/opt/PassRegistry.def b/tools/opt/PassRegistry.def index 66ee5e56272..b3296aa5ec0 100644 --- a/tools/opt/PassRegistry.def +++ b/tools/opt/PassRegistry.def @@ -50,6 +50,7 @@ CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass()) #ifndef FUNCTION_ANALYSIS #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) #endif +FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis()) FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) @@ -61,6 +62,7 @@ FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) FUNCTION_PASS("no-op-function", NoOpFunctionPass()) FUNCTION_PASS("print", PrintFunctionPass(dbgs())) +FUNCTION_PASS("print", AssumptionPrinterPass(dbgs())) FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) FUNCTION_PASS("print", LoopPrinterPass(dbgs())) FUNCTION_PASS("verify", VerifierPass()) diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index ee515430554..5488059905e 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -15,6 +15,7 @@ //===----------------------------------------------------------------------===// #include "Passes.h" +#include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LoopInfo.h"