[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