[llvm] r328004 - Add an analysis printer for must execute reasoning

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 20 10:09:21 PDT 2018


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"
+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)




More information about the llvm-commits mailing list