[llvm] r328004 - Add an analysis printer for must execute reasoning
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 29 10:15:36 PDT 2018
On 03/28/2018 04:16 PM, David Blaikie wrote:
>
>
> On Tue, Mar 20, 2018 at 10:11 AM Philip Reames via llvm-commits
> <llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>> wrote:
>
> Author: reames
> Date: Tue Mar 20 10:09:21 2018
> New Revision: 328004
>
> URL: http://llvm.org/viewvc/llvm-project?rev=328004&view=rev
> Log:
> Add an analysis printer for must execute reasoning
>
> Many of our loop passes make use of so called "must execute" or
> "guaranteed to execute" facts to prove the legality of code
> motion. The basic notion is that we know (by assumption) an
> instruction didn't fault at it's original location, so if the
> location we move it to is strictly post dominated by the original,
> then we can't have introduced a new fault.
>
> At the moment, the testing for this logic is somewhat adhoc and
> done mostly through LICM. Since I'm working on that code, I want
> to improve the testing. This patch is the first step in that
> direction. It doesn't actually test the variant used by the loop
> passes - I need to move that to the Analysis library first - but
> instead exercises an alternate implementation used by SCEV. (I
> plan on merging both implementations.)
>
> Note: I'll be replacing the printing logic within this with an
> annotation based version in the near future. Anna suggested this
> in review, and it seems like a strictly better format.
>
> Differential Revision: https://reviews.llvm.org/D44524
>
>
> Added:
> llvm/trunk/lib/Analysis/MustExecute.cpp
> llvm/trunk/test/Analysis/MustExecute/
> llvm/trunk/test/Analysis/MustExecute/loop-header.ll
> Modified:
> llvm/trunk/include/llvm/Analysis/Passes.h
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/include/llvm/LinkAllPasses.h
> llvm/trunk/lib/Analysis/Analysis.cpp
> llvm/trunk/lib/Analysis/CMakeLists.txt
>
> Modified: llvm/trunk/include/llvm/Analysis/Passes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=328004&r1=328003&r2=328004&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/Passes.h (original)
> +++ llvm/trunk/include/llvm/Analysis/Passes.h Tue Mar 20 10:09:21 2018
> @@ -96,6 +96,14 @@ namespace llvm {
> //
> FunctionPass *createMemDerefPrinter();
>
> +
> //===--------------------------------------------------------------------===//
> + //
> + // createMustExecutePrinter - This pass collects information
> about which
> + // instructions within a loop are guaranteed to execute if the
> loop header is
> + // entered and prints it with -analyze.
> + //
> + FunctionPass *createMustExecutePrinter();
> +
> }
>
> #endif
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=328004&r1=328003&r2=328004&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Mar 20 10:09:21
> 2018
> @@ -268,6 +268,7 @@ void initializeMergedLoadStoreMotionLega
> void initializeMetaRenamerPass(PassRegistry&);
> void initializeModuleDebugInfoPrinterPass(PassRegistry&);
> void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);
> +void initializeMustExecutePrinterPass(PassRegistry&);
> void initializeNameAnonGlobalLegacyPassPass(PassRegistry&);
> void initializeNaryReassociateLegacyPassPass(PassRegistry&);
> void initializeNewGVNLegacyPassPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=328004&r1=328003&r2=328004&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Mar 20 10:09:21 2018
> @@ -207,6 +207,7 @@ namespace {
> (void) llvm::createRewriteSymbolsPass();
> (void) llvm::createStraightLineStrengthReducePass();
> (void) llvm::createMemDerefPrinter();
> + (void) llvm::createMustExecutePrinter();
> (void) llvm::createFloat2IntPass();
> (void) llvm::createEliminateAvailableExternallyPass();
> (void) llvm::createScalarizeMaskedMemIntrinPass();
>
> Modified: llvm/trunk/lib/Analysis/Analysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=328004&r1=328003&r2=328004&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/Analysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/Analysis.cpp Tue Mar 20 10:09:21 2018
> @@ -65,6 +65,7 @@ void llvm::initializeAnalysis(PassRegist
> initializeMemoryDependenceWrapperPassPass(Registry);
> initializeModuleDebugInfoPrinterPass(Registry);
> initializeModuleSummaryIndexWrapperPassPass(Registry);
> + initializeMustExecutePrinterPass(Registry);
> initializeObjCARCAAWrapperPassPass(Registry);
> initializeOptimizationRemarkEmitterWrapperPassPass(Registry);
> initializePostDominatorTreeWrapperPassPass(Registry);
>
> Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=328004&r1=328003&r2=328004&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
> +++ llvm/trunk/lib/Analysis/CMakeLists.txt Tue Mar 20 10:09:21 2018
> @@ -58,6 +58,7 @@ add_llvm_library(LLVMAnalysis
> MemorySSAUpdater.cpp
> ModuleDebugInfoPrinter.cpp
> ModuleSummaryAnalysis.cpp
> + MustExecute.cpp
> ObjCARCAliasAnalysis.cpp
> ObjCARCAnalysisUtils.cpp
> ObjCARCInstKind.cpp
>
> Added: llvm/trunk/lib/Analysis/MustExecute.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MustExecute.cpp?rev=328004&view=auto
> ==============================================================================
> --- llvm/trunk/lib/Analysis/MustExecute.cpp (added)
> +++ llvm/trunk/lib/Analysis/MustExecute.cpp Tue Mar 20 10:09:21 2018
> @@ -0,0 +1,102 @@
> +//===- MustExecute.cpp - Printer for isGuaranteedToExecute
> ----------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/Analysis/LoopInfo.h"
> +#include "llvm/Analysis/Passes.h"
> +#include "llvm/Analysis/ValueTracking.h"
> +#include "llvm/IR/DataLayout.h"
> +#include "llvm/IR/InstIterator.h"
> +#include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/Support/ErrorHandling.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Transforms/Utils/LoopUtils.h"
>
>
> This looks like a circular/invalid dependency? Transforms depend on
> Analysis, not the other way around?
>
> Would be great to get this fixed - happy to help, if you've some ideas.
>
> Moving the whole LoopUtils isn't immediately possible, its
> implementation depends on BasicBlockUtils. (& also many of these
> utilities seem more for mutation, which isn't relevant to Analysis -
> so maybe it needs to be split up?)
I think this is just a stale header include. I'm building to confirm
now and if so will remove it.
>
> +using namespace llvm;
> +
> +namespace {
> + struct MustExecutePrinter : public FunctionPass {
> + DenseMap<Value*, SmallVector<Loop*, 4> > MustExec;
> + SmallVector<Value *, 4> Ordering;
> +
> + static char ID; // Pass identification, replacement for typeid
> + MustExecutePrinter() : FunctionPass(ID) {
> + initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());
> + }
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.setPreservesAll();
> + AU.addRequired<DominatorTreeWrapperPass>();
> + AU.addRequired<LoopInfoWrapperPass>();
> + }
> + bool runOnFunction(Function &F) override;
> + void print(raw_ostream &OS, const Module * = nullptr) const
> override;
> + void releaseMemory() override {
> + MustExec.clear();
> + Ordering.clear();
> + }
> + };
> +}
> +
> +char MustExecutePrinter::ID = 0;
> +INITIALIZE_PASS_BEGIN(MustExecutePrinter, "print-mustexecute",
> + "Instructions which execute on loop entry",
> false, true)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
> +INITIALIZE_PASS_END(MustExecutePrinter, "print-mustexecute",
> + "Instructions which execute on loop entry",
> false, true)
> +
> +FunctionPass *llvm::createMustExecutePrinter() {
> + return new MustExecutePrinter();
> +}
> +
> +bool isMustExecuteIn(Instruction &I, Loop *L, DominatorTree *DT) {
> + // TODO: move loop specific code to analysis
> + //LoopSafetyInfo LSI;
> + //computeLoopSafetyInfo(&LSI, L);
> + //return isGuaranteedToExecute(I, DT, L, &LSI);
> + return isGuaranteedToExecuteForEveryIteration(&I, L);
> +}
> +
> +bool MustExecutePrinter::runOnFunction(Function &F) {
> + auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
> + auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
> + for (auto &I: instructions(F)) {
> + Loop *L = LI.getLoopFor(I.getParent());
> + while (L) {
> + if (isMustExecuteIn(I, L, &DT)) {
> + if (!MustExec.count(&I))
> + Ordering.push_back(&I);
> + MustExec[&I].push_back(L);
> + }
> + L = L->getParentLoop();
> + };
> + }
> + return false;
> +}
> +
> +void MustExecutePrinter::print(raw_ostream &OS, const Module *M)
> const {
> + OS << "The following are guaranteed to execute (for the
> respective loops):\n";
> + for (Value *V: Ordering) {
> + V->printAsOperand(OS);
> + auto NumLoops = MustExec.lookup(V).size();
> + if (NumLoops > 1)
> + OS << "\t(mustexec in " << NumLoops << " loops: ";
> + else
> + OS << "\t(mustexec in: ";
> +
> + bool first = true;
> + for (const Loop *L : MustExec.lookup(V)) {
> + if (!first)
> + OS << ", ";
> + first = false;
> + OS << L->getHeader()->getName();
> + }
> + OS << ")\n";
> + }
> + OS << "\n";
> +}
>
> Added: llvm/trunk/test/Analysis/MustExecute/loop-header.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/MustExecute/loop-header.ll?rev=328004&view=auto
> ==============================================================================
> --- llvm/trunk/test/Analysis/MustExecute/loop-header.ll (added)
> +++ llvm/trunk/test/Analysis/MustExecute/loop-header.ll Tue Mar 20
> 10:09:21 2018
> @@ -0,0 +1,80 @@
> +; RUN: opt -analyze -print-mustexecute %s
> +
> +; CHECK: Printing analysis 'Instructions which execute on loop
> entry' for function 'header_with_icf':
> +; CHECK: The following are guaranteed to execute (for the
> respective loops):
> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
> (mustexec in: loop)
> +; CHECK: %v = load i32, i32* %p (mustexec in: loop)
> +; CHECK: call void @maythrow_and_use(i32 %v) (mustexec in: loop)
> +; CHECK-NOT: add
> +define i1 @header_with_icf(i32* noalias %p, i32 %high) {
> +entry:
> + br label %loop
> +
> +loop:
> + %iv = phi i32 [0, %entry], [%iv.next, %loop]
> + %v = load i32, i32* %p
> + call void @maythrow_and_use(i32 %v)
> + %iv.next = add nsw nuw i32 %iv, 1
> + %exit.test = icmp slt i32 %iv, %high
> + br i1 %exit.test, label %exit, label %loop
> +
> +exit:
> + ret i1 false
> +}
> +
> +; CHECK: Printing analysis 'Instructions which execute on loop
> entry' for function 'test':
> +; CHECK: The following are guaranteed to execute (for the
> respective loops):
> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ]
> (mustexec in: loop)
> +; CHECK: %v = load i32, i32* %p (mustexec in: loop)
> +; CHECK: br label %next (mustexec in: loop)
> +define i1 @test(i32* noalias %p, i32 %high) {
> +entry:
> + br label %loop
> +
> +loop:
> + %iv = phi i32 [0, %entry], [%iv.next, %next]
> + %v = load i32, i32* %p
> + br label %next
> +next:
> + call void @maythrow_and_use(i32 %v)
> + %iv.next = add nsw nuw i32 %iv, 1
> + %exit.test = icmp slt i32 %iv, %high
> + br i1 %exit.test, label %exit, label %loop
> +
> +exit:
> + ret i1 false
> +}
> +
> +; CHECK: Printing analysis 'Instructions which execute on loop
> entry' for function 'nested':
> +; CHECK: The following are guaranteed to execute (for the
> respective loops):
> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ]
> (mustexec in: loop)
> +; CHECK: br label %inner_loop (mustexec in: loop)
> +; FIXME: These three are also must execute for the outer loop.
> +; CHECK: %v = load i32, i32* %p (mustexec in: inner_loop)
> +; CHECK: %inner.test = icmp eq i32 %v, 0 (mustexec in:
> inner_loop)
> +; CHECK: br i1 %inner.test, label %inner_loop, label %next
> (mustexec in: inner_loop)
> +define i1 @nested(i32* noalias %p, i32 %high) {
> +entry:
> + br label %loop
> +
> +loop:
> + %iv = phi i32 [0, %entry], [%iv.next, %next]
> + br label %inner_loop
> +
> +inner_loop:
> + %v = load i32, i32* %p
> + %inner.test = icmp eq i32 %v, 0
> + br i1 %inner.test, label %inner_loop, label %next
> +
> +next:
> + call void @maythrow_and_use(i32 %v)
> + %iv.next = add nsw nuw i32 %iv, 1
> + %exit.test = icmp slt i32 %iv, %high
> + br i1 %exit.test, label %exit, label %loop
> +
> +exit:
> + ret i1 false
> +}
> +
> +
> +declare void @maythrow_and_use(i32)
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180329/859e122c/attachment-0001.html>
More information about the llvm-commits
mailing list