diff options
| author | Philip Reames <listmail@philipreames.com> | 2018-03-20 18:43:44 +0000 |
|---|---|---|
| committer | Philip Reames <listmail@philipreames.com> | 2018-03-20 18:43:44 +0000 |
| commit | ce998adf0a8f678b8121e3ce5bb6e46cd3a36d36 (patch) | |
| tree | 90061ff918a60226fc3834c5d26a0aa5fa7ceeb0 /llvm | |
| parent | fced530650414f4f0901567e12b4c6318d70d811 (diff) | |
| download | bcm5719-llvm-ce998adf0a8f678b8121e3ce5bb6e46cd3a36d36.tar.gz bcm5719-llvm-ce998adf0a8f678b8121e3ce5bb6e46cd3a36d36.zip | |
[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.
llvm-svn: 328015
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Analysis/MustExecute.cpp | 87 | ||||
| -rw-r--r-- | llvm/test/Analysis/MustExecute/loop-header.ll | 49 |
2 files changed, 82 insertions, 54 deletions
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp index 3d98a61c0ed..f741b35ab9c 100644 --- a/llvm/lib/Analysis/MustExecute.cpp +++ b/llvm/lib/Analysis/MustExecute.cpp @@ -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::createMustExecutePrinter() { 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, Loop *L, DominatorTree *DT) { 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(); + }; + } } - return false; -} + 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(); + }; + } + } + + + void printInfoComment(const Value &V, formatted_raw_ostream &OS) override { + if (!MustExec.count(&V)) + return; -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(); + 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; } diff --git a/llvm/test/Analysis/MustExecute/loop-header.ll b/llvm/test/Analysis/MustExecute/loop-header.ll index a505e85efa8..b74c3e2a317 100644 --- a/llvm/test/Analysis/MustExecute/loop-header.ll +++ b/llvm/test/Analysis/MustExecute/loop-header.ll @@ -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 |

