[llvm] r328015 - [MustExecute] Use the annotation style printer

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 20 11:43:44 PDT 2018


Author: reames
Date: Tue Mar 20 11:43:44 2018
New Revision: 328015

URL: http://llvm.org/viewvc/llvm-project?rev=328015&view=rev
Log:
[MustExecute] Use the annotation style printer

As suggested in the original review (https://reviews.llvm.org/D44524), use an annotation style printer instead.

Note: The switch from -analyze to -disable-output in tests was driven by the fact that seems to be the idiomatic style used in annoation passes.  I tried to keep both working, but the old style pass API for printers really doesn't make this easy.  It invokes (runOnFunction, print(Module)) repeatedly.  I decided the extra state wasn't worth it given the old pass manager is going away soonish anyway.


Modified:
    llvm/trunk/lib/Analysis/MustExecute.cpp
    llvm/trunk/test/Analysis/MustExecute/loop-header.ll

Modified: llvm/trunk/lib/Analysis/MustExecute.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MustExecute.cpp?rev=328015&r1=328014&r2=328015&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/MustExecute.cpp (original)
+++ llvm/trunk/lib/Analysis/MustExecute.cpp Tue Mar 20 11:43:44 2018
@@ -10,19 +10,19 @@
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/Passes.h"
 #include "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/AssemblyAnnotationWriter.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/FormattedStream.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) {
@@ -34,11 +34,6 @@ namespace {
       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();
-    }
   };
 }
 
@@ -54,7 +49,7 @@ FunctionPass *llvm::createMustExecutePri
   return new MustExecutePrinter();
 }
 
-bool isMustExecuteIn(Instruction &I, Loop *L, DominatorTree *DT) {
+bool isMustExecuteIn(const Instruction &I, Loop *L, DominatorTree *DT) {
   // TODO: move loop specific code to analysis
   //LoopSafetyInfo LSI;
   //computeLoopSafetyInfo(&LSI, L);
@@ -62,41 +57,67 @@ bool isMustExecuteIn(Instruction &I, Loo
   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();
-    };
+/// \brief An assembly annotator class to print must execute information in
+/// comments.
+class MustExecuteAnnotatedWriter : public AssemblyAnnotationWriter {
+  DenseMap<const Value*, SmallVector<Loop*, 4> > MustExec;
+
+public:
+  MustExecuteAnnotatedWriter(const Function &F,
+                             DominatorTree &DT, LoopInfo &LI) {
+    for (auto &I: instructions(F)) {
+      Loop *L = LI.getLoopFor(I.getParent());
+      while (L) {
+        if (isMustExecuteIn(I, L, &DT)) {
+          MustExec[&I].push_back(L);
+        }
+        L = L->getParentLoop();
+      };
+    }
+  }
+  MustExecuteAnnotatedWriter(const Module &M,
+                             DominatorTree &DT, LoopInfo &LI) {
+    for (auto &F : M)
+    for (auto &I: instructions(F)) {
+      Loop *L = LI.getLoopFor(I.getParent());
+      while (L) {
+        if (isMustExecuteIn(I, L, &DT)) {
+          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();
+
+  void printInfoComment(const Value &V, formatted_raw_ostream &OS) override {  
+    if (!MustExec.count(&V))
+      return;
+
+    const auto &Loops = MustExec.lookup(&V);
+    const auto NumLoops = Loops.size();
     if (NumLoops > 1)
-      OS << "\t(mustexec in " << NumLoops << " loops: ";
+      OS << " ; (mustexec in " << NumLoops << " loops: ";
     else
-      OS << "\t(mustexec in: ";
+      OS << " ; (mustexec in: ";
     
     bool first = true;
-    for (const Loop *L : MustExec.lookup(V)) {
+    for (const Loop *L : Loops) {
       if (!first)
         OS << ", ";
       first = false;
       OS << L->getHeader()->getName();
     }
-    OS << ")\n";
+    OS << ")";
   }
-  OS << "\n";
+};
+
+bool MustExecutePrinter::runOnFunction(Function &F) {
+  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+  auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+
+  MustExecuteAnnotatedWriter Writer(F, DT, LI);
+  F.print(dbgs(), &Writer);
+  
+  return false;
 }

Modified: llvm/trunk/test/Analysis/MustExecute/loop-header.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/MustExecute/loop-header.ll?rev=328015&r1=328014&r2=328015&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/MustExecute/loop-header.ll (original)
+++ llvm/trunk/test/Analysis/MustExecute/loop-header.ll Tue Mar 20 11:43:44 2018
@@ -1,12 +1,14 @@
-; RUN: opt -analyze -print-mustexecute %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -disable-output -print-mustexecute %s 2>&1 | FileCheck %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) {
+; CHECK-LABEL: @header_with_icf(
+; CHECK-LABEL:       loop:
+; 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: mustexec
+
 entry:
   br label %loop
 
@@ -22,12 +24,13 @@ 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) {
+define i1 @split_header(i32* noalias %p, i32 %high) {
+; CHECK-LABEL: @split_header(
+; CHECK-LABEL:       loop:
+; 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)
+; CHECK-NOT: mustexec
 entry:
   br label %loop
 
@@ -45,15 +48,19 @@ 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)
+; FIXME: everything in inner loop header should be must execute
+; for outer as well
 define i1 @nested(i32* noalias %p, i32 %high) {
+; CHECK-LABEL: @nested
+; CHECK-LABEL: loop:                                             ; preds = %next
+; CHECK:         %iv = phi i32 [ 0, %entry ], [ %iv.next, %next ]	; (mustexec in: loop)
+; CHECK:         br label %inner_loop	; (mustexec in: loop)
+; CHECK-LABEL: inner_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)
+; CHECK-NOT: mustexec
+
 entry:
   br label %loop
 




More information about the llvm-commits mailing list